@Override
  public MergeAppend appendFile(DataFile file) {
    add(file);
    return this;
  }
@TestTemplate
  public void testManifestEntryFieldIdsForChangedPartitionSpecForV1Table() {
    Snapshot snap = commit(table, table.newAppend().appendFile(FILE_A), branch);

    long commitId = snap.snapshotId();
    validateSnapshot(null, snap, 1, FILE_A);
    TableMetadata base = readMetadata();

    assertThat(snap.allManifests(table.io())).hasSize(1);
    ManifestFile initialManifest = snap.allManifests(table.io()).get(0);
    validateManifest(
        initialManifest,
        dataSeqs(1L),
        fileSeqs(1L),
        ids(commitId),
        files(FILE_A),
        statuses(Status.ADDED));

    // build the new spec using the table's schema, which uses fresh IDs
    PartitionSpec newSpec =
        PartitionSpec.builderFor(base.schema()).bucket("id", 8).bucket("data", 8).build();

    // commit the new partition spec to the table manually
    table.ops().commit(base, base.updatePartitionSpec(newSpec));
    V2Assert.assertEquals(
        "Last sequence number should be 1", 1, readMetadata().lastSequenceNumber());
    V1Assert.assertEquals(
        "Table should end with last-sequence-number 0", 0, readMetadata().lastSequenceNumber());

    // create a new with the table's current spec
    DataFile newFile =
        DataFiles.builder(table.spec())
            .withPath("/path/to/data-x.parquet")
            .withFileSizeInBytes(10)
            .withPartitionPath("id_bucket=1/data_bucket=1")
            .withRecordCount(1)
            .build();

    Snapshot committedSnapshot = commit(table, table.newAppend().appendFile(newFile), branch);

    V2Assert.assertEquals(
        "Snapshot sequence number should be 2", 2, committedSnapshot.sequenceNumber());
    V2Assert.assertEquals(
        "Last sequence number should be 2", 2, readMetadata().lastSequenceNumber());
    V1Assert.assertEquals(
        "Table should end with last-sequence-number 0", 0, readMetadata().lastSequenceNumber());

    assertThat(committedSnapshot.allManifests(table.io())).hasSize(2);

    // new manifest comes first
    validateManifest(
        committedSnapshot.allManifests(table.io()).get(0),
        dataSeqs(2L),
        fileSeqs(2L),
        ids(committedSnapshot.snapshotId()),
        files(newFile),
        statuses(Status.ADDED));

    assertThat(committedSnapshot.allManifests(table.io()))
        .as("Second manifest should be the initial manifest with the old spec")
        .element(1)
        .isEqualTo(initialManifest);

    // field ids of manifest entries in two manifests with different specs of the same source field
    // should be different
    ManifestEntry<DataFile> entry =
        ManifestFiles.read(committedSnapshot.allManifests(table.io()).get(0), FILE_IO)
            .entries()
            .iterator()
            .next();
    Types.NestedField field =
        ((PartitionData) entry.file().partition()).getPartitionType().fields().get(0);
    assertThat(field.fieldId()).isEqualTo(1000);
    assertThat(field.name()).isEqualTo("id_bucket");
    field = ((PartitionData) entry.file().partition()).getPartitionType().fields().get(1);
    assertThat(field.fieldId()).isEqualTo(1001);
    assertThat(field.name()).isEqualTo("data_bucket");

    entry =
        ManifestFiles.read(committedSnapshot.allManifests(table.io()).get(1), FILE_IO)
            .entries()
            .iterator()
            .next();
    field = ((PartitionData) entry.file().partition()).getPartitionType().fields().get(0);
    assertThat(field.fieldId()).isEqualTo(1000);
    assertThat(field.name()).isEqualTo("data_bucket");
  }