From 0be9fc1e3c82f7941f4577d9fbfb70aaee127233 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 20 Apr 2023 21:00:02 +0200 Subject: [PATCH 01/26] Events notification system for Nessie - VersionStore changes --- .../quarkus/cli/ITExportImport.java | 7 +- .../quarkus/cli/ITExportImportPersist.java | 14 +- .../quarkus/cli/ITNessieInfo.java | 13 +- .../quarkus/cli/ITNessieInfoPersist.java | 9 +- .../services/impl/NamespaceApiImpl.java | 4 +- .../services/impl/TreeApiImpl.java | 15 +- .../persist/adapter/DatabaseAdapter.java | 18 +- .../adapter/MetadataRewriteParams.java | 6 + .../adapter/spi/AbstractDatabaseAdapter.java | 42 +- .../adapter/spi/TracingDatabaseAdapter.java | 15 +- .../NonTransactionalDatabaseAdapter.java | 96 ++- .../persist/store/PersistVersionStore.java | 105 ++- .../persist/tests/AbstractCommitLogScan.java | 43 +- .../tests/AbstractCommitScenarios.java | 67 +- .../versioned/persist/tests/AbstractDiff.java | 6 +- .../persist/tests/AbstractEvents.java | 62 +- .../tests/AbstractGetNamedReferences.java | 35 +- .../persist/tests/AbstractManyCommits.java | 2 +- .../persist/tests/AbstractManyKeys.java | 115 ++-- .../tests/AbstractMergeTransplant.java | 52 +- .../persist/tests/AbstractRefLog.java | 2 +- .../persist/tests/AbstractReferences.java | 104 +-- .../persist/tests/AbstractRepositories.java | 4 +- .../persist/tx/TxDatabaseAdapter.java | 96 ++- .../projectnessie/versioned/CommitResult.java | 35 + .../versioned/EventsVersionStore.java | 223 ++++++ .../org/projectnessie/versioned/LazyPut.java | 63 ++ .../projectnessie/versioned/MergeResult.java | 20 +- .../versioned/MetricsVersionStore.java | 59 +- .../java/org/projectnessie/versioned/Put.java | 5 +- .../versioned/ReferenceAssignedResult.java | 33 + .../versioned/ReferenceCreatedResult.java | 31 + .../versioned/ReferenceDeletedResult.java | 31 + .../org/projectnessie/versioned/Result.java | 22 + .../projectnessie/versioned/ResultType.java | 25 + .../versioned/TracingVersionStore.java | 100 ++- .../projectnessie/versioned/VersionStore.java | 19 +- .../versioned/TestEventsVersionStore.java | 636 ++++++++++++++++++ .../versioned/TestMetricsVersionStore.java | 63 +- .../versioned/TestTracingVersionStore.java | 90 ++- ...java => TestedTracingStoreInvocation.java} | 39 +- .../commontests/AbstractCommitLogicTests.java | 165 +++-- .../AbstractRepositoryLogicTests.java | 15 +- .../storage/common/logic/CommitLogic.java | 4 +- .../storage/common/logic/CommitLogicImpl.java | 4 +- .../common/logic/ReferenceLogicImpl.java | 8 +- .../common/logic/RepositoryLogicImpl.java | 7 +- .../common/logic/TestCommitConflicts.java | 111 +-- .../common/logic/TestIndexesLogicImpl.java | 9 +- .../common/logic/TestReferenceIndexes.java | 14 +- .../versionstore/BaseCommitHelper.java | 13 +- .../BaseMergeTransplantIndividual.java | 9 + .../BaseMergeTransplantSquash.java | 9 + .../storage/versionstore/CommitImpl.java | 45 +- .../storage/versionstore/ContentMapping.java | 12 +- .../versioned/storage/versionstore/Merge.java | 2 + .../versionstore/MergeIndividualImpl.java | 7 +- .../storage/versionstore/MergeSquashImpl.java | 7 +- .../storage/versionstore/Transplant.java | 2 + .../TransplantIndividualImpl.java | 5 +- .../versionstore/TransplantSquashImpl.java | 5 +- .../versionstore/VersionStoreImpl.java | 46 +- .../versionstore/TestContentMapping.java | 6 +- .../storage/versionstore/TestRefMapping.java | 24 +- .../versionstore/TestVersionStoreImpl.java | 4 +- .../versioned/tests/AbstractAssign.java | 4 +- .../versioned/tests/AbstractCommitLog.java | 9 +- .../versioned/tests/AbstractCommits.java | 10 +- .../versioned/tests/AbstractContents.java | 16 +- .../tests/AbstractDuplicateTable.java | 8 +- .../tests/AbstractNamespaceValidation.java | 15 +- .../tests/AbstractNestedVersionStore.java | 8 +- .../tests/AbstractNoNamespaceValidation.java | 8 +- .../tests/AbstractReferenceNotFound.java | 7 + .../versioned/tests/AbstractReferences.java | 7 +- .../versioned/tests/AbstractSingleBranch.java | 11 +- .../versioned/tests/AbstractTransplant.java | 289 ++++++-- .../versioned/tests/CommitBuilder.java | 3 +- .../transfer/AbstractExportImport.java | 6 +- .../AbstractITCommitLogOptimization.java | 7 +- .../versioned/transfer/BaseExportImport.java | 44 +- 81 files changed, 2619 insertions(+), 792 deletions(-) create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceAssignedResult.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceCreatedResult.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceDeletedResult.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/Result.java create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/ResultType.java create mode 100644 versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java rename versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/{TestedTraceingStoreInvocation.java => TestedTracingStoreInvocation.java} (73%) diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java index d8168ff3e17..a661ea235d7 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java @@ -42,10 +42,11 @@ import org.projectnessie.quarkus.cli.ExportRepository.Format; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.CommitMetaSerializer; -import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.ReferenceAlreadyExistsException; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.persist.adapter.CommitLogEntry; import org.projectnessie.versioned.persist.adapter.ContentId; import org.projectnessie.versioned.persist.adapter.DatabaseAdapter; import org.projectnessie.versioned.persist.adapter.ImmutableCommitParams; @@ -232,7 +233,7 @@ private static void populateRepository(DatabaseAdapter adapter) ContentKey key = ContentKey.of("namespace123", "table123"); String namespaceId = UUID.randomUUID().toString(); String tableId = UUID.randomUUID().toString(); - Hash main = + CommitResult main = adapter.commit( ImmutableCommitParams.builder() .toBranch(branchMain) @@ -256,7 +257,7 @@ private static void populateRepository(DatabaseAdapter adapter) .toStoreOnReferenceState( IcebergTable.of("meta", 42, 43, 44, 45, tableId)))) .build()); - adapter.create(branchFoo, main); + adapter.create(branchFoo, main.getCommit().getHash()); adapter.commit( ImmutableCommitParams.builder() .toBranch(branchFoo) diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImportPersist.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImportPersist.java index bf15e16b051..0aa97778b23 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImportPersist.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImportPersist.java @@ -50,8 +50,8 @@ import org.projectnessie.versioned.storage.common.indexes.StoreKey; import org.projectnessie.versioned.storage.common.logic.CommitLogic; import org.projectnessie.versioned.storage.common.logic.ReferenceLogic; +import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.objtypes.ContentValueObj; -import org.projectnessie.versioned.storage.common.persist.ObjId; import org.projectnessie.versioned.storage.common.persist.Persist; import org.projectnessie.versioned.storage.common.persist.Reference; import org.projectnessie.versioned.store.DefaultStoreWorker; @@ -251,7 +251,7 @@ private void populateRepository(Persist persist) throws Exception { soft.assertThat(persist.storeObj(valueMain)).isTrue(); StoreKey key = key("namespace123", "table123"); - ObjId main = + CommitObj main = commitLogic.doCommit( newCommitBuilder() .parentCommitId(EMPTY_OBJ_ID) @@ -260,14 +260,14 @@ private void populateRepository(Persist persist) throws Exception { .headers(EMPTY_COMMIT_HEADERS) .build(), emptyList()); - referenceLogic.assignReference(refMain, requireNonNull(main)); + referenceLogic.assignReference(refMain, requireNonNull(main).id()); - Reference refFoo = referenceLogic.createReference("refs/heads/branch-foo", main); + Reference refFoo = referenceLogic.createReference("refs/heads/branch-foo", main.id()); soft.assertThat(persist.storeObj(valueFoo)).isTrue(); - ObjId foo = + CommitObj foo = commitLogic.doCommit( newCommitBuilder() - .parentCommitId(main) + .parentCommitId(main.id()) .addAdds( commitAdd( key, @@ -279,6 +279,6 @@ private void populateRepository(Persist persist) throws Exception { .headers(EMPTY_COMMIT_HEADERS) .build(), emptyList()); - referenceLogic.assignReference(refFoo, requireNonNull(foo)); + referenceLogic.assignReference(refFoo, requireNonNull(foo).id()); } } diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java index 35c62c27bd6..a7b2adfe189 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java @@ -54,11 +54,14 @@ public void testNoAncestorHash(LaunchResult result, DatabaseAdapter adapter) { public void testMainHash(QuarkusMainLauncher launcher, DatabaseAdapter adapter) throws ReferenceNotFoundException, ReferenceConflictException { Hash hash = - adapter.commit( - ImmutableCommitParams.builder() - .toBranch(BranchName.of("main")) - .commitMetaSerialized(ByteString.copyFrom(new byte[] {1, 2, 3})) - .build()); + adapter + .commit( + ImmutableCommitParams.builder() + .toBranch(BranchName.of("main")) + .commitMetaSerialized(ByteString.copyFrom(new byte[] {1, 2, 3})) + .build()) + .getCommit() + .getHash(); LaunchResult result = launcher.launch("info"); assertThat(result.getOutput()).contains(hash.asString()); diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfoPersist.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfoPersist.java index 28f79f3a97a..dae2cb43abf 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfoPersist.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfoPersist.java @@ -38,7 +38,7 @@ import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.exceptions.RefConditionFailedException; import org.projectnessie.versioned.storage.common.exceptions.RefNotFoundException; -import org.projectnessie.versioned.storage.common.persist.ObjId; +import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.persist.Persist; @QuarkusMainTest @@ -71,7 +71,7 @@ public void testMainHash(QuarkusMainLauncher launcher, Persist persist) ObjNotFoundException, RefNotFoundException, RefConditionFailedException { - ObjId head = + CommitObj head = commitLogic(persist) .doCommit( newCommitBuilder() @@ -81,12 +81,13 @@ public void testMainHash(QuarkusMainLauncher launcher, Persist persist) .build(), emptyList()); referenceLogic(persist) - .assignReference(reference("refs/heads/main", EMPTY_OBJ_ID, false), requireNonNull(head)); + .assignReference( + reference("refs/heads/main", EMPTY_OBJ_ID, false), requireNonNull(head).id()); LaunchResult result = launcher.launch("info"); assertThat(result.getOutput()) .contains("Repository created:") - .contains("Default branch head commit ID: " + head) + .contains("Default branch head commit ID: " + head.id()) .contains("Default branch commit count: 1") .contains("Version-store type: " + MONGODB.name()) .contains("Default branch: main") diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java index 473a05c9270..ceb7684c2df 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java @@ -365,6 +365,8 @@ private Hash commit( .rewriteSingle(CommitMeta.fromMessage(commitMsg)), Collections.singletonList(contentOperation), validator, - (k, c) -> {}); + (k, c) -> {}) + .getCommit() + .getHash(); } } diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java index d614110a0bc..844560b16e8 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java @@ -111,6 +111,7 @@ import org.projectnessie.versioned.GetNamedRefsParams.RetrieveOptions; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.KeyEntry; +import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MergeConflictException; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.NamedRef; @@ -275,7 +276,7 @@ public Reference createReference( check.checkAndThrow(); try { - Hash hash = getStore().create(namedReference, toHash(targetHash, false)); + Hash hash = getStore().create(namedReference, toHash(targetHash, false)).getHash(); return RefUtil.toReference(namedReference, hash); } catch (ReferenceNotFoundException e) { throw new NessieReferenceNotFoundException(e.getMessage(), e); @@ -346,7 +347,7 @@ public Reference deleteReference( startAccessCheck().canDeleteReference(ref).checkAndThrow(); - Hash deletedAthash = getStore().delete(ref, toHash(expectedHash, true)); + Hash deletedAthash = getStore().delete(ref, toHash(expectedHash, true)).getHash(); return RefUtil.toReference(ref, deletedAthash); } catch (ReferenceNotFoundException e) { throw new NessieReferenceNotFoundException(e.getMessage(), e); @@ -482,8 +483,8 @@ private ImmutableLogEntry commitToLogEntry(boolean fetchAll, Commit commit) { .forEach( op -> { ContentKey key = op.getKey(); - if (op instanceof Put) { - Content content = ((Put) op).getValue(); + if (op instanceof LazyPut) { + Content content = ((LazyPut) op).getValue(); logEntry.addOperations(Operation.Put.of(key, content)); } if (op instanceof Delete) { @@ -590,6 +591,7 @@ public MergeResponse transplantCommitsIntoBranch( MergeResult result = getStore() .transplant( + BranchName.of(fromRefName), targetBranch, into, transplants, @@ -652,6 +654,7 @@ public MergeResponse mergeRefIntoBranch( MergeResult result = getStore() .merge( + BranchName.of(fromRefName), toHash(fromRefName, fromHash), targetBranch, into, @@ -950,7 +953,9 @@ public CommitResponse commitMultipleOperations( () -> null, (key, cid) -> { commitResponse.addAddedContents(addedContent(key, cid)); - }); + }) + .getCommit() + .getHash(); return commitResponse.targetBranch(Branch.of(branch, newHash.asString())).build(); } catch (ReferenceNotFoundException e) { diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/DatabaseAdapter.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/DatabaseAdapter.java index 5782c6fc598..85643fee295 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/DatabaseAdapter.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/DatabaseAdapter.java @@ -26,6 +26,7 @@ import javax.annotation.Nonnull; import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Diff; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; @@ -33,7 +34,10 @@ import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.RefLogNotFoundException; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; @@ -148,7 +152,7 @@ Stream keys(Hash commit, KeyFilterPredicate keyFilter) * branch due to a conflicting change or if the expected hash in {@link * CommitParams#getToBranch()}is not its expected hEAD */ - Hash commit(CommitParams commitParams) + CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException; /** @@ -218,11 +222,11 @@ Stream> namedRefs(GetNamedRefsParams params) * @param target The already existing named reference with an optional hash on that branch. This * parameter can be {@code null} for the edge case when the default branch is re-created after * it has been dropped. - * @return the current HEAD of the created branch or tag + * @return A {@link ReferenceCreatedResult} containing the head of the created reference * @throws ReferenceAlreadyExistsException if the reference {@code ref} already exists. * @throws ReferenceNotFoundException if {@code target} does not exist. */ - Hash create(NamedRef ref, Hash target) + ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException; /** @@ -231,12 +235,12 @@ Hash create(NamedRef ref, Hash target) * @param reference named-reference to delete. If a value for the hash is specified, it must be * equal to the current HEAD. * @param expectedHead if present, {@code reference}'s current HEAD must be equal to this value - * @return head of deleted reference + * @return A {@link ReferenceDeletedResult} containing the head of the deleted reference * @throws ReferenceNotFoundException if the named reference in {@code reference} does not exist. * @throws ReferenceConflictException if the named reference's HEAD is not equal to the expected * HEAD */ - Hash delete(NamedRef reference, Optional expectedHead) + ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException; /** @@ -245,13 +249,15 @@ Hash delete(NamedRef reference, Optional expectedHead) * @param assignee named reference to re-assign * @param expectedHead if present, {@code assignee}'s current HEAD must be equal to this value * @param assignTo commit to update {@code assignee}'s HEAD to + * @return A {@link ReferenceAssignedResult} containing the previous and current head of the + * reference * @throws ReferenceNotFoundException if either the named reference in {@code assignTo} or the * commit on that reference, if specified, does not exist or if the named reference specified * in {@code assignee} does not exist. * @throws ReferenceConflictException if the HEAD of the named reference {@code assignee} is not * equal to the expected HEAD */ - void assign(NamedRef assignee, Optional expectedHead, Hash assignTo) + ReferenceAssignedResult assign(NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException; /** diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java index 9e2c944cb87..1bb1cb0a1b2 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java @@ -19,11 +19,15 @@ import org.immutables.value.Value; import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; +import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.MergeType; import org.projectnessie.versioned.MetadataRewriter; public interface MetadataRewriteParams extends ToBranchParams { + /** Branch to merge or transplant from. */ + BranchName getFromBranch(); + /** Whether to keep the individual commits and do not squash the commits to merge. */ @Value.Default default boolean keepIndividualCommits() { @@ -47,6 +51,8 @@ default MergeType getDefaultMergeType() { @SuppressWarnings({"override", "UnusedReturnValue"}) interface Builder extends ToBranchParams.Builder { + B fromBranch(BranchName fromBranch); + B keepIndividualCommits(boolean keepIndividualCommits); B defaultMergeType(MergeType defaultMergeType); diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java index a888ed375ea..72494936132 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java @@ -349,6 +349,7 @@ protected Hash mergeAttempt( Consumer branchCommits, Consumer newKeyLists, Consumer writtenCommits, + Consumer addedCommits, MergeParams mergeParams, ImmutableMergeResult.Builder mergeResult) throws ReferenceNotFoundException, ReferenceConflictException { @@ -411,6 +412,7 @@ protected Hash mergeAttempt( mergeParams, mergeResult, writtenCommits, + addedCommits, singletonList(commitsToMergeChronological.get(0).getHash())); } @@ -430,6 +432,7 @@ protected Hash transplantAttempt( Consumer branchCommits, Consumer newKeyLists, Consumer writtenCommits, + Consumer addedCommits, TransplantParams transplantParams, ImmutableMergeResult.Builder mergeResult) throws ReferenceNotFoundException, ReferenceConflictException { @@ -499,6 +502,7 @@ protected Hash transplantAttempt( transplantParams, mergeResult, writtenCommits, + addedCommits, emptyList()); } @@ -513,6 +517,7 @@ protected Hash mergeTransplantCommon( MetadataRewriteParams params, ImmutableMergeResult.Builder mergeResult, Consumer writtenCommits, + Consumer addedCommits, List additionalParents) throws ReferenceConflictException, ReferenceNotFoundException { @@ -588,13 +593,9 @@ protected Hash mergeTransplantCommon( result); } - if (params.isDryRun()) { - return toHead; - } - if (params.keepIndividualCommits()) { // re-apply commits in 'sequenceToTransplant' onto 'targetBranch' - toHead = + Hash newHead = copyCommits( ctx, timeInMicros, @@ -602,15 +603,19 @@ protected Hash mergeTransplantCommon( commitsToMergeChronological, newKeyLists, params.getUpdateCommitMetadata(), - mergePredicate); - - // Write commits + mergePredicate, + addedCommits); + + if (!params.isDryRun()) { + // Write commits + writeMultipleCommits(ctx, commitsToMergeChronological); + commitsToMergeChronological.stream() + .peek(writtenCommits) + .map(CommitLogEntry::getHash) + .forEach(branchCommits); + toHead = newHead; + } - writeMultipleCommits(ctx, commitsToMergeChronological); - commitsToMergeChronological.stream() - .peek(writtenCommits) - .map(CommitLogEntry::getHash) - .forEach(branchCommits); } else { CommitLogEntry squashed = squashCommits( @@ -624,8 +629,11 @@ protected Hash mergeTransplantCommon( additionalParents); if (squashed != null) { - writtenCommits.accept(squashed); - toHead = squashed.getHash(); + addedCommits.accept(squashed); + if (!params.isDryRun()) { + writtenCommits.accept(squashed); + toHead = squashed.getHash(); + } } } return toHead; @@ -2192,7 +2200,8 @@ protected Hash copyCommits( List commitsChronological, Consumer newKeyLists, MetadataRewriter rewriteMetadata, - Predicate includeKeyPredicate) + Predicate includeKeyPredicate, + Consumer addedCommits) throws ReferenceNotFoundException, ReferenceConflictException { int parentsPerCommit = config.getParentsPerCommit(); @@ -2265,6 +2274,7 @@ protected Hash copyCommits( commitsChronological.remove(i); } + addedCommits.accept(newEntry); targetHead = newEntry.getHash(); } return targetHead; diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TracingDatabaseAdapter.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TracingDatabaseAdapter.java index 2d8160d1b06..fbcf28e2064 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TracingDatabaseAdapter.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TracingDatabaseAdapter.java @@ -26,13 +26,17 @@ import javax.annotation.Nonnull; import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.RefLogNotFoundException; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.persist.adapter.CommitLogEntry; @@ -131,7 +135,7 @@ public Stream keys(Hash commit, KeyFilterPredicate keyFilter) } @Override - public Hash commit(CommitParams commitParams) + public CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException { try (Traced ignore = trace("commit").tag(TAG_REF, commitParams.getToBranch().getName())) { return delegate.commit(commitParams); @@ -175,7 +179,7 @@ public Stream> namedRefs(GetNamedRefsParams params) } @Override - public Hash create(NamedRef ref, Hash target) + public ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException { try (Traced ignore = trace("create").tag(TAG_REF, ref.getName()).tag(TAG_HASH, target.asString())) { @@ -184,7 +188,7 @@ public Hash create(NamedRef ref, Hash target) } @Override - public Hash delete(NamedRef reference, Optional expectedHead) + public ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException { try (Traced ignore = trace("delete").tag(TAG_REF, reference.getName())) { return delegate.delete(reference, expectedHead); @@ -192,11 +196,12 @@ public Hash delete(NamedRef reference, Optional expectedHead) } @Override - public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo) + public ReferenceAssignedResult assign( + NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException { try (Traced ignore = trace("assign").tag(TAG_HASH, assignTo.asString()).tag(TAG_REF, assignee.getName())) { - delegate.assign(assignee, expectedHead, assignTo); + return delegate.assign(assignee, expectedHead, assignTo); } } diff --git a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java index c025cc50fec..c9e307e76bc 100644 --- a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java +++ b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java @@ -62,16 +62,25 @@ import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.ImmutableCommitResult; import org.projectnessie.versioned.ImmutableMergeResult; +import org.projectnessie.versioned.ImmutableReferenceAssignedResult; +import org.projectnessie.versioned.ImmutableReferenceCreatedResult; +import org.projectnessie.versioned.ImmutableReferenceDeletedResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.RefLogNotFoundException; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.TagName; import org.projectnessie.versioned.VersionStoreException; import org.projectnessie.versioned.persist.adapter.CommitLogEntry; @@ -230,7 +239,10 @@ public MergeResult merge(MergeParams mergeParams) mergeParams.getToBranch(), CasOpVariant.COMMIT, (ctx, refHead, branchCommits, newKeyLists) -> { - ImmutableMergeResult.Builder mergeResult = MergeResult.builder(); + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceBranch(mergeParams.getFromBranch()); mergeResultHolder.set(mergeResult); Hash currentHead = Hash.of(refHead.getHash()); @@ -246,6 +258,7 @@ public MergeResult merge(MergeParams mergeParams) branchCommits, newKeyLists, writtenCommits::add, + mergeResult::addAddedCommits, mergeParams, mergeResult); @@ -290,7 +303,10 @@ public MergeResult transplant(TransplantParams transplantParams) transplantParams.getToBranch(), CasOpVariant.COMMIT, (ctx, refHead, branchCommits, newKeyLists) -> { - ImmutableMergeResult.Builder mergeResult = MergeResult.builder(); + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceBranch(transplantParams.getFromBranch()); mergeResultHolder.set(mergeResult); Hash currentHead = Hash.of(refHead.getHash()); @@ -306,6 +322,7 @@ public MergeResult transplant(TransplantParams transplantParams) branchCommits, newKeyLists, writtenCommits::add, + mergeResult::addAddedCommits, transplantParams, mergeResult); @@ -337,16 +354,22 @@ public MergeResult transplant(TransplantParams transplantParams) } @Override - public Hash commit(CommitParams commitParams) + public CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException { try { - return casOpLoop( + + AtomicReference> commitResultHolder = + new AtomicReference<>(); + + casOpLoop( "commit", commitParams.getToBranch(), CasOpVariant.COMMIT, (ctx, refHead, branchCommits, newKeyLists) -> { Hash currentHead = Hash.of(refHead.getHash()); + ImmutableCommitResult.Builder commitResult = CommitResult.builder(); + long timeInMicros = config.currentTimeInMicros(); CommitLogEntry newBranchCommit = @@ -355,6 +378,9 @@ public Hash commit(CommitParams commitParams) branchCommits.accept(newHead); + commitResult.targetBranch(commitParams.getToBranch()).commit(newBranchCommit); + commitResultHolder.set(commitResult); + return casOpResult( refHead, newHead, @@ -369,6 +395,12 @@ public Hash commit(CommitParams commitParams) () -> commitConflictMessage( "Retry-Failure", commitParams.getToBranch(), commitParams.getExpectedHead())); + + ImmutableCommitResult.Builder commitResult = + Objects.requireNonNull( + commitResultHolder.get(), "Internal error, commit-result builder not set."); + + return commitResult.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -377,14 +409,21 @@ public Hash commit(CommitParams commitParams) } @Override - public Hash create(NamedRef ref, Hash target) + public ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException { try { - return casOpLoop( + AtomicReference resultHolder = + new AtomicReference<>(); + + casOpLoop( "createRef", ref, CasOpVariant.CREATE_REF, (ctx, refHead, branchCommits, newKeyLists) -> { + ImmutableReferenceCreatedResult.Builder result = + ImmutableReferenceCreatedResult.builder().namedRef(ref); + resultHolder.set(result); + if (refHead != null) { throw referenceAlreadyExists(ref); } @@ -400,6 +439,8 @@ public Hash create(NamedRef ref, Hash target) Hash newHead = hash; + result.hash(newHead); + return casOpResult( refHead, hash, @@ -413,6 +454,12 @@ public Hash create(NamedRef ref, Hash target) () -> ReferenceCreatedEvent.builder().currentHash(newHead).ref(ref)); }, () -> createConflictMessage("Retry-Failure", ref, target)); + + ImmutableReferenceCreatedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceAlreadyExistsException | ReferenceNotFoundException | RuntimeException e) { throw e; } catch (Exception e) { @@ -421,17 +468,26 @@ public Hash create(NamedRef ref, Hash target) } @Override - public Hash delete(NamedRef reference, Optional expectedHead) + public ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException { try { - return casOpLoop( + AtomicReference resultHolder = + new AtomicReference<>(); + + casOpLoop( "deleteRef", reference, CasOpVariant.DELETE_REF, (ctx, refHead, branchCommits, newKeyLists) -> { + ImmutableReferenceDeletedResult.Builder result = + ImmutableReferenceDeletedResult.builder().namedRef(reference); + resultHolder.set(result); + Hash currentHead = Hash.of(refHead.getHash()); verifyExpectedHash(currentHead, reference, expectedHead); + result.hash(currentHead); + return casOpResult( refHead, currentHead, @@ -445,6 +501,12 @@ public Hash delete(NamedRef reference, Optional expectedHead) () -> ReferenceDeletedEvent.builder().currentHash(currentHead).ref(reference)); }, () -> deleteConflictMessage("Retry-Failure", reference, expectedHead)); + + ImmutableReferenceDeletedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -453,19 +515,29 @@ public Hash delete(NamedRef reference, Optional expectedHead) } @Override - public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo) + public ReferenceAssignedResult assign( + NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException { try { + AtomicReference resultHolder = + new AtomicReference<>(); + casOpLoop( "assignRef", assignee, CasOpVariant.REF_UPDATE, (ctx, refHead, branchCommits, newKeyLists) -> { + ImmutableReferenceAssignedResult.Builder result = + ImmutableReferenceAssignedResult.builder().namedRef(assignee); + resultHolder.set(result); + Hash beforeAssign = Hash.of(refHead.getHash()); verifyExpectedHash(beforeAssign, assignee, expectedHead); validateHashExists(ctx, assignTo); + result.previousHash(beforeAssign).currentHash(assignTo); + return casOpResult( refHead, assignTo, @@ -484,6 +556,12 @@ public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo .previousHash(beforeAssign)); }, () -> assignConflictMessage("Retry-Failure", assignee, expectedHead, assignTo)); + + ImmutableReferenceAssignedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { diff --git a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java index 31f72e93983..df78653b009 100644 --- a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java +++ b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java @@ -44,15 +44,18 @@ import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.CommitMetaSerializer; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.Diff; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ImmutableCommit; +import org.projectnessie.versioned.ImmutableCommitResult; import org.projectnessie.versioned.ImmutableMergeResult; import org.projectnessie.versioned.ImmutableRefLogDetails; import org.projectnessie.versioned.ImmutableRepositoryInformation; import org.projectnessie.versioned.KeyEntry; +import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MergeConflictException; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MergeType; @@ -64,7 +67,10 @@ import org.projectnessie.versioned.RefLogDetails; import org.projectnessie.versioned.RefLogNotFoundException; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.RepositoryInformation; @@ -124,13 +130,13 @@ public Hash noAncestorHash() { } @Override - public Hash commit( + public CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional expectedHead, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @Nonnull @jakarta.annotation.Nonnull List operations, @Nonnull @jakarta.annotation.Nonnull Callable validator, - BiConsumer addedContents) + @Nonnull @jakarta.annotation.Nonnull BiConsumer addedContents) throws ReferenceNotFoundException, ReferenceConflictException { ImmutableCommitParams.Builder commitAttempt = @@ -172,11 +178,12 @@ public Hash commit( } } - return databaseAdapter.commit(commitAttempt.build()); + return storeCommitResult(databaseAdapter.commit(commitAttempt.build())); } @Override public MergeResult transplant( + BranchName sourceBranch, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -192,6 +199,7 @@ public MergeResult transplant( MergeResult adapterMergeResult = databaseAdapter.transplant( TransplantParams.builder() + .fromBranch(sourceBranch) .toBranch(targetBranch) .expectedHead(referenceHash) .sequenceToTransplant(sequenceToTransplant) @@ -213,6 +221,7 @@ public MergeResult transplant( @Override public MergeResult merge( + BranchName fromBranch, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -228,6 +237,7 @@ public MergeResult merge( MergeResult adapterMergeResult = databaseAdapter.merge( MergeParams.builder() + .fromBranch(fromBranch) .toBranch(toBranch) .expectedHead(expectedHash) .mergeFromHash(fromHash) @@ -262,10 +272,25 @@ private static Map mergeTypesForKeys( })); } + private CommitResult storeCommitResult(CommitResult adapterCommitResult) { + CommitLogEntry logEntry = adapterCommitResult.getCommit(); + ImmutableCommit.Builder commit = + Commit.builder().hash(logEntry.getHash()).commitMeta(commitMetaFromLogEntry(logEntry)); + logEntry.getParents().stream().findFirst().ifPresent(commit::parentHash); + enhancerForCommitLog(true).accept(commit, logEntry); + ImmutableCommitResult.Builder storeResult = + ImmutableCommitResult.builder() + .targetBranch(adapterCommitResult.getTargetBranch()) + .commit(commit.build()); + return storeResult.build(); + } + private MergeResult storeMergeResult( MergeResult adapterMergeResult, boolean fetchAdditionalInfo) { ImmutableMergeResult.Builder storeResult = ImmutableMergeResult.builder() + .resultType(adapterMergeResult.getResultType()) + .sourceBranch(adapterMergeResult.getSourceBranch()) .targetBranch(adapterMergeResult.getTargetBranch()) .effectiveTargetHash(adapterMergeResult.getEffectiveTargetHash()) .commonAncestor(adapterMergeResult.getCommonAncestor()) @@ -275,28 +300,45 @@ private MergeResult storeMergeResult( .wasSuccessful(adapterMergeResult.wasSuccessful()) .details(adapterMergeResult.getDetails()); - BiConsumer enhancer = - enhancerForCommitLog(fetchAdditionalInfo); - - Function mapper = - logEntry -> { - ImmutableCommit.Builder commit = Commit.builder(); - commit.hash(logEntry.getHash()).commitMeta(commitMetaFromLogEntry(logEntry)); - enhancer.accept(commit, logEntry); - return commit.build(); - }; - - if (adapterMergeResult.getSourceCommits() != null) { - adapterMergeResult.getSourceCommits().stream() - .map(mapper) - .forEach(storeResult::addSourceCommits); + { + BiConsumer enhancer = + enhancerForCommitLog(fetchAdditionalInfo); + + Function mapper = + logEntry -> { + ImmutableCommit.Builder commit = Commit.builder(); + commit.hash(logEntry.getHash()).commitMeta(commitMetaFromLogEntry(logEntry)); + enhancer.accept(commit, logEntry); + return commit.build(); + }; + + if (adapterMergeResult.getSourceCommits() != null) { + adapterMergeResult.getSourceCommits().stream() + .map(mapper) + .forEach(storeResult::addSourceCommits); + } + if (adapterMergeResult.getTargetCommits() != null) { + adapterMergeResult.getTargetCommits().stream() + .map(mapper) + .forEach(storeResult::addTargetCommits); + } } - if (adapterMergeResult.getTargetCommits() != null) { - adapterMergeResult.getTargetCommits().stream() - .map(mapper) - .forEach(storeResult::addTargetCommits); + { + BiConsumer enhancer = enhancerForCommitLog(true); + + adapterMergeResult.getAddedCommits().stream() + .map( + logEntry -> { + ImmutableCommit.Builder commit = + Commit.builder() + .hash(logEntry.getHash()) + .commitMeta(commitMetaFromLogEntry(logEntry)); + logEntry.getParents().stream().findFirst().ifPresent(commit::parentHash); + enhancer.accept(commit, logEntry); + return commit.build(); + }) + .forEach(storeResult::addAddedCommits); } - return storeResult.build(); } @@ -320,19 +362,19 @@ public ByteString squash(List metadata) { } @Override - public void assign(NamedRef ref, Optional expectedHash, Hash targetHash) + public ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, Hash targetHash) throws ReferenceNotFoundException, ReferenceConflictException { - databaseAdapter.assign(ref, expectedHash, targetHash); + return databaseAdapter.assign(ref, expectedHash, targetHash); } @Override - public Hash create(NamedRef ref, Optional targetHash) + public ReferenceCreatedResult create(NamedRef ref, Optional targetHash) throws ReferenceNotFoundException, ReferenceAlreadyExistsException { return databaseAdapter.create(ref, targetHash.orElseGet(databaseAdapter::noAncestorHash)); } @Override - public Hash delete(NamedRef ref, Optional hash) + public ReferenceDeletedResult delete(NamedRef ref, Optional hash) throws ReferenceNotFoundException, ReferenceConflictException { return databaseAdapter.delete(ref, hash); } @@ -473,12 +515,11 @@ private BiConsumer enhancerForCommitLog .forEach( put -> commitBuilder.addOperations( - Put.of( + LazyPut.of( put.getKey(), - STORE_WORKER.valueFromStore( - put.getPayload(), - put.getValue(), - () -> getGlobalContents.apply(put))))); + put.getPayload(), + put.getValue(), + () -> getGlobalContents.apply(put)))); }; } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java index e218d9c4877..0be13ee33a2 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java @@ -155,7 +155,7 @@ private void prepareReferences( for (int branchNum = 0; branchNum < numBranches; branchNum++) { BranchName branchName = branch.apply(branchNum); - Hash head = databaseAdapter.create(branchName, root); + Hash head = databaseAdapter.create(branchName, root).getHash(); head = addCommits(numCommits, branchName, head, committed); setRefHead.accept(branchName, head); @@ -199,25 +199,28 @@ private Hash addCommits( byte payload = (byte) payloadForContent(c); head = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(branchName) - .expectedHead(Optional.of(head)) - .commitMetaSerialized( - ByteString.copyFromUtf8( - "commit #" - + commitNum - + " in " - + branchName.getName() - + " of " - + numCommits)) - .addPuts( - KeyWithBytes.of( - key, - cid, - payload, - DefaultStoreWorker.instance().toStoreOnReferenceState(c))) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(branchName) + .expectedHead(Optional.of(head)) + .commitMetaSerialized( + ByteString.copyFromUtf8( + "commit #" + + commitNum + + " in " + + branchName.getName() + + " of " + + numCommits)) + .addPuts( + KeyWithBytes.of( + key, + cid, + payload, + DefaultStoreWorker.instance().toStoreOnReferenceState(c))) + .build()) + .getCommit() + .getHash(); committed.accept(head); } return head; diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java index 68ddebc84b9..18e5f17254c 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java @@ -126,12 +126,15 @@ void commitRenameTable(RenameTable param) throws Exception { IntFunction performDummyCommit = i -> { try { - return databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(ByteString.copyFromUtf8("dummy commit meta " + i)) - .addUnchanged(dummyKey) - .build()); + return databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(ByteString.copyFromUtf8("dummy commit meta " + i)) + .addUnchanged(dummyKey) + .build()) + .getCommit() + .getHash(); } catch (ReferenceNotFoundException | ReferenceConflictException e) { throw new RuntimeException(e); } @@ -158,7 +161,7 @@ void commitRenameTable(RenameTable param) throws Exception { contentId, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(initialContent))); - Hash hashInitial = databaseAdapter.commit(commit.build()); + Hash hashInitial = databaseAdapter.commit(commit.build()).getCommit().getHash(); List beforeRename = IntStream.range(0, param.afterInitialCommits) @@ -176,7 +179,7 @@ void commitRenameTable(RenameTable param) throws Exception { contentId, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(renamContent))); - Hash hashRename = databaseAdapter.commit(commit.build()); + Hash hashRename = databaseAdapter.commit(commit.build()).getCommit().getHash(); List beforeDelete = IntStream.range(0, param.afterRenameCommits) @@ -188,7 +191,7 @@ void commitRenameTable(RenameTable param) throws Exception { .toBranch(branch) .commitMetaSerialized(ByteString.copyFromUtf8("delete table")) .addDeletes(newKey); - Hash hashDelete = databaseAdapter.commit(commit.build()); + Hash hashDelete = databaseAdapter.commit(commit.build()).getCommit().getHash(); List afterDelete = IntStream.range(0, param.afterDeleteCommits) @@ -278,7 +281,7 @@ void commit(int tablesPerCommit) throws Exception { (byte) payloadForContent(c), DefaultStoreWorker.instance().toStoreOnReferenceState(c))); } - Hash head = databaseAdapter.commit(commit.build()); + Hash head = databaseAdapter.commit(commit.build()).getCommit().getHash(); for (int commitNum = 0; commitNum < 3; commitNum++) { commit = @@ -298,7 +301,7 @@ void commit(int tablesPerCommit) throws Exception { DefaultStoreWorker.instance().toStoreOnReferenceState(newContent))); } - Hash newHead = databaseAdapter.commit(commit.build()); + Hash newHead = databaseAdapter.commit(commit.build()).getCommit().getHash(); assertThat(newHead).isNotEqualTo(head); head = newHead; } @@ -437,25 +440,35 @@ public void smallEmbeddedKeyLists( Hash commitNation = mine.commit( - ImmutableCommitParams.builder() - .toBranch(branchName) - .expectedHead(Optional.of(head)) - .commitMetaSerialized(ByteString.copyFromUtf8("commit nation")) - .addPuts( - KeyWithBytes.of( - keyNation, idNation, (byte) payloadForContent(onRefNation), stateNation)) - .build()); + ImmutableCommitParams.builder() + .toBranch(branchName) + .expectedHead(Optional.of(head)) + .commitMetaSerialized(ByteString.copyFromUtf8("commit nation")) + .addPuts( + KeyWithBytes.of( + keyNation, + idNation, + (byte) payloadForContent(onRefNation), + stateNation)) + .build()) + .getCommit() + .getHash(); Hash commitRegion = mine.commit( - ImmutableCommitParams.builder() - .toBranch(branchName) - .expectedHead(Optional.of(commitNation)) - .commitMetaSerialized(ByteString.copyFromUtf8("commit region")) - .addPuts( - KeyWithBytes.of( - keyRegion, idRegion, (byte) payloadForContent(onRefRegion), stateRegion)) - .build()); + ImmutableCommitParams.builder() + .toBranch(branchName) + .expectedHead(Optional.of(commitNation)) + .commitMetaSerialized(ByteString.copyFromUtf8("commit region")) + .addPuts( + KeyWithBytes.of( + keyRegion, + idRegion, + (byte) payloadForContent(onRefRegion), + stateRegion)) + .build()) + .getCommit() + .getHash(); List nonExistentKey = Collections.singletonList(ContentKey.of("non_existent")); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java index 9dbeb1dd7d7..f2c55a17e86 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java @@ -51,7 +51,9 @@ void diff() throws Exception { BranchName branch = BranchName.of("branch"); Hash initialHash = - databaseAdapter.create(branch, databaseAdapter.hashOnReference(main, Optional.empty())); + databaseAdapter + .create(branch, databaseAdapter.hashOnReference(main, Optional.empty())) + .getHash(); Hash[] commits = new Hash[3]; for (int i = 0; i < commits.length; i++) { @@ -68,7 +70,7 @@ void diff() throws Exception { (byte) payloadForContent(c), DefaultStoreWorker.instance().toStoreOnReferenceState(c))); } - commits[i] = databaseAdapter.commit(commit.build()); + commits[i] = databaseAdapter.commit(commit.build()).getCommit().getHash(); } try (Stream diff = diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java index 088c68fe5dd..8ef6024ef5a 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java @@ -173,12 +173,15 @@ public void eventAssignRef( ByteString meta = ByteString.copyFromUtf8("foo bar baz"); Hash committed = - adapter.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(meta) - .addPuts(put) - .build()); + adapter + .commit( + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(meta) + .addPuts(put) + .build()) + .getCommit() + .getHash(); events.events.clear(); @@ -220,12 +223,15 @@ public void eventCommit( ByteString meta = ByteString.copyFromUtf8("foo bar baz"); Hash committed = - adapter.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(meta) - .addPuts(put) - .build()); + adapter + .commit( + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(meta) + .addPuts(put) + .build()) + .getCommit() + .getHash(); assertThat(events.events) .hasSize(1) @@ -275,12 +281,15 @@ public void eventMerge( BranchName source = BranchName.of("events-merge"); adapter.create(source, adapter.noAncestorHash()); Hash committed = - adapter.commit( - ImmutableCommitParams.builder() - .toBranch(source) - .commitMetaSerialized(meta) - .addPuts(put) - .build()); + adapter + .commit( + ImmutableCommitParams.builder() + .toBranch(source) + .commitMetaSerialized(meta) + .addPuts(put) + .build()) + .getCommit() + .getHash(); events.events.clear(); @@ -289,6 +298,7 @@ public void eventMerge( adapter.merge( MergeParams.builder() .mergeFromHash(committed) + .fromBranch(source) .toBranch(main) .updateCommitMetadata(updater) .build()); @@ -347,12 +357,15 @@ public void eventTransplant( BranchName source = BranchName.of("events-transplant"); adapter.create(source, adapter.noAncestorHash()); Hash committed = - adapter.commit( - ImmutableCommitParams.builder() - .toBranch(source) - .commitMetaSerialized(meta) - .addPuts(put) - .build()); + adapter + .commit( + ImmutableCommitParams.builder() + .toBranch(source) + .commitMetaSerialized(meta) + .addPuts(put) + .build()) + .getCommit() + .getHash(); events.events.clear(); @@ -362,6 +375,7 @@ public void eventTransplant( TransplantParams.builder() .addSequenceToTransplant(committed) .updateCommitMetadata(updater) + .fromBranch(source) .toBranch(main) .build()); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java index 27220fde199..5802feba2f0 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java @@ -287,9 +287,9 @@ public void fromNoAncestor() throws Exception { Hash main10 = mainHash; Hash branch2Parent = mainParent; - Hash branch2Hash = databaseAdapter.create(branch2, main10); + Hash branch2Hash = databaseAdapter.create(branch2, main10).getHash(); Hash tag2Parent = mainParent; - Hash tag2Hash = databaseAdapter.create(tag2, main10); + Hash tag2Hash = databaseAdapter.create(tag2, main10).getHash(); // same expectations as above, but include branch2 + tag2 // - common ancestor of branch2 + tag2 is the 100th commit on 'main' @@ -350,9 +350,9 @@ public void fromNoAncestor() throws Exception { // Create branch2+tag3 at branch2 Hash branch2plus42 = branch2Hash; - Hash branch3Hash = databaseAdapter.create(branch3, branch2plus42); + Hash branch3Hash = databaseAdapter.create(branch3, branch2plus42).getHash(); Hash branch3Parent = branch2Parent; - Hash tag3Hash = databaseAdapter.create(tag3, branch2plus42); + Hash tag3Hash = databaseAdapter.create(tag3, branch2plus42).getHash(); Hash tag3Parent = branch2Parent; // Add 42 commits to branch3 @@ -387,18 +387,21 @@ private ByteString commitMetaFor(NamedRef ref, int num) { } private Hash dummyCommit(BranchName branch, Hash expectedHash, int num) throws Exception { - return databaseAdapter.commit( - ImmutableCommitParams.builder() - .commitMetaSerialized(commitMetaFor(branch, num)) - .toBranch(branch) - .expectedHead(Optional.of(expectedHash)) - .addPuts( - KeyWithBytes.of( - SOME_KEY, - ContentId.of(SOME_CONTENT_ID), - (byte) 42, - ByteString.copyFromUtf8("dummy content"))) - .build()); + return databaseAdapter + .commit( + ImmutableCommitParams.builder() + .commitMetaSerialized(commitMetaFor(branch, num)) + .toBranch(branch) + .expectedHead(Optional.of(expectedHash)) + .addPuts( + KeyWithBytes.of( + SOME_KEY, + ContentId.of(SOME_CONTENT_ID), + (byte) 42, + ByteString.copyFromUtf8("dummy content"))) + .build()) + .getCommit() + .getHash(); } private void verifyReferences(ExpectedNamedReference... references) diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java index aa631289d20..0e6e16e6b29 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java @@ -84,7 +84,7 @@ void manyCommits(int numCommits) throws Exception { fixed, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(c))); - Hash hash = databaseAdapter.commit(commit.build()); + Hash hash = databaseAdapter.commit(commit.build()).getCommit().getHash(); commits[i] = hash; } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java index 0afc1c26117..5c537bdcee6 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java @@ -201,17 +201,19 @@ void enhanceKeyListWithCommitId( ContentKey key = ContentKey.of("k" + i + "-" + longString); Hash hash = da.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(meta) - .addPuts( - KeyWithBytes.of( - key, - ContentId.of("c" + i), - (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), - DefaultStoreWorker.instance() - .toStoreOnReferenceState(onRef("r" + i, "c" + i)))) - .build()); + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(meta) + .addPuts( + KeyWithBytes.of( + key, + ContentId.of("c" + i), + (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), + DefaultStoreWorker.instance() + .toStoreOnReferenceState(onRef("r" + i, "c" + i)))) + .build()) + .getCommit() + .getHash(); keyToCommit.put(key, hash); } @@ -260,17 +262,19 @@ void enhanceKeyListWithCommitId( ContentKey key = ContentKey.of("pre-fix-" + i); Hash hash = da.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(meta) - .addPuts( - KeyWithBytes.of( - key, - ContentId.of("c" + i), - (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), - DefaultStoreWorker.instance() - .toStoreOnReferenceState(onRef("pf" + i, "cpf" + i)))) - .build()); + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(meta) + .addPuts( + KeyWithBytes.of( + key, + ContentId.of("c" + i), + (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), + DefaultStoreWorker.instance() + .toStoreOnReferenceState(onRef("pf" + i, "cpf" + i)))) + .build()) + .getCommit() + .getHash(); keyToCommit.put(key, hash); } @@ -327,17 +331,20 @@ void pointContentKeyLookups( keyNum++, estimatedTotalKeyLength -= assumedKeyEntryLen) { OnRefOnly val = valueGen.apply(keyNum); head = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(branch) - .commitMetaSerialized(ByteString.EMPTY) - .addPuts( - KeyWithBytes.of( - keyGen.apply(keyNum), - ContentId.of(val.getId()), - (byte) payloadForContent(val), - val.serialized())) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(branch) + .commitMetaSerialized(ByteString.EMPTY) + .addPuts( + KeyWithBytes.of( + keyGen.apply(keyNum), + ContentId.of(val.getId()), + (byte) payloadForContent(val), + val.serialized())) + .build()) + .getCommit() + .getHash(); } for (int i = 0; i < keyNum; i++) { @@ -492,11 +499,14 @@ private static Hash makeEmptyCommits( Hash head = null; for (int i = 0; i < commitCount; i++) { head = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(toBranch) - .commitMetaSerialized(ByteString.EMPTY) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(toBranch) + .commitMetaSerialized(ByteString.EMPTY) + .build()) + .getCommit() + .getHash(); } Preconditions.checkNotNull(head); return head; @@ -594,19 +604,22 @@ private void testManyKeysProgressive(List names, DatabaseAdapter databas for (String name : names) { ContentKey key = ContentKey.of(name); head = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(main) - .commitMetaSerialized(ByteString.copyFromUtf8("foo")) - .expectedHead(Optional.of(head)) - .addPuts( - KeyWithBytes.of( - key, - ContentId.of("id-" + name), - (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), - DefaultStoreWorker.instance() - .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + name)))) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(main) + .commitMetaSerialized(ByteString.copyFromUtf8("foo")) + .expectedHead(Optional.of(head)) + .addPuts( + KeyWithBytes.of( + key, + ContentId.of("id-" + name), + (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), + DefaultStoreWorker.instance() + .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + name)))) + .build()) + .getCommit() + .getHash(); activeKeys.add(key); } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java index 20c750a1c28..71174460831 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java @@ -47,6 +47,7 @@ import org.projectnessie.versioned.MergeResult.KeyDetails; import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.persist.adapter.CommitLogEntry; import org.projectnessie.versioned.persist.adapter.ContentAndState; import org.projectnessie.versioned.persist.adapter.ContentId; @@ -82,10 +83,12 @@ void merge(int numCommits, boolean keepIndividualCommits) throws Exception { AtomicInteger unifier = new AtomicInteger(); MetadataRewriter metadataUpdater = createMetadataUpdater(unifier, "merged"); + BranchName sourceBranch = BranchName.of("branch"); mergeTransplant( numCommits, (commitHashes, i) -> MergeParams.builder() + .fromBranch(sourceBranch) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) .mergeFromHash(commitHashes[i]), @@ -93,15 +96,17 @@ void merge(int numCommits, boolean keepIndividualCommits) throws Exception { keepIndividualCommits, true); - BranchName branch = BranchName.of("branch"); BranchName branch2 = BranchName.of("branch2"); - databaseAdapter.create(branch2, databaseAdapter.hashOnReference(branch, Optional.empty())); + databaseAdapter.create( + branch2, databaseAdapter.hashOnReference(sourceBranch, Optional.empty())); assertThatThrownBy( () -> databaseAdapter.merge( MergeParams.builder() + .fromBranch(sourceBranch) .toBranch(branch2) - .mergeFromHash(databaseAdapter.hashOnReference(branch, Optional.empty())) + .mergeFromHash( + databaseAdapter.hashOnReference(sourceBranch, Optional.empty())) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) .build())) @@ -143,11 +148,13 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception AtomicInteger unifier = new AtomicInteger(); MetadataRewriter metadataUpdater = createMetadataUpdater(unifier, "transplanted"); + BranchName sourceBranch = BranchName.of("branch"); Hash[] commits = mergeTransplant( numCommits, (commitHashes, i) -> TransplantParams.builder() + .fromBranch(sourceBranch) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) .sequenceToTransplant(Arrays.asList(commitHashes).subList(0, i + 1)), @@ -164,6 +171,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception databaseAdapter .transplant( TransplantParams.builder() + .fromBranch(sourceBranch) .toBranch(conflict) .expectedHead(Optional.of(noConflictHead)) .addSequenceToTransplant(commits) @@ -180,6 +188,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception databaseAdapter .transplant( TransplantParams.builder() + .fromBranch(sourceBranch) .toBranch(conflict) .addSequenceToTransplant(commits) .updateCommitMetadata(metadataUpdater) @@ -194,6 +203,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception () -> databaseAdapter.transplant( TransplantParams.builder() + .fromBranch(sourceBranch) .toBranch(conflict) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) @@ -269,7 +279,7 @@ Hash[] mergeTransplant( commit.addPuts( KeyWithBytes.of(key, ContentId.of("C" + k), (byte) payloadForContent(value), onRef)); } - commits[i] = databaseAdapter.commit(commit.build()); + commits[i] = databaseAdapter.commit(commit.build()).getCommit().getHash(); } List commitLogEntries; @@ -332,7 +342,17 @@ Hash mergeTransplantSuccess( .expectedHead(Optional.empty()) .isDryRun(true)); - assertThat(mergeResult).isEqualTo(expectedMergeResult.resultantTargetHash(mainHead).build()); + BranchName source = BranchName.of("branch"); + + assertThat(mergeResult) + .isEqualTo( + expectedMergeResult + .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) + .sourceBranch(source) + .targetBranch(target) + .resultantTargetHash(mainHead) + .addedCommits(mergeResult.getAddedCommits()) + .build()); // Merge/transplant @@ -343,7 +363,21 @@ Hash mergeTransplantSuccess( targetHead = databaseAdapter.hashOnReference(target, Optional.empty()); assertThat(mergeResult) - .isEqualTo(expectedMergeResult.resultantTargetHash(targetHead).wasApplied(true).build()); + .isEqualTo( + expectedMergeResult + .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) + .sourceBranch(source) + .targetBranch(target) + .resultantTargetHash(targetHead) + .wasApplied(true) + .addedCommits(mergeResult.getAddedCommits()) + .build()); + + if (individualCommits) { + assertThat(mergeResult.getAddedCommits()).hasSize(expectedSourceCommits.size()); + } else { + assertThat(mergeResult.getAddedCommits()).hasSize(1); + } // Briefly check commit log @@ -368,7 +402,7 @@ void mergeTransplantConflict( // prepare conflict for keys 0 + 1 - Hash conflictBase = databaseAdapter.create(conflict, mainHead); + Hash conflictBase = databaseAdapter.create(conflict, mainHead).getHash(); ImmutableCommitParams.Builder commit = ImmutableCommitParams.builder() .toBranch(conflict) @@ -382,7 +416,7 @@ void mergeTransplantConflict( (byte) payloadForContent(conflictValue), DefaultStoreWorker.instance().toStoreOnReferenceState(conflictValue))); } - Hash conflictHead = databaseAdapter.commit(commit.build()); + Hash conflictHead = databaseAdapter.commit(commit.build()).getCommit().getHash(); List expectedSourceCommits = commitLogEntries.subList(commits.length - 1 - 2, commits.length); @@ -439,7 +473,9 @@ private MergeResult conflictExpectedMergeResult( ImmutableMergeResult.Builder expectedMergeResult = MergeResult.builder() + .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) .resultantTargetHash(conflictHead) + .sourceBranch(BranchName.of("branch")) .targetBranch(conflict) .effectiveTargetHash(conflictHead) .expectedHash(conflictBase) diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRefLog.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRefLog.java index 311cbbeaaba..bb6ab719e57 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRefLog.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRefLog.java @@ -167,7 +167,7 @@ void splitRefLog() throws Exception { for (int i = 0; i < 50; i++) { NamedRef ref = refGen.apply(i); - assertThat(databaseAdapter.create(ref, databaseAdapter.noAncestorHash())) + assertThat(databaseAdapter.create(ref, databaseAdapter.noAncestorHash()).getHash()) .isEqualTo(databaseAdapter.noAncestorHash()); refLogOpsPerRef diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java index beec77985b9..529c0848938 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java @@ -83,7 +83,9 @@ private void createNamedRef(NamedRef create, NamedRef opposite) throws Exception .isInstanceOf(ReferenceNotFoundException.class); Hash createHash = - databaseAdapter.create(create, databaseAdapter.hashOnReference(branch, Optional.empty())); + databaseAdapter + .create(create, databaseAdapter.hashOnReference(branch, Optional.empty())) + .getHash(); assertThat(createHash).isEqualTo(mainHash); try (Stream> refs = @@ -115,7 +117,8 @@ private void createNamedRef(NamedRef create, NamedRef opposite) throws Exception assertThatThrownBy(() -> databaseAdapter.delete(opposite, Optional.of(createHash))) .isInstanceOf(ReferenceNotFoundException.class); - assertThat(databaseAdapter.delete(create, Optional.of(createHash))).isEqualTo(createHash); + assertThat(databaseAdapter.delete(create, Optional.of(createHash)).getHash()) + .isEqualTo(createHash); assertThatThrownBy(() -> databaseAdapter.hashOnReference(create, Optional.empty())) .isInstanceOf(ReferenceNotFoundException.class); @@ -134,21 +137,26 @@ void verifyNotFoundAndConflictExceptionsForUnreachableCommit() throws Exception databaseAdapter.create(unreachable, databaseAdapter.hashOnReference(main, Optional.empty())); Hash helperHead = - databaseAdapter.create(helper, databaseAdapter.hashOnReference(main, Optional.empty())); + databaseAdapter + .create(helper, databaseAdapter.hashOnReference(main, Optional.empty())) + .getHash(); OnRefOnly hello = onRef("hello", "contentId"); Hash unreachableHead = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(unreachable) - .commitMetaSerialized(ByteString.copyFromUtf8("commit meta")) - .addPuts( - KeyWithBytes.of( - ContentKey.of("foo"), - ContentId.of(hello.getId()), - (byte) payloadForContent(hello), - hello.serialized())) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(unreachable) + .commitMetaSerialized(ByteString.copyFromUtf8("commit meta")) + .addPuts( + KeyWithBytes.of( + ContentKey.of("foo"), + ContentId.of(hello.getId()), + (byte) payloadForContent(hello), + hello.serialized())) + .build()) + .getCommit() + .getHash(); assertAll( () -> @@ -210,17 +218,20 @@ void assign() throws Exception { for (int i = 0; i < commits.length; i++) { OnRefOnly hello = onRef("hello " + i, "contentId-" + i); commits[i] = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch(main) - .commitMetaSerialized(ByteString.copyFromUtf8("commit meta " + i)) - .addPuts( - KeyWithBytes.of( - ContentKey.of("bar-" + i), - ContentId.of(hello.getId()), - (byte) payloadForContent(hello), - hello.serialized())) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch(main) + .commitMetaSerialized(ByteString.copyFromUtf8("commit meta " + i)) + .addPuts( + KeyWithBytes.of( + ContentKey.of("bar-" + i), + ContentId.of(hello.getId()), + (byte) payloadForContent(hello), + hello.serialized())) + .build()) + .getCommit() + .getHash(); } Hash expect = beginning; @@ -252,7 +263,7 @@ void recreateDefaultBranch() throws Exception { BranchName main = BranchName.of("main"); Hash mainHead = databaseAdapter.hashOnReference(main, Optional.empty()); - assertThat(databaseAdapter.delete(main, Optional.of(mainHead))).isEqualTo(mainHead); + assertThat(databaseAdapter.delete(main, Optional.of(mainHead)).getHash()).isEqualTo(mainHead); assertThatThrownBy(() -> databaseAdapter.hashOnReference(main, Optional.empty())) .isInstanceOf(ReferenceNotFoundException.class); @@ -276,10 +287,12 @@ void deleteReferences() throws Exception { databaseAdapter.create(delete3, mainHead); databaseAdapter.create(delete4, mainHead); - assertThat(databaseAdapter.delete(delete1, Optional.of(mainHead))).isEqualTo(mainHead); - assertThat(databaseAdapter.delete(delete2, Optional.of(mainHead))).isEqualTo(mainHead); - assertThat(databaseAdapter.delete(delete3, Optional.empty())).isEqualTo(mainHead); - assertThat(databaseAdapter.delete(delete4, Optional.empty())).isEqualTo(mainHead); + assertThat(databaseAdapter.delete(delete1, Optional.of(mainHead)).getHash()) + .isEqualTo(mainHead); + assertThat(databaseAdapter.delete(delete2, Optional.of(mainHead)).getHash()) + .isEqualTo(mainHead); + assertThat(databaseAdapter.delete(delete3, Optional.empty()).getHash()).isEqualTo(mainHead); + assertThat(databaseAdapter.delete(delete4, Optional.empty()).getHash()).isEqualTo(mainHead); assertThatThrownBy(() -> databaseAdapter.hashOnReference(delete1, Optional.empty())) .isInstanceOf(ReferenceNotFoundException.class); @@ -310,7 +323,7 @@ void manyReferences() throws Exception { for (int i = 0; i < 50; i++) { NamedRef ref = refGen.apply(i); - assertThat(databaseAdapter.create(ref, databaseAdapter.noAncestorHash())) + assertThat(databaseAdapter.create(ref, databaseAdapter.noAncestorHash()).getHash()) .isEqualTo(databaseAdapter.noAncestorHash()); refHeads.put(ref, databaseAdapter.noAncestorHash()); @@ -336,19 +349,22 @@ void manyReferences() throws Exception { NamedRef ref = refGen.apply(i); if (ref instanceof BranchName) { Hash newHead = - databaseAdapter.commit( - ImmutableCommitParams.builder() - .toBranch((BranchName) ref) - .commitMetaSerialized(ByteString.copyFromUtf8("foo on " + ref.getName())) - .expectedHead(Optional.of(refHeads.get(ref))) - .addPuts( - KeyWithBytes.of( - ContentKey.of("table-" + commit), - ContentId.of("c" + commit), - (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), - DefaultStoreWorker.instance() - .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + commit)))) - .build()); + databaseAdapter + .commit( + ImmutableCommitParams.builder() + .toBranch((BranchName) ref) + .commitMetaSerialized(ByteString.copyFromUtf8("foo on " + ref.getName())) + .expectedHead(Optional.of(refHeads.get(ref))) + .addPuts( + KeyWithBytes.of( + ContentKey.of("table-" + commit), + ContentId.of("c" + commit), + (byte) payloadForContent(OnRefOnly.ON_REF_ONLY), + DefaultStoreWorker.instance() + .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + commit)))) + .build()) + .getCommit() + .getHash(); refHeads.put(ref, newHead); } } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRepositories.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRepositories.java index d85ea79d809..2b4543389d1 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRepositories.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractRepositories.java @@ -109,8 +109,8 @@ void multipleRepositories( Hash fooMain = foo.hashOnReference(main, Optional.empty()); Hash barMain = bar.hashOnReference(main, Optional.empty()); - Hash fooBranch = foo.create(fooBranchName, fooMain); - Hash barBranch = bar.create(barBranchName, barMain); + Hash fooBranch = foo.create(fooBranchName, fooMain).getHash(); + Hash barBranch = bar.create(barBranchName, barMain).getHash(); assertThat(fooMain).isNotEqualTo(barMain).isEqualTo(fooBranch); assertThat(barMain).isNotEqualTo(fooMain).isEqualTo(barBranch); diff --git a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java index 55d6f76ec38..ca1a8ca9d80 100644 --- a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java +++ b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java @@ -67,17 +67,26 @@ import org.projectnessie.nessie.relocated.protobuf.InvalidProtocolBufferException; import org.projectnessie.nessie.relocated.protobuf.UnsafeByteOperations; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.ImmutableCommitResult; import org.projectnessie.versioned.ImmutableMergeResult; +import org.projectnessie.versioned.ImmutableReferenceAssignedResult; +import org.projectnessie.versioned.ImmutableReferenceCreatedResult; +import org.projectnessie.versioned.ImmutableReferenceDeletedResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.RefLogNotFoundException; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.ReferenceRetryFailureException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.TagName; import org.projectnessie.versioned.VersionStoreException; import org.projectnessie.versioned.persist.adapter.CommitLogEntry; @@ -236,7 +245,10 @@ public MergeResult merge(MergeParams mergeParams) (conn, currentHead) -> { long timeInMicros = config.currentTimeInMicros(); - ImmutableMergeResult.Builder mergeResult = MergeResult.builder(); + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceBranch(mergeParams.getFromBranch()); mergeResultHolder.set(mergeResult); List writtenCommits = new ArrayList<>(); @@ -248,6 +260,7 @@ public MergeResult merge(MergeParams mergeParams) h -> {}, h -> {}, writtenCommits::add, + mergeResult::addAddedCommits, mergeParams, mergeResult); @@ -301,7 +314,11 @@ public MergeResult transplant(TransplantParams transplantParams) (conn, currentHead) -> { long timeInMicros = config.currentTimeInMicros(); - ImmutableMergeResult.Builder mergeResult = MergeResult.builder(); + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceBranch(transplantParams.getFromBranch()); + mergeResultHolder.set(mergeResult); List writtenCommits = new ArrayList<>(); @@ -313,6 +330,7 @@ public MergeResult transplant(TransplantParams transplantParams) h -> {}, h -> {}, writtenCommits::add, + mergeResult::addAddedCommits, transplantParams, mergeResult); @@ -347,16 +365,21 @@ public MergeResult transplant(TransplantParams transplantParams) } @Override - public Hash commit(CommitParams commitParams) + public CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException { try { - return opLoop( + AtomicReference> commitResultHolder = + new AtomicReference<>(); + + opLoop( "commit", commitParams.getToBranch(), false, (conn, branchHead) -> { long timeInMicros = config.currentTimeInMicros(); + ImmutableCommitResult.Builder commitResult = CommitResult.builder(); + CommitLogEntry newBranchCommit = commitAttempt(conn, timeInMicros, branchHead, commitParams, h -> {}); @@ -364,6 +387,9 @@ public Hash commit(CommitParams commitParams) tryMoveNamedReference( conn, commitParams.getToBranch(), branchHead, newBranchCommit.getHash()); + commitResult.commit(newBranchCommit).targetBranch(commitParams.getToBranch()); + commitResultHolder.set(commitResult); + return opResult( resultHash, () -> @@ -379,6 +405,12 @@ public Hash commit(CommitParams commitParams) () -> commitConflictMessage( "Retry-Failure", commitParams.getToBranch(), commitParams.getExpectedHead())); + + ImmutableCommitResult.Builder commitResult = + Objects.requireNonNull( + commitResultHolder.get(), "Internal error, commit-result builder not set."); + + return commitResult.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -388,14 +420,21 @@ public Hash commit(CommitParams commitParams) @SuppressWarnings("RedundantThrows") @Override - public Hash create(NamedRef ref, Hash target) + public ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException { try { - return opLoop( + AtomicReference resultHolder = + new AtomicReference<>(); + + opLoop( "createRef", ref, true, (conn, nullHead) -> { + ImmutableReferenceCreatedResult.Builder result = + ImmutableReferenceCreatedResult.builder().namedRef(ref); + resultHolder.set(result); + if (checkNamedRefExistence(conn, ref.getName())) { throw referenceAlreadyExists(ref); } @@ -419,10 +458,18 @@ public Hash create(NamedRef ref, Hash target) RefLogEntry.Operation.CREATE_REFERENCE, emptyList()); + result.hash(hash); + return opResult(hash, () -> ReferenceCreatedEvent.builder().currentHash(hash).ref(ref)); }, () -> createConflictMessage("Conflict", ref, target), () -> createConflictMessage("Retry-Failure", ref, target)); + + ImmutableReferenceCreatedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceAlreadyExistsException | ReferenceNotFoundException | RuntimeException e) { throw e; } catch (Exception e) { @@ -431,14 +478,21 @@ public Hash create(NamedRef ref, Hash target) } @Override - public Hash delete(NamedRef reference, Optional expectedHead) + public ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException { try { - return opLoop( + AtomicReference resultHolder = + new AtomicReference<>(); + + opLoop( "deleteRef", reference, false, (conn, pointer) -> { + ImmutableReferenceDeletedResult.Builder result = + ImmutableReferenceDeletedResult.builder().namedRef(reference); + resultHolder.set(result); + verifyExpectedHash(pointer, reference, expectedHead); Hash commitHash = fetchNamedRefHead(conn, reference); @@ -461,12 +515,20 @@ public Hash delete(NamedRef reference, Optional expectedHead) RefLogEntry.Operation.DELETE_REFERENCE, emptyList()); + result.hash(commitHash); + return opResult( pointer, () -> ReferenceDeletedEvent.builder().currentHash(commitHash).ref(reference)); }, () -> deleteConflictMessage("Conflict", reference, expectedHead), () -> deleteConflictMessage("Retry-Failure", reference, expectedHead)); + + ImmutableReferenceDeletedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -475,14 +537,22 @@ public Hash delete(NamedRef reference, Optional expectedHead) } @Override - public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo) + public ReferenceAssignedResult assign( + NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException { try { + AtomicReference resultHolder = + new AtomicReference<>(); + opLoop( "assignRef", assignee, false, (conn, assigneeHead) -> { + ImmutableReferenceAssignedResult.Builder result = + ImmutableReferenceAssignedResult.builder().namedRef(assignee); + resultHolder.set(result); + verifyExpectedHash(assigneeHead, assignee, expectedHead); validateHashExists(conn, assignTo); @@ -497,6 +567,8 @@ public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo RefLogEntry.Operation.ASSIGN_REFERENCE, Collections.singletonList(assigneeHead)); + result.previousHash(assigneeHead).currentHash(assignTo); + return opResult( resultHash, () -> @@ -507,6 +579,12 @@ public void assign(NamedRef assignee, Optional expectedHead, Hash assignTo }, () -> assignConflictMessage("Conflict", assignee, expectedHead, assignTo), () -> assignConflictMessage("Retry-Failure", assignee, expectedHead, assignTo)); + + ImmutableReferenceAssignedResult.Builder result = + Objects.requireNonNull( + resultHolder.get(), "Internal error, reference-result builder not set."); + + return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java new file mode 100644 index 00000000000..c3f470c1e81 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import org.immutables.value.Value; + +@Value.Immutable +public interface CommitResult extends Result { + + @Override + default ResultType getResultType() { + return ResultType.COMMIT; + } + + COMMIT getCommit(); + + BranchName getTargetBranch(); + + static ImmutableCommitResult.Builder builder() { + return ImmutableCommitResult.builder(); + } +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java new file mode 100644 index 00000000000..b3d88d9d47e --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import org.projectnessie.model.CommitMeta; +import org.projectnessie.model.Content; +import org.projectnessie.model.ContentKey; +import org.projectnessie.model.MergeBehavior; +import org.projectnessie.model.MergeKeyBehavior; +import org.projectnessie.versioned.paging.PaginationIterator; + +/** + * A {@link VersionStore} wrapper that publishes results when a method is called that changes the + * catalog state. + */ +public class EventsVersionStore implements VersionStore { + + private final VersionStore delegate; + private final Consumer resultSink; + + /** + * Takes the {@link VersionStore} instance to enrich with events. + * + * @param delegate backing/delegate {@link VersionStore}. + * @param resultSink a consumer for results. + */ + public EventsVersionStore(VersionStore delegate, Consumer resultSink) { + this.delegate = delegate; + this.resultSink = resultSink; + } + + @Override + public CommitResult commit( + @Nonnull @jakarta.annotation.Nonnull BranchName branch, + @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, + @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, + @Nonnull @jakarta.annotation.Nonnull List operations, + @Nonnull @jakarta.annotation.Nonnull Callable validator, + @Nonnull @jakarta.annotation.Nonnull BiConsumer addedContents) + throws ReferenceNotFoundException, ReferenceConflictException { + CommitResult result = + delegate.commit(branch, referenceHash, metadata, operations, validator, addedContents); + resultSink.accept(result); + return result; + } + + @Override + public MergeResult transplant( + BranchName sourceBranch, + BranchName targetBranch, + Optional referenceHash, + List sequenceToTransplant, + MetadataRewriter updateCommitMetadata, + boolean keepIndividualCommits, + Map mergeKeyBehaviors, + MergeBehavior defaultMergeBehavior, + boolean dryRun, + boolean fetchAdditionalInfo) + throws ReferenceNotFoundException, ReferenceConflictException { + MergeResult result = + delegate.transplant( + sourceBranch, + targetBranch, + referenceHash, + sequenceToTransplant, + updateCommitMetadata, + keepIndividualCommits, + mergeKeyBehaviors, + defaultMergeBehavior, + dryRun, + fetchAdditionalInfo); + if (!dryRun) { + resultSink.accept(result); + } + return result; + } + + @Override + public MergeResult merge( + BranchName fromBranch, + Hash fromHash, + BranchName toBranch, + Optional expectedHash, + MetadataRewriter updateCommitMetadata, + boolean keepIndividualCommits, + Map mergeKeyBehaviors, + MergeBehavior defaultMergeBehavior, + boolean dryRun, + boolean fetchAdditionalInfo) + throws ReferenceNotFoundException, ReferenceConflictException { + MergeResult result = + delegate.merge( + fromBranch, + fromHash, + toBranch, + expectedHash, + updateCommitMetadata, + keepIndividualCommits, + mergeKeyBehaviors, + defaultMergeBehavior, + dryRun, + fetchAdditionalInfo); + if (!dryRun) { + resultSink.accept(result); + } + return result; + } + + @Override + public ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, Hash targetHash) + throws ReferenceNotFoundException, ReferenceConflictException { + ReferenceAssignedResult result = delegate.assign(ref, expectedHash, targetHash); + resultSink.accept(result); + return result; + } + + @Override + public ReferenceCreatedResult create(NamedRef ref, Optional targetHash) + throws ReferenceNotFoundException, ReferenceAlreadyExistsException { + // FIXME half-created refs with new storage model + ReferenceCreatedResult result = delegate.create(ref, targetHash); + resultSink.accept(result); + return result; + } + + @Override + public ReferenceDeletedResult delete(NamedRef ref, Optional hash) + throws ReferenceNotFoundException, ReferenceConflictException { + ReferenceDeletedResult result = delegate.delete(ref, hash); + resultSink.accept(result); + return result; + } + + @Override + public Hash hashOnReference(NamedRef namedReference, Optional hashOnReference) + throws ReferenceNotFoundException { + return delegate.hashOnReference(namedReference, hashOnReference); + } + + @Nonnull + @jakarta.annotation.Nonnull + @Override + public Hash noAncestorHash() { + return delegate.noAncestorHash(); + } + + @Override + public ReferenceInfo getNamedRef(String ref, GetNamedRefsParams params) + throws ReferenceNotFoundException { + return delegate.getNamedRef(ref, params); + } + + @Override + public PaginationIterator> getNamedRefs( + GetNamedRefsParams params, String pagingToken) throws ReferenceNotFoundException { + return delegate.getNamedRefs(params, pagingToken); + } + + @Override + public PaginationIterator getCommits(Ref ref, boolean fetchAdditionalInfo) + throws ReferenceNotFoundException { + return delegate.getCommits(ref, fetchAdditionalInfo); + } + + @Override + public PaginationIterator getKeys(Ref ref, String pagingToken, boolean withContent) + throws ReferenceNotFoundException { + return delegate.getKeys(ref, pagingToken, withContent); + } + + @Override + public Content getValue(Ref ref, ContentKey key) throws ReferenceNotFoundException { + return delegate.getValue(ref, key); + } + + @Override + public Map getValues(Ref ref, Collection keys) + throws ReferenceNotFoundException { + return delegate.getValues(ref, keys); + } + + @Override + public PaginationIterator getDiffs(Ref from, Ref to, String pagingToken) + throws ReferenceNotFoundException { + return delegate.getDiffs(from, to, pagingToken); + } + + @Override + @Deprecated + @SuppressWarnings("MustBeClosedChecker") + public Stream getRefLog(Hash refLogId) throws RefLogNotFoundException { + return delegate.getRefLog(refLogId); + } + + @Nonnull + @jakarta.annotation.Nonnull + @Override + public RepositoryInformation getRepositoryInformation() { + return delegate.getRepositoryInformation(); + } +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java b/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java new file mode 100644 index 00000000000..9d75455b0a8 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import java.util.function.Supplier; +import org.immutables.value.Value; +import org.projectnessie.model.Content; +import org.projectnessie.model.ContentKey; +import org.projectnessie.nessie.relocated.protobuf.ByteString; +import org.projectnessie.versioned.store.DefaultStoreWorker; + +/** + * A PUT operation that has been retrieved from the version store. The content value is kept in its + * raw (serialized) form; deserialization happens lazily, on first access to {@link #getValue()}. + */ +@Value.Immutable +public interface LazyPut extends Operation { + + int getPayload(); + + ByteString getRawValue(); + + @Value.Lazy + @SuppressWarnings("deprecation") + default Content getValue() { + return DefaultStoreWorker.instance() + .valueFromStore((byte) getPayload(), getRawValue(), getGlobalStateSupplier()); + } + + /** TODO remove global state supplier completely when it's removed from VersionStore. */ + @Value.Default + @Value.Auxiliary + default Supplier getGlobalStateSupplier() { + return () -> null; + } + + static LazyPut of(ContentKey key, int payload, ByteString value) { + return of(key, payload, value, () -> null); + } + + static LazyPut of( + ContentKey key, int payload, ByteString value, Supplier globalStateSupplier) { + return ImmutableLazyPut.builder() + .key(key) + .payload(payload) + .rawValue(value) + .globalStateSupplier(globalStateSupplier) + .build(); + } +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java index d1e98b27696..4564fd7e96e 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java @@ -24,7 +24,7 @@ import org.projectnessie.model.MergeBehavior; @Value.Immutable -public interface MergeResult { +public interface MergeResult extends Result { /** Indicates whether the merge or transplant operation has been applied. */ @Value.Default @@ -48,6 +48,9 @@ default boolean wasSuccessful() { @jakarta.annotation.Nullable Hash getCommonAncestor(); + /** Name of the source branch. */ + BranchName getSourceBranch(); + /** Name of the target branch. */ BranchName getTargetBranch(); @@ -72,6 +75,21 @@ default boolean wasSuccessful() { @Deprecated // for removal and replaced with something else List getTargetCommits(); + /** + * List of commits that where added to the target branch, that is, all the commits between + * {@linkplain #getEffectiveTargetHash() the previous HEAD} (exclusive) and {@linkplain + * #getResultantTargetHash() the current HEAD} (inclusive). + * + *

The returned list will always be empty if the merge or transplant operation failed. + * Otherwise, if commits were squashed, it will contain exactly one element; otherwise, it will + * generally contain as many commits as there were {@linkplain #getSourceCommits() source commits} + * to rebase (unless some source commits were filtered out). + * + *

This list is currently not exposed via the REST API. It is intended to be used by the Nessie + * events notification system. + */ + List getAddedCommits(); + /** Details of all keys encountered during the merge or transplant operation. */ Map getDetails(); diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java index fb32070a847..1764e686c4f 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java @@ -86,7 +86,7 @@ public Hash noAncestorHash() { } @Override - public Hash commit( + public CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @@ -94,14 +94,17 @@ public Hash commit( @Nonnull @jakarta.annotation.Nonnull Callable validator, @Nonnull @jakarta.annotation.Nonnull BiConsumer addedContents) throws ReferenceNotFoundException, ReferenceConflictException { - return this.delegate2ExR( - "commit", - () -> - delegate.commit(branch, referenceHash, metadata, operations, validator, addedContents)); + return this + ., ReferenceNotFoundException, ReferenceConflictException>delegate2ExR( + "commit", + () -> + delegate.commit( + branch, referenceHash, metadata, operations, validator, addedContents)); } @Override public MergeResult transplant( + BranchName sourceBranch, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -117,6 +120,7 @@ public MergeResult transplant( "transplant", () -> delegate.transplant( + sourceBranch, targetBranch, referenceHash, sequenceToTransplant, @@ -130,6 +134,7 @@ public MergeResult transplant( @Override public MergeResult merge( + BranchName fromBranch, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -145,6 +150,7 @@ public MergeResult merge( "merge", () -> delegate.merge( + fromBranch, fromHash, toBranch, expectedHash, @@ -157,24 +163,27 @@ public MergeResult merge( } @Override - public void assign(NamedRef ref, Optional expectedHash, Hash targetHash) + public ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, Hash targetHash) throws ReferenceNotFoundException, ReferenceConflictException { - this.delegate2Ex( - "assign", () -> delegate.assign(ref, expectedHash, targetHash)); + return this + . + delegate2ExR("assign", () -> delegate.assign(ref, expectedHash, targetHash)); } @Override - public Hash create(NamedRef ref, Optional targetHash) + public ReferenceCreatedResult create(NamedRef ref, Optional targetHash) throws ReferenceNotFoundException, ReferenceAlreadyExistsException { - return this.delegate2ExR( - "create", () -> delegate.create(ref, targetHash)); + return this + . + delegate2ExR("create", () -> delegate.create(ref, targetHash)); } @Override - public Hash delete(NamedRef ref, Optional hash) + public ReferenceDeletedResult delete(NamedRef ref, Optional hash) throws ReferenceNotFoundException, ReferenceConflictException { - return this.delegate2ExR( - "delete", () -> delegate.delete(ref, hash)); + return this + . + delegate2ExR("delete", () -> delegate.delete(ref, hash)); } @Override @@ -312,23 +321,6 @@ private R delegate1Ex( return delegate2ExR(requestName, delegate::handle); } - private void delegate2Ex( - String requestName, DelegateWith2 delegate) throws E1, E2 { - Sample sample = Timer.start(clock); - Exception failure = null; - try { - delegate.handle(); - } catch (IllegalArgumentException e) { - // IllegalArgumentException indicates a user-error, not a server error - throw e; - } catch (RuntimeException e) { - failure = e; - throw e; - } finally { - measure(requestName, sample, failure); - } - } - private R delegate2ExR( String requestName, DelegateWith2R delegate) throws E1, E2 { Sample sample = Timer.start(clock); @@ -351,11 +343,6 @@ interface DelegateWith1 { R handle() throws E1; } - @FunctionalInterface - interface DelegateWith2 { - void handle() throws E1, E2; - } - @FunctionalInterface interface DelegateWith2R { R handle() throws E1, E2; diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index f4d678711d7..5ac760dc142 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -20,7 +20,10 @@ import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; -/** Setting a new value. Can optionally declare whether the prior hash must match. */ +/** + * A PUT operation provided by the client in order to set a new value in a commit. Can optionally + * declare whether the prior hash must match. + */ @Value.Immutable public interface Put extends Operation { diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceAssignedResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceAssignedResult.java new file mode 100644 index 00000000000..cfe01e49f2d --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceAssignedResult.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import org.immutables.value.Value; + +@Value.Immutable +public interface ReferenceAssignedResult extends Result { + + @Override + default ResultType getResultType() { + return ResultType.REFERENCE_ASSIGNED; + } + + NamedRef getNamedRef(); + + Hash getPreviousHash(); + + Hash getCurrentHash(); +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceCreatedResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceCreatedResult.java new file mode 100644 index 00000000000..0410f958e07 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceCreatedResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import org.immutables.value.Value; + +@Value.Immutable +public interface ReferenceCreatedResult extends Result { + + @Override + default ResultType getResultType() { + return ResultType.REFERENCE_CREATED; + } + + NamedRef getNamedRef(); + + Hash getHash(); +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceDeletedResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceDeletedResult.java new file mode 100644 index 00000000000..6dbe1a5bd28 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/ReferenceDeletedResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import org.immutables.value.Value; + +@Value.Immutable +public interface ReferenceDeletedResult extends Result { + + @Override + default ResultType getResultType() { + return ResultType.REFERENCE_DELETED; + } + + NamedRef getNamedRef(); + + Hash getHash(); +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Result.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Result.java new file mode 100644 index 00000000000..27d8c849178 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Result.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +/** A common superinterface for results of operations on a {@link VersionStore}. */ +public interface Result { + + ResultType getResultType(); +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/ResultType.java b/versioned/spi/src/main/java/org/projectnessie/versioned/ResultType.java new file mode 100644 index 00000000000..315b1821588 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/ResultType.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +public enum ResultType { + REFERENCE_ASSIGNED, + REFERENCE_DELETED, + REFERENCE_CREATED, + COMMIT, + MERGE, + TRANSPLANT +} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java index 718085de24d..3b6f6bdbe3f 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java @@ -111,7 +111,7 @@ public Hash noAncestorHash() { } @Override - public Hash commit( + public CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @@ -120,20 +120,21 @@ public Hash commit( @Nonnull @jakarta.annotation.Nonnull BiConsumer addedContents) throws ReferenceNotFoundException, ReferenceConflictException { return TracingVersionStore - .callWithTwoExceptions( - tracer, - "Commit", - b -> - b.setAttribute(TAG_BRANCH, safeRefName(branch)) - .setAttribute(TAG_HASH, safeToString(referenceHash)) - .setAttribute(TAG_NUM_OPS, safeSize(operations)), - () -> - delegate.commit( - branch, referenceHash, metadata, operations, validator, addedContents)); + ., ReferenceNotFoundException, ReferenceConflictException> + callWithTwoExceptions( + tracer,"Commit", + b -> + b.setAttribute(TAG_BRANCH, safeRefName(branch)) + .setAttribute(TAG_HASH, safeToString(referenceHash)) + .setAttribute(TAG_NUM_OPS, safeSize(operations)), + () -> + delegate.commit( + branch, referenceHash, metadata, operations, validator, addedContents)); } @Override public MergeResult transplant( + BranchName sourceBranch, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -155,6 +156,7 @@ public MergeResult transplant( .setAttribute(TAG_TRANSPLANTS, safeSize(sequenceToTransplant)), () -> delegate.transplant( + sourceBranch, targetBranch, referenceHash, sequenceToTransplant, @@ -168,6 +170,7 @@ public MergeResult transplant( @Override public MergeResult merge( + BranchName fromBranch, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -189,6 +192,7 @@ public MergeResult merge( .setAttribute(TAG_EXPECTED_HASH, safeToString(expectedHash)), () -> delegate.merge( + fromBranch, fromHash, toBranch, expectedHash, @@ -201,43 +205,42 @@ public MergeResult merge( } @Override - public void assign(NamedRef ref, Optional expectedHash, Hash targetHash) + public ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, Hash targetHash) throws ReferenceNotFoundException, ReferenceConflictException { - TracingVersionStore - .callWithTwoExceptions( - tracer, - "Assign", - b -> - b.setAttribute(TAG_REF, safeToString(ref)) - .setAttribute(TracingVersionStore.TAG_EXPECTED_HASH, safeToString(expectedHash)) - .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), - () -> delegate.assign(ref, expectedHash, targetHash)); + return TracingVersionStore + . + callWithTwoExceptions( + tracer,"Assign", + b -> + b.setAttribute(TAG_REF, safeToString(ref)) + .setAttribute(TracingVersionStore.TAG_EXPECTED_HASH, safeToString(expectedHash)) + .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), + () -> delegate.assign(ref, expectedHash, targetHash)); } @Override - public Hash create(NamedRef ref, Optional targetHash) + public ReferenceCreatedResult create(NamedRef ref, Optional targetHash) throws ReferenceNotFoundException, ReferenceAlreadyExistsException { return TracingVersionStore - .callWithTwoExceptions( - tracer, - "Create", - b -> - b.setAttribute(TAG_REF, safeToString(ref)) - .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), - () -> delegate.create(ref, targetHash)); + . + callWithTwoExceptions( + tracer,"Create", + b -> + b.setAttribute(TAG_REF, safeToString(ref)) + .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), + () -> delegate.create(ref, targetHash)); } @Override - public Hash delete(NamedRef ref, Optional hash) + public ReferenceDeletedResult delete(NamedRef ref, Optional hash) throws ReferenceNotFoundException, ReferenceConflictException { return TracingVersionStore - .callWithTwoExceptions( - tracer, - "Delete", - b -> - b.setAttribute(TAG_REF, safeToString(ref)) + . + callWithTwoExceptions( + tracer,"Delete", + b -> b.setAttribute(TAG_REF, safeToString(ref)) .setAttribute(TAG_HASH, safeToString(hash)), - () -> delegate.delete(ref, hash)); + () -> delegate.delete(ref, hash)); } @Override @@ -375,25 +378,6 @@ private static R callWithOneException( } } - private static - void callWithTwoExceptions( - Tracer tracer, - String spanName, - Consumer spanBuilder, - InvokerWithTwoExceptions invoker) - throws E1, E2 { - try (SpanHolder span = createSpan(tracer, spanName, spanBuilder)) { - try { - invoker.handle(); - } catch (IllegalArgumentException e) { - // IllegalArgumentException is a special kind of exception that indicates a user-error. - throw e; - } catch (RuntimeException e) { - throw traceError(span.get(), e); - } - } - } - private static R callWithTwoExceptions( Tracer tracer, @@ -418,12 +402,6 @@ interface InvokerWithOneException { R handle() throws E1; } - @FunctionalInterface - interface InvokerWithTwoExceptions< - E1 extends VersionStoreException, E2 extends VersionStoreException> { - void handle() throws E1, E2; - } - @FunctionalInterface interface InvokerWithTwoExceptionsR< R, E1 extends VersionStoreException, E2 extends VersionStoreException> { diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java index 89a77511cd2..9a6c02cfd01 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java @@ -89,7 +89,7 @@ Hash hashOnReference(NamedRef namedReference, Optional hashOnReference) * @throws ReferenceNotFoundException if {@code branch} is not present in the store * @throws NullPointerException if one of the argument is {@code null} */ - Hash commit( + CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @@ -98,7 +98,7 @@ Hash commit( @Nonnull @jakarta.annotation.Nonnull BiConsumer addedContents) throws ReferenceNotFoundException, ReferenceConflictException; - default Hash commit( + default CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @@ -114,6 +114,7 @@ default Hash commit( * to concurrent readers/writers. The sequence to transplant must be contiguous, in order and * share a common ancestor with the target branch. * + * @param sourceBranch The branch we're transplanting from * @param targetBranch The branch we're transplanting to * @param referenceHash The hash to use as a reference for conflict detection. If not present, do * not perform conflict detection @@ -134,6 +135,7 @@ default Hash commit( * sequenceToTransplant} is not present in the store. */ MergeResult transplant( + BranchName sourceBranch, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -160,6 +162,7 @@ MergeResult transplant( *

  • the expected branch hash does not match the actual branch hash * * + * @param fromBranch The branch we are merging from * @param fromHash The hash we are using to get additional commits * @param toBranch The branch that we are merging into * @param expectedHash The current head of the branch to validate before updating (optional). @@ -179,6 +182,7 @@ MergeResult transplant( * the store. */ MergeResult merge( + BranchName fromBranch, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -201,12 +205,14 @@ MergeResult merge( * @param expectedHash The current head of the NamedRef to validate before updating. If not * present, force assignment. * @param targetHash The hash that this ref should refer to. + * @return A {@link ReferenceAssignedResult} containing the previous and current head of the + * reference * @throws ReferenceNotFoundException if {@code ref} is not present in the store or if {@code * targetHash} is not present in the store * @throws ReferenceConflictException if {@code expectedHash} is not empty and its value doesn't * match the stored hash for {@code ref} */ - void assign(NamedRef ref, Optional expectedHash, Hash targetHash) + ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, Hash targetHash) throws ReferenceNotFoundException, ReferenceConflictException; /** @@ -216,11 +222,12 @@ void assign(NamedRef ref, Optional expectedHash, Hash targetHash) * @param ref The named ref we're assigning * @param targetHash The hash that this ref should refer to (optional). Otherwise will reference * the beginning of time. + * @return A {@link ReferenceCreatedResult} containing the head of the created reference * @throws ReferenceNotFoundException if {@code targetHash} is not empty and not present in the * store * @throws ReferenceAlreadyExistsException if {@code ref} already exists */ - Hash create(NamedRef ref, Optional targetHash) + ReferenceCreatedResult create(NamedRef ref, Optional targetHash) throws ReferenceNotFoundException, ReferenceAlreadyExistsException; /** @@ -231,12 +238,12 @@ Hash create(NamedRef ref, Optional targetHash) * @param ref The NamedRef to be deleted. * @param hash An optional hash. If provided, this operation will only succeed if the branch is * pointing at the provided - * @return head of deleted reference + * @return A {@link ReferenceDeletedResult} containing the head of the deleted reference * @throws ReferenceNotFoundException if {@code ref} is not present in the store * @throws ReferenceConflictException if {@code hash} doesn't match the stored hash for {@code * ref} */ - Hash delete(NamedRef ref, Optional hash) + ReferenceDeletedResult delete(NamedRef ref, Optional hash) throws ReferenceNotFoundException, ReferenceConflictException; /** diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java new file mode 100644 index 00000000000..00b28c49b0c --- /dev/null +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java @@ -0,0 +1,636 @@ +/* + * Copyright (C) 2020 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableMap; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Callable; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.projectnessie.model.CommitMeta; +import org.projectnessie.model.Content; +import org.projectnessie.model.ContentKey; +import org.projectnessie.model.IcebergTable; +import org.projectnessie.model.MergeBehavior; +import org.projectnessie.versioned.paging.PaginationIterator; + +@ExtendWith(MockitoExtension.class) +class TestEventsVersionStore { + + @Mock VersionStore delegate; + @Mock Consumer sink; + + @Mock MetadataRewriter metadataRewriter; + @Mock PaginationIterator> iteratorInfos; + @Mock PaginationIterator iteratorCommits; + @Mock PaginationIterator iteratorKeyEntries; + @Mock PaginationIterator iteratorDiffs; + @Mock Stream refLogDetails; + + BranchName branch1 = BranchName.of("branch1"); + BranchName branch2 = BranchName.of("branch2"); + Hash hash1 = Hash.of("1234"); + Hash hash2 = Hash.of("5678"); + CommitMeta commitMeta = CommitMeta.fromMessage("irrelevant"); + ContentKey key1 = ContentKey.of("foo.bar.table1"); + ContentKey key2 = ContentKey.of("foo.bar.table2"); + IcebergTable table1 = IcebergTable.of("somewhere", 42, 42, 42, 42, "table1"); + IcebergTable table2 = IcebergTable.of("somewhere", 42, 42, 42, 42, "table2"); + List operations = Collections.singletonList(Put.of(key1, table1)); + Callable validator = () -> null; + BiConsumer addedContents = (k, v) -> {}; + + @Test + void testCommitSuccess() throws Exception { + CommitResult expectedResult = + CommitResult.builder() + .targetBranch(branch1) + .commit( + ImmutableCommit.builder() + .hash(hash1) + .commitMeta(commitMeta) + .operations(operations) + .build()) + .build(); + when(delegate.commit( + branch1, Optional.of(hash1), commitMeta, operations, validator, addedContents)) + .thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + CommitResult actualResult = + versionStore.commit( + branch1, Optional.of(hash1), commitMeta, operations, validator, addedContents); + assertThat(actualResult).isEqualTo(expectedResult); + verify(delegate) + .commit( + eq(branch1), + eq(Optional.of(hash1)), + eq(commitMeta), + eq(operations), + eq(validator), + eq(addedContents)); + verify(sink).accept(eq(expectedResult)); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceNotFoundException.class, ReferenceConflictException.class}) + void testCommitFailure(Class e) throws Exception { + when(delegate.commit( + branch1, Optional.of(hash1), commitMeta, operations, validator, addedContents)) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy( + () -> + versionStore.commit( + branch1, Optional.of(hash1), commitMeta, operations, validator, addedContents)) + .isInstanceOf(e); + verify(delegate) + .commit( + eq(branch1), + eq(Optional.of(hash1)), + eq(commitMeta), + eq(operations), + eq(validator), + eq(addedContents)); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testTransplantDryRun() throws Exception { + boolean dryRun = true; + MergeResult expectedResult = + MergeResult.builder() + .sourceBranch(branch1) + .targetBranch(branch2) + .resultType(ResultType.TRANSPLANT) + .effectiveTargetHash(hash1) + .resultantTargetHash(hash2) + .build(); + when(delegate.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false)) + .thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + MergeResult result = + versionStore.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false); + assertThat(result).isEqualTo(expectedResult); + verify(delegate) + .transplant( + eq(branch1), + eq(branch2), + eq(Optional.of(hash1)), + eq(Arrays.asList(hash1, hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(dryRun), + eq(false)); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testTransplantSuccessful() throws Exception { + boolean dryRun = false; + MergeResult expectedResult = + MergeResult.builder() + .sourceBranch(branch1) + .targetBranch(branch2) + .resultType(ResultType.TRANSPLANT) + .effectiveTargetHash(hash1) + .resultantTargetHash(hash2) + .build(); + when(delegate.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false)) + .thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + MergeResult result = + versionStore.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false); + assertThat(result).isEqualTo(expectedResult); + verify(delegate) + .transplant( + eq(branch1), + eq(branch2), + eq(Optional.of(hash1)), + eq(Arrays.asList(hash1, hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(dryRun), + eq(false)); + verify(sink).accept(expectedResult); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceNotFoundException.class, ReferenceConflictException.class}) + void testTransplantFailure(Class e) throws Exception { + when(delegate.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false)) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy( + () -> + versionStore.transplant( + branch1, + branch2, + Optional.of(hash1), + Arrays.asList(hash1, hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false)) + .isInstanceOf(e); + verify(delegate) + .transplant( + eq(branch1), + eq(branch2), + eq(Optional.of(hash1)), + eq(Arrays.asList(hash1, hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(false), + eq(false)); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testMergeDryRun() throws Exception { + boolean dryRun = true; + MergeResult expectedResult = + MergeResult.builder() + .sourceBranch(branch1) + .targetBranch(branch2) + .resultType(ResultType.MERGE) + .effectiveTargetHash(hash1) + .resultantTargetHash(hash2) + .build(); + when(delegate.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false)) + .thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + MergeResult result = + versionStore.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false); + assertThat(result).isEqualTo(expectedResult); + verify(delegate) + .merge( + eq(branch1), + eq(hash1), + eq(branch2), + eq(Optional.of(hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(dryRun), + eq(false)); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testMergeSuccessful() throws Exception { + boolean dryRun = false; + MergeResult expectedResult = + MergeResult.builder() + .sourceBranch(branch1) + .targetBranch(branch2) + .resultType(ResultType.MERGE) + .effectiveTargetHash(hash1) + .resultantTargetHash(hash2) + .build(); + when(delegate.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false)) + .thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + MergeResult result = + versionStore.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + dryRun, + false); + assertThat(result).isEqualTo(expectedResult); + verify(delegate) + .merge( + eq(branch1), + eq(hash1), + eq(branch2), + eq(Optional.of(hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(dryRun), + eq(false)); + verify(sink).accept(expectedResult); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceNotFoundException.class, ReferenceConflictException.class}) + void testMergeFailure(Class e) throws Exception { + when(delegate.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false)) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy( + () -> + versionStore.merge( + branch1, + hash1, + branch2, + Optional.of(hash2), + metadataRewriter, + false, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false)) + .isInstanceOf(e); + verify(delegate) + .merge( + eq(branch1), + eq(hash1), + eq(branch2), + eq(Optional.of(hash2)), + eq(metadataRewriter), + eq(false), + eq(Collections.emptyMap()), + eq(MergeBehavior.NORMAL), + eq(false), + eq(false)); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testAssignSuccess() throws Exception { + ReferenceAssignedResult expectedResult = + ImmutableReferenceAssignedResult.builder() + .namedRef(branch1) + .previousHash(hash1) + .currentHash(hash2) + .build(); + when(delegate.assign(branch1, Optional.of(hash1), hash2)).thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + ReferenceAssignedResult actualResult = versionStore.assign(branch1, Optional.of(hash1), hash2); + assertThat(actualResult).isEqualTo(expectedResult); + verify(delegate).assign(branch1, Optional.of(hash1), hash2); + verify(sink).accept(expectedResult); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceNotFoundException.class, ReferenceConflictException.class}) + void testAssignFailure(Class e) throws Exception { + when(delegate.assign(branch1, Optional.of(hash1), hash2)) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy(() -> versionStore.assign(branch1, Optional.of(hash1), hash2)) + .isInstanceOf(e); + verify(delegate).assign(branch1, Optional.of(hash1), hash2); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testCreateSuccess() throws Exception { + ReferenceCreatedResult expectedResult = + ImmutableReferenceCreatedResult.builder().namedRef(branch1).hash(hash2).build(); + when(delegate.create(branch1, Optional.of(hash1))).thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + ReferenceCreatedResult actualResult = versionStore.create(branch1, Optional.of(hash1)); + assertThat(actualResult).isEqualTo(expectedResult); + verify(delegate).create(branch1, Optional.of(hash1)); + verify(sink).accept(expectedResult); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceAlreadyExistsException.class, ReferenceConflictException.class}) + void testCreateFailure(Class e) throws Exception { + when(delegate.create(branch1, Optional.of(hash1))) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy(() -> versionStore.create(branch1, Optional.of(hash1))).isInstanceOf(e); + verify(delegate).create(branch1, Optional.of(hash1)); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testDeleteSuccess() throws Exception { + ReferenceDeletedResult expectedResult = + ImmutableReferenceDeletedResult.builder().namedRef(branch1).hash(hash2).build(); + when(delegate.delete(branch1, Optional.of(hash1))).thenReturn(expectedResult); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + ReferenceDeletedResult actualResult = versionStore.delete(branch1, Optional.of(hash1)); + assertThat(actualResult).isEqualTo(expectedResult); + verify(delegate).delete(branch1, Optional.of(hash1)); + verify(sink).accept(expectedResult); + verifyNoMoreInteractions(delegate, sink); + } + + @ParameterizedTest + @ValueSource(classes = {ReferenceNotFoundException.class, ReferenceConflictException.class}) + void testDeleteFailure(Class e) throws Exception { + when(delegate.delete(branch1, Optional.of(hash1))) + .thenAnswer( + invocation -> { + throw e.getConstructor(String.class).newInstance("irrelevant"); + }); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + assertThatThrownBy(() -> versionStore.delete(branch1, Optional.of(hash1))).isInstanceOf(e); + verify(delegate).delete(branch1, Optional.of(hash1)); + verifyNoMoreInteractions(delegate, sink); + } + + @Test + void testHashOnReferenceSuccess() throws ReferenceNotFoundException { + when(delegate.hashOnReference(branch1, Optional.of(hash1))).thenReturn(hash1); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + Hash actualHash = versionStore.hashOnReference(branch1, Optional.of(hash1)); + assertThat(actualHash).isEqualTo(hash1); + verify(delegate).hashOnReference(eq(branch1), eq(Optional.of(hash1))); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testNoAncestor() throws ReferenceNotFoundException { + when(delegate.noAncestorHash()).thenReturn(hash1); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + Hash actual = versionStore.noAncestorHash(); + assertThat(actual).isEqualTo(hash1); + verify(delegate).noAncestorHash(); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetNamedRef() throws Exception { + String ref = "refs/heads/master"; + GetNamedRefsParams params = GetNamedRefsParams.builder().build(); + ReferenceInfo expected = ReferenceInfo.of(hash1, branch1); + when(delegate.getNamedRef(ref, params)).thenReturn(expected); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + ReferenceInfo result = versionStore.getNamedRef(ref, params); + assertThat(result).isSameAs(expected); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetNamedRefs() throws Exception { + GetNamedRefsParams params = GetNamedRefsParams.builder().build(); + when(delegate.getNamedRefs(params, "token1")).thenReturn(iteratorInfos); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + PaginationIterator> result = + versionStore.getNamedRefs(params, "token1"); + assertThat(result).isSameAs(iteratorInfos); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetCommits() throws Exception { + boolean fetchAdditionalInfo = true; + when(delegate.getCommits(branch1, fetchAdditionalInfo)).thenReturn(iteratorCommits); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + PaginationIterator result = versionStore.getCommits(branch1, fetchAdditionalInfo); + assertThat(result).isSameAs(iteratorCommits); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetKeys() throws Exception { + when(delegate.getKeys(branch1, "token1", false)).thenReturn(iteratorKeyEntries); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + PaginationIterator result = versionStore.getKeys(branch1, "token1", false); + assertThat(result).isSameAs(iteratorKeyEntries); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetValue() throws Exception { + when(delegate.getValue(branch1, key1)).thenReturn(table1); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + Content result = versionStore.getValue(branch1, key1); + assertThat(result).isEqualTo(table1); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetValues() throws Exception { + Map expected = ImmutableMap.of(key1, table1, key2, table2); + when(delegate.getValues(branch1, Arrays.asList(key1, key2))).thenReturn(expected); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + Map result = versionStore.getValues(branch1, Arrays.asList(key1, key2)); + assertThat(result).isEqualTo(expected); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @Test + void testGetDiffs() throws Exception { + when(delegate.getDiffs(hash1, hash2, "token1")).thenReturn(iteratorDiffs); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + PaginationIterator result = versionStore.getDiffs(hash1, hash2, "token1"); + assertThat(result).isSameAs(iteratorDiffs); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } + + @SuppressWarnings("deprecation") + @Test + void testGetRefLog() throws Exception { + when(delegate.getRefLog(hash1)).thenReturn(refLogDetails); + EventsVersionStore versionStore = new EventsVersionStore(delegate, sink); + Stream result = versionStore.getRefLog(hash1); + assertThat(result).isSameAs(refLogDetails); + verifyNoMoreInteractions(delegate); + verifyNoInteractions(sink); + } +} diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java index e278686b12e..1ef58680d25 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java @@ -112,10 +112,48 @@ public CommitMeta squash(List metadata) { } }; + CommitResult dummyCommitResult = + CommitResult.builder() + .targetBranch(BranchName.of("foo")) + .commit( + Commit.builder() + .hash(Hash.of("cafebabe")) + .commitMeta(CommitMeta.fromMessage("log#1"))) + .build(); + MergeResult dummyMergeResult = MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceBranch(BranchName.of("foo")) + .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) - .targetBranch(BranchName.of("foo")) + .build(); + + MergeResult dummyTransplantResult = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceBranch(BranchName.of("foo")) + .targetBranch(BranchName.of("bar")) + .effectiveTargetHash(Hash.of("123456")) + .build(); + + ImmutableReferenceCreatedResult dummyRefCreatedResult = + ImmutableReferenceCreatedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .hash(Hash.of("cafebabedeadbeef")) + .build(); + + ImmutableReferenceAssignedResult dummyRefAssignedResult = + ImmutableReferenceAssignedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .previousHash(Hash.of("cafebabedeadbeef")) + .currentHash(Hash.of("12341234")) + .build(); + + ImmutableReferenceDeletedResult dummyRefDeletedResult = + ImmutableReferenceDeletedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .hash(Hash.of("cafebabedeadbeef")) .build(); // "Declare" test-invocations for all VersionStore functions with their respective outcomes @@ -137,12 +175,13 @@ public CommitMeta squash(List metadata) { Collections.emptyList(), () -> null, (k, c) -> {}), - () -> Hash.of("cafebabedeadbeef"), + () -> dummyCommitResult, refNotFoundAndRefConflictThrows), new VersionStoreInvocation<>( "transplant", vs -> vs.transplant( + BranchName.of("source-branch"), BranchName.of("mock-branch"), Optional.empty(), Collections.emptyList(), @@ -152,12 +191,13 @@ public CommitMeta squash(List metadata) { MergeBehavior.NORMAL, false, false), - () -> dummyMergeResult, + () -> dummyTransplantResult, refNotFoundAndRefConflictThrows), new VersionStoreInvocation<>( "merge", vs -> vs.merge( + BranchName.of("source-branch"), Hash.of("42424242"), BranchName.of("mock-branch"), Optional.empty(), @@ -173,16 +213,17 @@ public CommitMeta squash(List metadata) { "assign", vs -> vs.assign(BranchName.of("mock-branch"), Optional.empty(), Hash.of("12341234")), + () -> dummyRefAssignedResult, refNotFoundAndRefConflictThrows), new VersionStoreInvocation<>( "create", vs -> vs.create(BranchName.of("mock-branch"), Optional.of(Hash.of("cafebabe"))), - () -> Hash.of("cafebabedeadbeef"), + () -> dummyRefCreatedResult, refNotFoundAndRefAlreadyExistsThrows), new VersionStoreInvocation<>( "delete", vs -> vs.delete(BranchName.of("mock-branch"), Optional.of(Hash.of("cafebabe"))), - () -> Hash.of("cafebabedeadbeef"), + () -> dummyRefDeletedResult, refNotFoundAndRefConflictThrows), new VersionStoreInvocation<>( "getcommits", @@ -350,18 +391,6 @@ static class VersionStoreInvocation { this.result = result; this.failures = failures; } - - VersionStoreInvocation( - String opName, ThrowingConsumer function, List failures) { - this.opName = opName; - this.function = - vs -> { - function.accept(vs); - return null; - }; - this.result = null; - this.failures = failures; - } } @FunctionalInterface diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java index 5712b291631..12eccfd267e 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java @@ -58,7 +58,7 @@ import org.projectnessie.model.IcebergTable; import org.projectnessie.model.MergeBehavior; import org.projectnessie.versioned.paging.PaginationIterator; -import org.projectnessie.versioned.test.tracing.TestedTraceingStoreInvocation; +import org.projectnessie.versioned.test.tracing.TestedTracingStoreInvocation; class TestTracingVersionStore { @@ -106,23 +106,61 @@ public CommitMeta squash(List metadata) { } }; + CommitResult dummyCommitResult = + CommitResult.builder() + .targetBranch(BranchName.of("foo")) + .commit( + Commit.builder() + .hash(Hash.of("cafebabe")) + .commitMeta(CommitMeta.fromMessage("log#1"))) + .build(); + MergeResult dummyMergeResult = MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceBranch(BranchName.of("foo")) + .targetBranch(BranchName.of("bar")) + .effectiveTargetHash(Hash.of("123456")) + .build(); + + MergeResult dummyTransplantResult = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceBranch(BranchName.of("foo")) + .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) - .targetBranch(BranchName.of("foo")) + .build(); + + ImmutableReferenceCreatedResult dummyRefCreatedResult = + ImmutableReferenceCreatedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .hash(Hash.of("cafebabedeadbeef")) + .build(); + + ImmutableReferenceAssignedResult dummyRefAssignedResult = + ImmutableReferenceAssignedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .previousHash(Hash.of("cafebabedeadbeef")) + .currentHash(Hash.of("12341234")) + .build(); + + ImmutableReferenceDeletedResult dummyRefDeletedResult = + ImmutableReferenceDeletedResult.builder() + .namedRef(BranchName.of("mock-branch")) + .hash(Hash.of("cafebabedeadbeef")) .build(); // "Declare" test-invocations for all VersionStore functions with their respective outcomes // and exceptions. @SuppressWarnings("unchecked") - Stream> versionStoreFunctions = + Stream> versionStoreFunctions = Stream.of( - new TestedTraceingStoreInvocation("GetNamedRef", refNotFoundThrows) + new TestedTracingStoreInvocation("GetNamedRef", refNotFoundThrows) .tag("nessie.version-store.ref", "mock-branch") .function( vs -> vs.getNamedRef("mock-branch", GetNamedRefsParams.DEFAULT), () -> ReferenceInfo.of(Hash.of("cafebabe"), BranchName.of("mock-branch"))), - new TestedTraceingStoreInvocation( + new TestedTracingStoreInvocation( "Commit", refNotFoundAndRefConflictThrows) .tag("nessie.version-store.branch", "mock-branch") .tag("nessie.version-store.num-ops", 0) @@ -136,8 +174,8 @@ public CommitMeta squash(List metadata) { Collections.emptyList(), () -> null, (k, c) -> {}), - () -> Hash.of("deadbeefcafebabe")), - new TestedTraceingStoreInvocation( + () -> dummyCommitResult), + new TestedTracingStoreInvocation( "Transplant", refNotFoundAndRefConflictThrows) .tag("nessie.version-store.target-branch", "mock-branch") .tag("nessie.version-store.transplants", 0) @@ -145,6 +183,7 @@ public CommitMeta squash(List metadata) { .function( vs -> vs.transplant( + BranchName.of("source-branch"), BranchName.of("mock-branch"), Optional.empty(), Collections.emptyList(), @@ -154,15 +193,15 @@ public CommitMeta squash(List metadata) { MergeBehavior.NORMAL, false, false), - () -> dummyMergeResult), - new TestedTraceingStoreInvocation( - "Merge", refNotFoundAndRefConflictThrows) + () -> dummyTransplantResult), + new TestedTracingStoreInvocation("Merge", refNotFoundAndRefConflictThrows) .tag("nessie.version-store.to-branch", "mock-branch") .tag("nessie.version-store.from-hash", "Hash 42424242") .tag("nessie.version-store.expected-hash", "Optional.empty") .function( vs -> vs.merge( + BranchName.of("source-branch"), Hash.of("42424242"), BranchName.of("mock-branch"), Optional.empty(), @@ -173,30 +212,31 @@ public CommitMeta squash(List metadata) { false, false), () -> dummyMergeResult), - new TestedTraceingStoreInvocation( + new TestedTracingStoreInvocation( "Assign", refNotFoundAndRefConflictThrows) .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .tag("nessie.version-store.target-hash", "Hash 12341234") .tag("nessie.version-store.expected-hash", "Optional.empty") - .method( + .function( vs -> vs.assign( - BranchName.of("mock-branch"), Optional.empty(), Hash.of("12341234"))), - new TestedTraceingStoreInvocation( + BranchName.of("mock-branch"), Optional.empty(), Hash.of("12341234")), + () -> dummyRefAssignedResult), + new TestedTracingStoreInvocation( "Create", refNotFoundAndRefAlreadyExistsThrows) .tag("nessie.version-store.target-hash", "Optional[Hash cafebabe]") .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .function( vs -> vs.create(BranchName.of("mock-branch"), Optional.of(Hash.of("cafebabe"))), - () -> Hash.of("deadbeefcafebabe")), - new TestedTraceingStoreInvocation( + () -> dummyRefCreatedResult), + new TestedTracingStoreInvocation( "Delete", refNotFoundAndRefConflictThrows) .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .tag("nessie.version-store.hash", "Optional[Hash cafebabe]") .function( vs -> vs.delete(BranchName.of("mock-branch"), Optional.of(Hash.of("cafebabe"))), - () -> Hash.of("deadbeefcafebabe")), - new TestedTraceingStoreInvocation("GetCommits.stream", refNotFoundThrows) + () -> dummyRefDeletedResult), + new TestedTracingStoreInvocation("GetCommits.stream", refNotFoundThrows) .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .function( vs -> vs.getCommits(BranchName.of("mock-branch"), false), @@ -210,12 +250,12 @@ public CommitMeta squash(List metadata) { .hash(Hash.of("deadbeef")) .commitMeta(CommitMeta.fromMessage("log#2")) .build())), - new TestedTraceingStoreInvocation("GetKeys.stream", refNotFoundThrows) + new TestedTracingStoreInvocation("GetKeys.stream", refNotFoundThrows) .tag("nessie.version-store.ref", "Hash cafe4242") .function( vs -> vs.getKeys(Hash.of("cafe4242"), null, false), () -> PaginationIterator.of(ContentKey.of("hello", "world"))), - new TestedTraceingStoreInvocation("GetNamedRefs.stream", runtimeThrows) + new TestedTracingStoreInvocation("GetNamedRefs.stream", runtimeThrows) .function( stringStringDummyEnumVersionStore -> stringStringDummyEnumVersionStore.getNamedRefs( @@ -224,13 +264,13 @@ public CommitMeta squash(List metadata) { PaginationIterator.of( WithHash.of(Hash.of("cafebabe"), BranchName.of("foo")), WithHash.of(Hash.of("deadbeef"), BranchName.of("cow")))), - new TestedTraceingStoreInvocation("GetValue", refNotFoundThrows) + new TestedTracingStoreInvocation("GetValue", refNotFoundThrows) .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .tag("nessie.version-store.key", "some.key") .function( vs -> vs.getValue(BranchName.of("mock-branch"), ContentKey.of("some", "key")), () -> IcebergTable.of("meta", 42, 43, 44, 45)), - new TestedTraceingStoreInvocation("GetValues", refNotFoundThrows) + new TestedTracingStoreInvocation("GetValues", refNotFoundThrows) .tag("nessie.version-store.ref", "BranchName{name=mock-branch}") .tag("nessie.version-store.keys", "[some.key]") .function( @@ -239,7 +279,7 @@ public CommitMeta squash(List metadata) { BranchName.of("mock-branch"), Collections.singletonList(ContentKey.of("some", "key"))), Collections::emptyMap), - new TestedTraceingStoreInvocation("GetDiffs.stream", refNotFoundThrows) + new TestedTracingStoreInvocation("GetDiffs.stream", refNotFoundThrows) .tag("nessie.version-store.from", "BranchName{name=mock-branch}") .tag("nessie.version-store.to", "BranchName{name=foo-branch}") .function( @@ -248,13 +288,13 @@ public CommitMeta squash(List metadata) { BranchName.of("mock-branch"), BranchName.of("foo-branch"), null), PaginationIterator::empty)); - return TestedTraceingStoreInvocation.toArguments(versionStoreFunctions); + return TestedTracingStoreInvocation.toArguments(versionStoreFunctions); } @ParameterizedTest @MethodSource("versionStoreInvocations") void versionStoreInvocation( - TestedTraceingStoreInvocation invocation, Exception expectedThrow) + TestedTracingStoreInvocation invocation, Exception expectedThrow) throws Throwable { boolean isServerError = diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTraceingStoreInvocation.java b/versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTracingStoreInvocation.java similarity index 73% rename from versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTraceingStoreInvocation.java rename to versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTracingStoreInvocation.java index 38e1001b22e..d1ce650040e 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTraceingStoreInvocation.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/test/tracing/TestedTracingStoreInvocation.java @@ -21,7 +21,6 @@ import java.util.Map; import java.util.function.Supplier; import java.util.stream.Stream; -import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.jupiter.params.provider.Arguments; /** @@ -31,7 +30,7 @@ * * @param store type */ -public class TestedTraceingStoreInvocation { +public class TestedTracingStoreInvocation { final String opName; Map tags = new HashMap<>(); List> logs = new ArrayList<>(); @@ -39,21 +38,16 @@ public class TestedTraceingStoreInvocation { Supplier result; final List failures; - public TestedTraceingStoreInvocation(String opName, List failures) { + public TestedTracingStoreInvocation(String opName, List failures) { this.opName = opName; this.failures = failures; } - public TestedTraceingStoreInvocation tag(String tag, Object value) { + public TestedTracingStoreInvocation tag(String tag, Object value) { this.tags.put(tag, value); return this; } - public TestedTraceingStoreInvocation log(Map log) { - this.logs.add(log); - return this; - } - /** * The function to be tested. * @@ -62,7 +56,7 @@ public TestedTraceingStoreInvocation log(Map log) { * @param result type * @return {@code this} */ - public TestedTraceingStoreInvocation function( + public TestedTracingStoreInvocation function( ThrowingFunction function, Supplier result) { this.function = function; this.result = result; @@ -70,32 +64,17 @@ public TestedTraceingStoreInvocation function( } /** - * The method (function returning {@code void}) to be tested. - * - * @param method method to be tested - * @return {@code this} - */ - public TestedTraceingStoreInvocation method(ThrowingConsumer method) { - this.function = - store -> { - method.accept(store); - return null; - }; - return this; - } - - /** - * Convert a stream of {@link TestedTraceingStoreInvocation}s to a stream of {@link Arguments}, - * which are pairs of {@link TestedTraceingStoreInvocation} plus {@link Exception}, which are the + * Convert a stream of {@link TestedTracingStoreInvocation}s to a stream of {@link Arguments}, + * which are pairs of {@link TestedTracingStoreInvocation} plus {@link Exception}, which are the * arguments for the parameterized tests. * - * @param versionStoreFunctions stream of {@link TestedTraceingStoreInvocation}s + * @param versionStoreFunctions stream of {@link TestedTracingStoreInvocation}s * @param store type, a {@code Store} or {@code VersionStore} - * @return Stream of {@link Arguments} (pairs of {@link TestedTraceingStoreInvocation} plus {@link + * @return Stream of {@link Arguments} (pairs of {@link TestedTracingStoreInvocation} plus {@link * Exception}); */ public static Stream toArguments( - Stream> versionStoreFunctions) { + Stream> versionStoreFunctions) { // flatten all "normal executions" + "throws XYZ" return versionStoreFunctions.flatMap( invocation -> { diff --git a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java index 4da42f5dcc0..84ae49c0f0f 100644 --- a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java +++ b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java @@ -114,7 +114,7 @@ public void fetchCommit() throws Exception { assertThat(commitLogic.fetchCommit(EMPTY_OBJ_ID)).isNull(); - ObjId commitId = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())); + ObjId commitId = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())).id(); TagObj tag = TagObj.tag(randomObjId(), commitId, null, null, ByteString.EMPTY); soft.assertThat(persist.storeObj(tag)).isTrue(); @@ -133,15 +133,16 @@ public void fetchCommit() throws Exception { public void commonAncestor() throws Exception { CommitLogic commitLogic = commitLogic(persist); - ObjId root = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())); + ObjId root = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())).id(); ObjId commonAncestor = root; for (int i = 0; i < 5; i++) { commonAncestor = - commitLogic.doCommit( - stdCommit().parentCommitId(commonAncestor).message("Commit #" + i).build(), - emptyList()); - soft.assertThat(commonAncestor).isNotNull(); + requireNonNull( + commitLogic.doCommit( + stdCommit().parentCommitId(commonAncestor).message("Commit #" + i).build(), + emptyList())) + .id(); } ObjId[] branches = new ObjId[5]; @@ -149,12 +150,14 @@ public void commonAncestor() throws Exception { for (int branch = 0; branch < 5; branch++) { for (int i = 0; i < 5; i++) { branches[branch] = - commitLogic.doCommit( - stdCommit() - .parentCommitId(branches[branch]) - .message("Branch " + branch + " commit #" + i) - .build(), - emptyList()); + requireNonNull( + commitLogic.doCommit( + stdCommit() + .parentCommitId(branches[branch]) + .message("Branch " + branch + " commit #" + i) + .build(), + emptyList())) + .id(); } } @@ -183,30 +186,36 @@ public void noCommonAncestor() throws Exception { ObjId branch1commit1 = requireNonNull( - commitLogic.doCommit(stdCommit().message("branch1commit1").build(), emptyList())); + commitLogic.doCommit(stdCommit().message("branch1commit1").build(), emptyList())) + .id(); ObjId branch1commit2 = requireNonNull( - commitLogic.doCommit( - stdCommit().message("branch1commit2").parentCommitId(branch1commit1).build(), - emptyList())); + commitLogic.doCommit( + stdCommit().message("branch1commit2").parentCommitId(branch1commit1).build(), + emptyList())) + .id(); ObjId branch1commit3 = requireNonNull( - commitLogic.doCommit( - stdCommit().message("branch1commit3").parentCommitId(branch1commit2).build(), - emptyList())); + commitLogic.doCommit( + stdCommit().message("branch1commit3").parentCommitId(branch1commit2).build(), + emptyList())) + .id(); ObjId branch2commit1 = requireNonNull( - commitLogic.doCommit(stdCommit().message("branch2commit1").build(), emptyList())); + commitLogic.doCommit(stdCommit().message("branch2commit1").build(), emptyList())) + .id(); ObjId branch2commit2 = requireNonNull( - commitLogic.doCommit( - stdCommit().message("branch2commit2").parentCommitId(branch2commit1).build(), - emptyList())); + commitLogic.doCommit( + stdCommit().message("branch2commit2").parentCommitId(branch2commit1).build(), + emptyList())) + .id(); ObjId branch2commit3 = requireNonNull( - commitLogic.doCommit( - stdCommit().message("branch2commit3").parentCommitId(branch2commit2).build(), - emptyList())); + commitLogic.doCommit( + stdCommit().message("branch2commit3").parentCommitId(branch2commit2).build(), + emptyList())) + .id(); soft.assertThatThrownBy(() -> commitLogic.findCommonAncestor(branch1commit1, branch2commit1)) .isInstanceOf(NoSuchElementException.class) @@ -260,7 +269,7 @@ public void commitLog() throws Exception { soft.assertThat(newArrayList(commitLogic.commitLog(commitLogQuery(EMPTY_OBJ_ID)))).isEmpty(); - ObjId tip = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())); + ObjId tip = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())).id(); List tail = new ArrayList<>(); tail.add(EMPTY_OBJ_ID); @@ -282,8 +291,9 @@ public void commitLog() throws Exception { String msg = "commit #" + i; tip = requireNonNull( - commitLogic.doCommit( - stdCommit().parentCommitId(tip).message(msg).build(), emptyList())); + commitLogic.doCommit( + stdCommit().parentCommitId(tip).message(msg).build(), emptyList())) + .id(); expected.add(0, tuple(new ArrayList<>(tail), msg, 2L + i)); } @@ -336,7 +346,7 @@ public void commitIdLog() throws Exception { soft.assertThat(newArrayList(commitLogic.commitIdLog(commitLogQuery(EMPTY_OBJ_ID)))).isEmpty(); - ObjId tip = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())); + ObjId tip = requireNonNull(commitLogic.doCommit(stdCommit().build(), emptyList())).id(); List expected = new ArrayList<>(); expected.add(tip); @@ -349,8 +359,9 @@ public void commitIdLog() throws Exception { String msg = "commit #" + i; tip = requireNonNull( - commitLogic.doCommit( - stdCommit().parentCommitId(tip).message(msg).build(), emptyList())); + commitLogic.doCommit( + stdCommit().parentCommitId(tip).message(msg).build(), emptyList())) + .id(); expected.add(0, tip); } @@ -436,8 +447,10 @@ public void diff( throws Exception { CommitLogic commitLogic = commitLogic(persist); - ObjId commitId1 = requireNonNull(commitLogic.doCommit(commitBuilder1.build(), emptyList())); - ObjId commitId2 = requireNonNull(commitLogic.doCommit(commitBuilder2.build(), emptyList())); + ObjId commitId1 = + requireNonNull(commitLogic.doCommit(commitBuilder1.build(), emptyList())).id(); + ObjId commitId2 = + requireNonNull(commitLogic.doCommit(commitBuilder2.build(), emptyList())).id(); CommitObj commit1 = commitLogic.fetchCommit(commitId1); CommitObj commit2 = commitLogic.fetchCommit(commitId2); @@ -498,22 +511,24 @@ public void diffWithPaging() throws Exception { ObjId commitId1 = requireNonNull( - commitLogic.doCommit( - stdCommit() - .addAdds(commitAdd(key("aaa"), 0, idAaa, null, cidAaa)) - .addAdds(commitAdd(key("ccc"), 0, idCcc, null, cidCcc)) - .addAdds(commitAdd(key("eee"), 0, idEee, null, cidEee)) - .build(), - emptyList())); + commitLogic.doCommit( + stdCommit() + .addAdds(commitAdd(key("aaa"), 0, idAaa, null, cidAaa)) + .addAdds(commitAdd(key("ccc"), 0, idCcc, null, cidCcc)) + .addAdds(commitAdd(key("eee"), 0, idEee, null, cidEee)) + .build(), + emptyList())) + .id(); ObjId commitId2 = requireNonNull( - commitLogic.doCommit( - stdCommit() - .addAdds(commitAdd(key("bbb"), 0, idBbb, null, cidBbb)) - .addAdds(commitAdd(key("ddd"), 0, idDdd, null, cidDdd)) - .addAdds(commitAdd(key("fff"), 0, idFff, null, cidFff)) - .build(), - emptyList())); + commitLogic.doCommit( + stdCommit() + .addAdds(commitAdd(key("bbb"), 0, idBbb, null, cidBbb)) + .addAdds(commitAdd(key("ddd"), 0, idDdd, null, cidDdd)) + .addAdds(commitAdd(key("fff"), 0, idFff, null, cidFff)) + .build(), + emptyList())) + .id(); CommitObj commit1 = commitLogic.fetchCommit(commitId1); CommitObj commit2 = commitLogic.fetchCommit(commitId2); @@ -555,24 +570,26 @@ public void diffToCreateCommit() throws Exception { ObjId idEee = randomObjId(); ObjId commitId1 = requireNonNull( - commitLogic.doCommit( - stdCommit() - .addAdds(commitAdd(key("aaa"), 0, idAaa, null, null)) - .addAdds(commitAdd(key("bbb"), 0, idBbb, null, null)) - .addAdds(commitAdd(key("ccc"), 0, idCcc, null, null)) - .build(), - emptyList())); + commitLogic.doCommit( + stdCommit() + .addAdds(commitAdd(key("aaa"), 0, idAaa, null, null)) + .addAdds(commitAdd(key("bbb"), 0, idBbb, null, null)) + .addAdds(commitAdd(key("ccc"), 0, idCcc, null, null)) + .build(), + emptyList())) + .id(); ObjId commitId2 = requireNonNull( - commitLogic.doCommit( - stdCommit() - .parentCommitId(commitId1) - .addAdds(commitAdd(key("ccc"), 0, idCcc2, idCcc, null)) - .addAdds(commitAdd(key("ddd"), 0, idDdd, null, null)) - .addAdds(commitAdd(key("eee"), 0, idEee, null, null)) - .addRemoves(commitRemove(key("bbb"), 0, idBbb, null)) - .build(), - emptyList())); + commitLogic.doCommit( + stdCommit() + .parentCommitId(commitId1) + .addAdds(commitAdd(key("ccc"), 0, idCcc2, idCcc, null)) + .addAdds(commitAdd(key("ddd"), 0, idDdd, null, null)) + .addAdds(commitAdd(key("eee"), 0, idEee, null, null)) + .addRemoves(commitRemove(key("bbb"), 0, idBbb, null)) + .build(), + emptyList())) + .id(); CommitObj commit1 = commitLogic.fetchCommit(commitId1); CommitObj commit2 = commitLogic.fetchCommit(commitId2); @@ -598,13 +615,14 @@ public void headCommit() throws Exception { CommitLogic commitLogic = commitLogic(persist); ObjId tip = requireNonNull( - commitLogic.doCommit( - newCommitBuilder() - .headers(EMPTY_COMMIT_HEADERS) - .message("msg foo") - .parentCommitId(EMPTY_OBJ_ID) - .build(), - emptyList())); + commitLogic.doCommit( + newCommitBuilder() + .headers(EMPTY_COMMIT_HEADERS) + .message("msg foo") + .parentCommitId(EMPTY_OBJ_ID) + .build(), + emptyList())) + .id(); Reference ref = refLogic.createReference("foo", tip); soft.assertThat(commitLogic.headCommit(ref)) .extracting(CommitObj::message) @@ -763,7 +781,7 @@ private void prepareReferences( private ObjId addCommits(CommitLogic commitLogic, int numCommits, ObjId head, int branchNum) throws Exception { for (int commitNum = 0; commitNum < numCommits; commitNum++) { - head = + CommitObj commit = commitLogic.doCommit( newCommitBuilder() .headers(EMPTY_COMMIT_HEADERS) @@ -772,7 +790,8 @@ private ObjId addCommits(CommitLogic commitLogic, int numCommits, ObjId head, in "commit #" + commitNum + " of " + numCommits + " - unifier: " + branchNum) .build(), emptyList()); - checkState(head != null); + checkState(commit != null); + head = commit.id(); } return head; diff --git a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractRepositoryLogicTests.java b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractRepositoryLogicTests.java index 2f610b28761..731c39da2fa 100644 --- a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractRepositoryLogicTests.java +++ b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractRepositoryLogicTests.java @@ -133,13 +133,14 @@ public void emptyRepositoryDescription() throws Exception { CommitLogic commitLogic = commitLogic(persist); ObjId tip = requireNonNull( - commitLogic.doCommit( - CreateCommit.newCommitBuilder() - .parentCommitId(EMPTY_OBJ_ID) - .headers(EMPTY_COMMIT_HEADERS) - .message("no key") - .build(), - emptyList())); + commitLogic.doCommit( + CreateCommit.newCommitBuilder() + .parentCommitId(EMPTY_OBJ_ID) + .headers(EMPTY_COMMIT_HEADERS) + .message("no key") + .build(), + emptyList())) + .id(); ref = persist.updateReferencePointer(ref, tip); soft.assertThat(ref.pointer()).isEqualTo(tip); soft.assertThat(repositoryLogic.fetchRepositoryDescription()).isNull(); diff --git a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogic.java b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogic.java index 01d14dc6408..832c79ce5ec 100644 --- a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogic.java +++ b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogic.java @@ -63,12 +63,12 @@ PagedResult commitIdLog( * @param createCommit parameters for {@link #buildCommitObj(CreateCommit, ConflictHandler, * CommitOpHandler, ValueReplacement, ValueReplacement)} * @param additionalObjects additional {@link Obj}s to store, for example {@link ContentValueObj} - * @return the non-null object ID if the commit was stored as a new record or {@code null} if an + * @return the non-null commit, if the commit was stored as a new record, or {@code null} if an * object with the same ID already exists. */ @Nullable @jakarta.annotation.Nullable - ObjId doCommit( + CommitObj doCommit( @Nonnull @jakarta.annotation.Nonnull CreateCommit createCommit, @Nonnull @jakarta.annotation.Nonnull List additionalObjects) throws CommitConflictException, ObjNotFoundException; diff --git a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogicImpl.java b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogicImpl.java index a06b28b5a24..498ea662ceb 100644 --- a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogicImpl.java +++ b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/CommitLogicImpl.java @@ -280,14 +280,14 @@ public PagingToken tokenForKey(ObjId key) { @Nullable @jakarta.annotation.Nullable @Override - public ObjId doCommit( + public CommitObj doCommit( @Nonnull @jakarta.annotation.Nonnull CreateCommit createCommit, @Nonnull @jakarta.annotation.Nonnull List additionalObjects) throws CommitConflictException, ObjNotFoundException { CommitObj commit = buildCommitObj( createCommit, c -> CONFLICT, (k, v) -> {}, NO_VALUE_REPLACEMENT, NO_VALUE_REPLACEMENT); - return storeCommit(commit, additionalObjects) ? commit.id() : null; + return storeCommit(commit, additionalObjects) ? commit : null; } @Override diff --git a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/ReferenceLogicImpl.java b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/ReferenceLogicImpl.java index 342a60b1ec1..090410c4f97 100644 --- a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/ReferenceLogicImpl.java +++ b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/ReferenceLogicImpl.java @@ -521,18 +521,18 @@ void commitDeleteReference(Reference reference) throws RetryTimeoutException { private static void commitReferenceChange(Persist p, Reference refRefs, CreateCommit c) throws CommitConflictException, RetryException { - ObjId commitId; + CommitObj commit; try { - commitId = commitLogic(p).doCommit(c, emptyList()); + commit = commitLogic(p).doCommit(c, emptyList()); } catch (ObjNotFoundException e) { throw new RuntimeException("Internal error committing to log of references", e); } - checkState(commitId != null); + checkState(commit != null); // Commit to REF_REFS try { - p.updateReferencePointer(refRefs, commitId); + p.updateReferencePointer(refRefs, commit.id()); } catch (RefConditionFailedException e) { throw new RetryException(); } catch (RefNotFoundException e) { diff --git a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/RepositoryLogicImpl.java b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/RepositoryLogicImpl.java index 0f58b015fe3..9ac09c148d5 100644 --- a/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/RepositoryLogicImpl.java +++ b/versioned/storage/common/src/main/java/org/projectnessie/versioned/storage/common/logic/RepositoryLogicImpl.java @@ -52,7 +52,6 @@ import org.projectnessie.versioned.storage.common.objtypes.CommitType; import org.projectnessie.versioned.storage.common.objtypes.Compression; import org.projectnessie.versioned.storage.common.objtypes.StringObj; -import org.projectnessie.versioned.storage.common.persist.ObjId; import org.projectnessie.versioned.storage.common.persist.Persist; import org.projectnessie.versioned.storage.common.persist.Reference; @@ -196,15 +195,15 @@ private void initializeInternalRef( commitEnhancer.accept(c); CommitLogic commitLogic = commitLogic(persist); - ObjId commitId; + CommitObj commit; try { - commitId = commitLogic.doCommit(c.build(), emptyList()); + commit = commitLogic.doCommit(c.build(), emptyList()); } catch (CommitConflictException | ObjNotFoundException e) { throw new RuntimeException(e); } try { - persist.addReference(reference(internalRef.name(), commitId, false)); + persist.addReference(reference(internalRef.name(), commit.id(), false)); } catch (RefAlreadyExistsException ignore) { // ignore an existing reference (theoretically possible race of two initialize() calls) } diff --git a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestCommitConflicts.java b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestCommitConflicts.java index c77b7d7c819..99db2014bae 100644 --- a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestCommitConflicts.java +++ b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestCommitConflicts.java @@ -46,7 +46,6 @@ import static org.projectnessie.versioned.storage.common.objtypes.CommitOp.commitOp; import static org.projectnessie.versioned.storage.common.persist.ObjId.objIdFromString; import static org.projectnessie.versioned.storage.common.persist.ObjId.randomObjId; -import static org.projectnessie.versioned.storage.common.persist.ObjType.COMMIT; import static org.projectnessie.versioned.storage.commontests.AbstractCommitLogicTests.stdCommit; import java.util.ArrayList; @@ -101,16 +100,18 @@ public void conflictAddNewToExisting() throws Exception { ObjId addObjId = objIdFromString("0000"); ObjId otherObjId = objIdFromString("0001"); - ObjId tip = + CommitObj tip = commitLogic.doCommit( stdCommit().addAdds(commitAdd(key, 0, addObjId, null, null)).build(), emptyList()); - soft.assertThat(tip).isNotNull(); + assertThat(tip).isNotNull(); soft.assertThatThrownBy( () -> buildCommit( commitLogic, - b -> b.parentCommitId(tip).addAdds(commitAdd(key, 0, addObjId, null, null)))) + b -> + b.parentCommitId(tip.id()) + .addAdds(commitAdd(key, 0, addObjId, null, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_EXISTS:hello") .asInstanceOf(type(CommitConflictException.class)) @@ -123,7 +124,9 @@ public void conflictAddNewToExisting() throws Exception { () -> buildCommit( commitLogic, - b -> b.parentCommitId(tip).addAdds(commitAdd(key, 0, otherObjId, null, null)))) + b -> + b.parentCommitId(tip.id()) + .addAdds(commitAdd(key, 0, otherObjId, null, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_EXISTS:hello") .asInstanceOf(type(CommitConflictException.class)) @@ -137,10 +140,13 @@ public void conflictAddNewToExisting() throws Exception { // remove, try again - ObjId tip2 = removeAndTryAgain(commitLogic, key, addObjId, tip); + CommitObj tip2 = removeAndTryAgain(commitLogic, key, addObjId, tip.id()); commitLogic.doCommit( - stdCommit().parentCommitId(tip2).addAdds(commitAdd(key, 0, addObjId, null, null)).build(), + stdCommit() + .parentCommitId(tip2.id()) + .addAdds(commitAdd(key, 0, addObjId, null, null)) + .build(), emptyList()); // verify key index @@ -162,17 +168,17 @@ public void conflictWithWrongExpected() throws Exception { ObjId wrongObjId = objIdFromString("0001"); ObjId replaceObjId = objIdFromString("0002"); - ObjId tip = + CommitObj tip = commitLogic.doCommit( stdCommit().addAdds(commitAdd(key, 0, addObjId, null, null)).build(), emptyList()); - soft.assertThat(tip).isNotNull(); + assertThat(tip).isNotNull(); soft.assertThatThrownBy( () -> buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addAdds(commitAdd(key, 0, replaceObjId, wrongObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: VALUE_DIFFERS:hello") @@ -188,7 +194,7 @@ public void conflictWithWrongExpected() throws Exception { commitLogic, b -> b.message("hello") - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key, 0, wrongObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: VALUE_DIFFERS:hello") @@ -203,7 +209,7 @@ public void conflictWithWrongExpected() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addUnchanged(commitUnchanged(key, 0, wrongObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: VALUE_DIFFERS:hello") @@ -218,7 +224,7 @@ public void conflictWithWrongExpected() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addAdds(commitAdd(key, 0, replaceObjId, wrongObjId, randomUUID())))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: CONTENT_ID_DIFFERS:hello") @@ -233,7 +239,7 @@ public void conflictWithWrongExpected() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addUnchanged(commitUnchanged(key, 0, replaceObjId, randomUUID())))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: CONTENT_ID_DIFFERS:hello") @@ -248,7 +254,7 @@ public void conflictWithWrongExpected() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addRemoves(commitRemove(key, 0, wrongObjId, randomUUID())))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: CONTENT_ID_DIFFERS:hello") @@ -270,17 +276,17 @@ public void conflictWithWrongPayload() throws Exception { ObjId addObjId = objIdFromString("0000"); ObjId replaceObjId = objIdFromString("0002"); - ObjId tip = + CommitObj tip = commitLogic.doCommit( stdCommit().addAdds(commitAdd(key, 0, addObjId, null, null)).build(), emptyList()); - soft.assertThat(tip).isNotNull(); + assertThat(tip).isNotNull(); soft.assertThatThrownBy( () -> buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addAdds(commitAdd(key, 1, replaceObjId, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: PAYLOAD_DIFFERS:hello") @@ -294,7 +300,9 @@ public void conflictWithWrongPayload() throws Exception { () -> buildCommit( commitLogic, - b -> b.parentCommitId(tip).addRemoves(commitRemove(key, 1, addObjId, null)))) + b -> + b.parentCommitId(tip.id()) + .addRemoves(commitRemove(key, 1, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: PAYLOAD_DIFFERS:hello") .asInstanceOf(type(CommitConflictException.class)) @@ -308,7 +316,7 @@ public void conflictWithWrongPayload() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addUnchanged(commitUnchanged(key, 1, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: PAYLOAD_DIFFERS:hello") @@ -331,17 +339,17 @@ public void conflictNonExisting() throws Exception { ObjId addObjId = objIdFromString("0000"); ObjId replaceObjId = objIdFromString("0002"); - ObjId tip = + CommitObj tip = commitLogic.doCommit( stdCommit().addAdds(commitAdd(key, 0, addObjId, null, null)).build(), emptyList()); - soft.assertThat(tip).isNotNull(); + assertThat(tip).isNotNull(); soft.assertThatThrownBy( () -> buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addAdds(commitAdd(nonExistingKey, 1, replaceObjId, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_DOES_NOT_EXIST:non-existing") @@ -356,7 +364,7 @@ public void conflictNonExisting() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addRemoves(commitRemove(nonExistingKey, 0, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_DOES_NOT_EXIST:non-existing") @@ -370,13 +378,15 @@ public void conflictNonExisting() throws Exception { verifyKeyIndex(key, addObjId, tip); // remove added, try remove again - ObjId tip2 = removeAndTryAgain(commitLogic, key, addObjId, tip); + CommitObj tip2 = removeAndTryAgain(commitLogic, key, addObjId, tip.id()); soft.assertThatThrownBy( () -> buildCommit( commitLogic, - b -> b.parentCommitId(tip2).addRemoves(commitRemove(key, 0, addObjId, null)))) + b -> + b.parentCommitId(tip2.id()) + .addRemoves(commitRemove(key, 0, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_DOES_NOT_EXIST:hello") .asInstanceOf(type(CommitConflictException.class)) @@ -390,7 +400,7 @@ public void conflictNonExisting() throws Exception { buildCommit( commitLogic, b -> - b.parentCommitId(tip2) + b.parentCommitId(tip2.id()) .addUnchanged(commitUnchanged(key, 0, addObjId, null)))) .isInstanceOf(CommitConflictException.class) .hasMessage("Commit conflict: KEY_DOES_NOT_EXIST:hello") @@ -405,9 +415,10 @@ StoreIndex buildCompleteIndex(CommitObj c) { return indexesLogic(persist).buildCompleteIndex(c, Optional.empty()); } - private ObjId removeAndTryAgain(CommitLogic commitLogic, StoreKey key, ObjId addObjId, ObjId tip) + private CommitObj removeAndTryAgain( + CommitLogic commitLogic, StoreKey key, ObjId addObjId, ObjId tip) throws CommitConflictException, ObjNotFoundException { - ObjId tip2 = + CommitObj tip2 = requireNonNull( commitLogic.doCommit( stdCommit() @@ -417,7 +428,7 @@ private ObjId removeAndTryAgain(CommitLogic commitLogic, StoreKey key, ObjId add emptyList())); // verify key index - soft.assertThat(persist.fetchTypedObj(tip2, COMMIT, CommitObj.class)) + soft.assertThat(tip2) .extracting(this::buildCompleteIndex) .satisfies(i -> assertThat(i.elementCount()).isEqualTo(1)) .satisfies(i -> assertThat(existingFromIndex(i, key)).isNull()) @@ -427,8 +438,8 @@ private ObjId removeAndTryAgain(CommitLogic commitLogic, StoreKey key, ObjId add return tip2; } - private void verifyKeyIndex(StoreKey key, ObjId addObjId, ObjId tip) throws ObjNotFoundException { - soft.assertThat(persist.fetchTypedObj(tip, COMMIT, CommitObj.class)) + private void verifyKeyIndex(StoreKey key, ObjId addObjId, CommitObj tip) { + soft.assertThat(tip) .extracting(this::buildCompleteIndex) .satisfies(i -> assertThat(i.elementCount()).isEqualTo(1)) .extracting(i -> existingFromIndex(i, key)) @@ -631,14 +642,14 @@ public void commitReaddContent(int payload1, int payload2, UUID contentId1, UUID ObjId addObjId = objIdFromString("0000"); ObjId replaceObjId = objIdFromString("0002"); - ObjId tip = + CommitObj tip = requireNonNull( commitLogic.doCommit( stdCommit().addAdds(commitAdd(key, payload1, addObjId, null, contentId1)).build(), emptyList())); StoreIndex index = - indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip)); + indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip.id())); soft.assertThat(index.get(key)) .extracting( e -> e.content().payload(), @@ -652,21 +663,21 @@ public void commitReaddContent(int payload1, int payload2, UUID contentId1, UUID buildCommit( commitLogic, b -> - b.parentCommitId(tip) + b.parentCommitId(tip.id()) .addAdds(commitAdd(key, payload2, replaceObjId, null, contentId2)))) .isInstanceOf(CommitConflictException.class); - ObjId tip2 = + CommitObj tip2 = requireNonNull( commitLogic.doCommit( stdCommit() - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key, payload1, addObjId, contentId1)) .addAdds(commitAdd(key, payload2, replaceObjId, null, contentId2)) .build(), emptyList())); - index = indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip2)); + index = indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip2.id())); soft.assertThat(index.get(key)) .extracting( e -> e.content().payload(), @@ -689,14 +700,14 @@ public void commitRenameAndReAddMustFail() throws Exception { StoreKey key1 = key("base"); StoreKey key2 = key("rename-to"); - ObjId tip = + CommitObj tip = requireNonNull( commitLogic.doCommit( stdCommit().addAdds(commitAdd(key1, payload1, addObjId, null, contentId)).build(), emptyList())); StoreIndex index = - indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip)); + indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip.id())); soft.assertThat(index.get(key1)) .extracting( e -> e.content().payload(), @@ -710,7 +721,7 @@ public void commitRenameAndReAddMustFail() throws Exception { () -> commitLogic.doCommit( stdCommit() - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key1, payload1, addObjId, contentId)) // rename .addAdds(commitAdd(key2, payload1, addObjId, null, contentId)) @@ -724,7 +735,7 @@ public void commitRenameAndReAddMustFail() throws Exception { () -> commitLogic.doCommit( stdCommit() - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key1, payload1, addObjId, contentId)) // rename .addAdds(commitAdd(key2, payload1, addObjId, addObjId, contentId)) @@ -756,14 +767,14 @@ public void commitRenameKey(ObjId addObjId, ObjId expectedValue, UUID contentId) StoreKey key1 = key("rename-from"); StoreKey key2 = key("rename-to"); - ObjId tip = + CommitObj tip = requireNonNull( commitLogic.doCommit( stdCommit().addAdds(commitAdd(key1, payload, addObjId, null, contentId)).build(), emptyList())); StoreIndex index = - indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip)); + indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip.id())); soft.assertThat(index.get(key1)) .extracting( e -> e.content().payload(), @@ -772,17 +783,17 @@ public void commitRenameKey(ObjId addObjId, ObjId expectedValue, UUID contentId) e -> e.content().contentId()) .containsExactly(payload, addObjId, ADD, contentId); - ObjId tip2 = + CommitObj tip2 = requireNonNull( commitLogic.doCommit( stdCommit() - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key1, payload, addObjId, contentId)) .addAdds(commitAdd(key2, payload, addObjId, expectedValue, contentId)) .build(), emptyList())); - index = indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip2)); + index = indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip2.id())); soft.assertThat(index.get(key1)) .extracting( e -> e.content().payload(), @@ -823,14 +834,14 @@ public void commitRenameKeyFailure( StoreKey key1 = key("rename-from"); StoreKey key2 = key("rename-to"); - ObjId tip = + CommitObj tip = requireNonNull( commitLogic.doCommit( stdCommit().addAdds(commitAdd(key1, payload, addObjId, null, contentId)).build(), emptyList())); StoreIndex index = - indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip)); + indexesLogic(persist).buildCompleteIndexOrEmpty(commitLogic.fetchCommit(tip.id())); soft.assertThat(index.get(key1)) .extracting( e -> e.content().payload(), @@ -843,7 +854,7 @@ public void commitRenameKeyFailure( () -> commitLogic.doCommit( stdCommit() - .parentCommitId(tip) + .parentCommitId(tip.id()) .addRemoves(commitRemove(key1, payload, addObjId, contentId)) .addAdds(commitAdd(key2, payload, addObjId, expectedValue, contentId)) .build(), diff --git a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java index 17ccd71a85b..d18eacec865 100644 --- a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java +++ b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java @@ -16,6 +16,8 @@ package org.projectnessie.versioned.storage.common.logic; import static java.util.Collections.emptyList; +import static java.util.Objects.requireNonNull; +import static org.assertj.core.api.Assertions.assertThat; import static org.projectnessie.versioned.storage.common.indexes.StoreIndexElement.indexElement; import static org.projectnessie.versioned.storage.common.indexes.StoreIndexes.newStoreIndex; import static org.projectnessie.versioned.storage.common.indexes.StoreKey.key; @@ -76,7 +78,7 @@ public void completeIndexesInCommitChain(boolean discrete) throws Exception { } ObjId secondaryHeadId = secondary.get(0); CommitObj secondaryHead = commitLogic.fetchCommit(secondaryHeadId); - soft.assertThat(secondaryHead).isNotNull(); + assertThat(secondaryHead).isNotNull(); soft.assertThatIllegalArgumentException() .isThrownBy(() -> indexesLogic.buildCompleteIndex(secondaryHead, Optional.empty())); @@ -94,7 +96,7 @@ public void completeIndexesInCommitChain(boolean discrete) throws Exception { ObjId headId = tail.get(0); CommitObj head = commitLogic.fetchCommit(headId); - soft.assertThat(head).isNotNull(); + assertThat(head).isNotNull(); soft.assertThatIllegalArgumentException() .isThrownBy(() -> indexesLogic.buildCompleteIndex(head, Optional.empty())); @@ -200,7 +202,7 @@ private List fiveCompleteCommits(Map keyValue) throws Ex ObjId v = randomObjId(); soft.assertThat(keyValue.put(k, v)).isNull(); - headId = + CommitObj commit = commitLogic.doCommit( newCommitBuilder() .parentCommitId(headId) @@ -209,6 +211,7 @@ private List fiveCompleteCommits(Map keyValue) throws Ex .headers(EMPTY_COMMIT_HEADERS) .build(), emptyList()); + headId = requireNonNull(commit).id(); tail.add(0, headId); } diff --git a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestReferenceIndexes.java b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestReferenceIndexes.java index af3b748c2dc..acba09e097c 100644 --- a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestReferenceIndexes.java +++ b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestReferenceIndexes.java @@ -176,7 +176,7 @@ public void referenceIndexLifecycle( // Remove all keys added above. for (int i = REF_INDEX_LIFECYCLE_TEST_CYCLES_EMBEDDED - 1; i >= 0; i--) { - head = requireNonNull(commitLogic.doCommit(remove.apply(head, i), emptyList())); + head = requireNonNull(commitLogic.doCommit(remove.apply(head, i), emptyList())).id(); CommitObj commit = requireNonNull(persist.fetchTypedObj(head, COMMIT, CommitObj.class)); soft.assertThat(commit.referenceIndex()).isNull(); soft.assertThat(commit.referenceIndexStripes()).isEmpty(); @@ -197,7 +197,7 @@ public void referenceIndexLifecycle( // Adds new keys, one per commits. // Loop until it has to spill out to reference index stripes... for (num = 0; ; num++) { - head = requireNonNull(commitLogic.doCommit(add.apply(head, num), emptyList())); + head = requireNonNull(commitLogic.doCommit(add.apply(head, num), emptyList())).id(); CommitObj commit = requireNonNull(persist.fetchTypedObj(head, COMMIT, CommitObj.class)); @@ -285,7 +285,7 @@ public void referenceIndexLifecycle( // Remove keys now... until we're back at "embedded" reference segments list (no longer need // ObjType.INDEX_SEGMENTS)... for (num--; num >= 0; num--) { - head = requireNonNull(commitLogic.doCommit(remove.apply(head, num), emptyList())); + head = requireNonNull(commitLogic.doCommit(remove.apply(head, num), emptyList())).id(); CommitObj commit = requireNonNull(persist.fetchTypedObj(head, COMMIT, CommitObj.class)); @@ -311,7 +311,7 @@ public void referenceIndexLifecycle( // Remove keys now... until we're done removing all keys... // Can't get back to "incremental only" w/o another "spill out". for (num--; num >= 0; num--) { - head = requireNonNull(commitLogic.doCommit(remove.apply(head, num), emptyList())); + head = requireNonNull(commitLogic.doCommit(remove.apply(head, num), emptyList())).id(); CommitObj commit = requireNonNull(persist.fetchTypedObj(head, COMMIT, CommitObj.class)); @@ -355,7 +355,7 @@ private ObjId commitWithValues( .extracting(ObjNotFoundException::objIds) .asInstanceOf(list(ObjId.class)) .hasSize(values.size()); - head = requireNonNull(commitLogic.doCommit(add.apply(head, num), values)); + head = requireNonNull(commitLogic.doCommit(add.apply(head, num), values)).id(); soft.assertThat(persist.fetchObjs(values.stream().map(Obj::id).toArray(ObjId[]::new))) .doesNotContainNull(); return head; @@ -449,7 +449,7 @@ public void commitWithReferenceIndex( } soft.assertThat(knownKeys.size()).describedAs("num keys: %d", numKeys).isEqualTo(numKeys); - tip = requireNonNull(commitLogic.doCommit(createCommit.build(), emptyList())); + tip = requireNonNull(commitLogic.doCommit(createCommit.build(), emptyList())).id(); commitIds.add(tip); soft.assertThat(tip).describedAs("num keys: %d", numKeys).isNotNull(); @@ -542,7 +542,7 @@ public void commitWithReferenceIndex( createCommit.addAdds(commitAdd(key, 0, value, expected, null)); } - tip = requireNonNull(commitLogic.doCommit(createCommit.build(), emptyList())); + tip = requireNonNull(commitLogic.doCommit(createCommit.build(), emptyList())).id(); commitIds.add(tip); soft.assertThat(tip).describedAs("num keys: %d", numKeys).isNotNull(); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java index 31ef9da7819..26648f9052b 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java @@ -520,7 +520,7 @@ ImmutableMergeResult mergeSquashFastForward( CommitObj source, ImmutableMergeResult.Builder result, MergeBehaviors mergeBehaviors) - throws RetryException { + throws RetryException, ReferenceNotFoundException { result.wasSuccessful(true); IndexesLogic indexesLogic = indexesLogic(persist); @@ -539,6 +539,8 @@ ImmutableMergeResult mergeSquashFastForward( result.wasApplied(true).resultantTargetHash(objIdToHash(fromId)); } + result.addAddedCommits(commitObjToCommit(source)); + return result.build(); } @@ -734,4 +736,13 @@ MergeResult finishMergeTransplant( return mergeResult.build(); } + + Commit commitObjToCommit(CommitObj newCommit) throws ReferenceNotFoundException { + try { + ContentMapping contentMapping = new ContentMapping(persist); + return contentMapping.commitObjToCommit(true, newCommit); + } catch (ObjNotFoundException e) { + throw referenceNotFound(e); + } + } } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java index 58ed8bffb1d..24733539782 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java @@ -42,6 +42,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.indexes.StoreIndexElement; import org.projectnessie.versioned.storage.common.logic.CommitLogic; @@ -103,8 +104,16 @@ MergeResult individualCommits( if (!dryRun) { commitLogic.storeCommit(newCommit, objsToStore); newHead = newCommit.id(); + try { + // We need to fetch the existing commit in order to return the correct object. + // The existing commit may have a different set of parents than the new commit. + newCommit = commitLogic.fetchCommit(newCommit.id()); + } catch (ObjNotFoundException ignored) { + // cannot happen + } } + mergeResult.addAddedCommits(commitObjToCommit(newCommit)); sourceParentIndex = indexesLogic.buildCompleteIndex(sourceCommit, Optional.empty()); targetParentIndex = indexesLogic.buildCompleteIndex(newCommit, Optional.empty()); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java index ff4d309cab0..ee1e50e627d 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java @@ -40,6 +40,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.indexes.StoreKey; import org.projectnessie.versioned.storage.common.logic.CommitLogic; @@ -106,8 +107,16 @@ MergeResult squash( CommitLogic commitLogic = commitLogic(persist); commitLogic.storeCommit(mergeCommit, objsToStore); newHead = mergeCommit.id(); + try { + // We need to fetch the existing commit in order to return the correct object. + // The existing commit may have a different set of parents than the new commit. + mergeCommit = commitLogic.fetchCommit(mergeCommit.id()); + } catch (ObjNotFoundException ignored) { + // cannot happen + } } + mergeResult.addAddedCommits(commitObjToCommit(mergeCommit)); return finishMergeTransplant(false, mergeResult, newHead, dryRun, hasConflicts); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java index 480dd060a73..1ca02e5e087 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java @@ -33,7 +33,6 @@ import static org.projectnessie.versioned.storage.versionstore.RefMapping.referenceNotFound; import static org.projectnessie.versioned.storage.versionstore.TypeMapping.fromCommitMeta; import static org.projectnessie.versioned.storage.versionstore.TypeMapping.keyToStoreKey; -import static org.projectnessie.versioned.storage.versionstore.TypeMapping.objIdToHash; import static org.projectnessie.versioned.store.DefaultStoreWorker.payloadForContent; import java.util.ArrayList; @@ -55,8 +54,11 @@ import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.ImmutableCommitResult; import org.projectnessie.versioned.Operation; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.ReferenceConflictException; @@ -83,6 +85,8 @@ class CommitImpl extends BaseCommitHelper { private final StoreIndex headIndex; private final StoreIndex expectedIndex; + private final ContentMapping contentMapping; + private final CommitLogic commitLogic; CommitImpl( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @@ -92,7 +96,8 @@ class CommitImpl extends BaseCommitHelper { @Nullable @jakarta.annotation.Nullable CommitObj head) throws ReferenceNotFoundException { super(branch, referenceHash, persist, reference, head); - + commitLogic = commitLogic(persist); + contentMapping = new ContentMapping(persist); this.headIndex = lazyStoreIndex( () -> { @@ -130,7 +135,7 @@ static class CommitRetryState { final Map generatedContentIds = new HashMap<>(); } - Hash commit( + CommitResult commit( @Nonnull @jakarta.annotation.Nonnull Optional retryState, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @Nonnull @jakarta.annotation.Nonnull List operations, @@ -170,26 +175,28 @@ Hash commit( fromCommitMeta(metadata, commit); - ObjId newHead; try { - CommitLogic commitLogic = commitLogic(persist); - newHead = commitLogic.doCommit(commit.build(), objectsToStore); + CommitObj newHead = commitLogic.doCommit(commit.build(), objectsToStore); + + checkState( + newHead != null, + "Hash collision detected, a commit with the same parent commit, commit message, " + + "headers/commit-metadata and operations already exists"); + + bumpReferencePointer(newHead.id(), Optional.of(commitRetryState)); + + commitRetryState.generatedContentIds.forEach(addedContents); + + return ImmutableCommitResult.builder() + .commit(contentMapping.commitObjToCommit(true, newHead)) + .targetBranch((BranchName) RefMapping.referenceToNamedRef(reference)) + .build(); + } catch (CommitConflictException e) { throw referenceConflictException(e); } catch (ObjNotFoundException e) { throw referenceNotFound(e); } - - checkState( - newHead != null, - "Hash collision detected, a commit with the same parent commit, commit message, " - + "headers/commit-metadata and operations already exists"); - - bumpReferencePointer(newHead, Optional.of(commitRetryState)); - - commitRetryState.generatedContentIds.forEach(addedContents); - - return objIdToHash(newHead); } void commitAddOperations( @@ -347,8 +354,6 @@ private void commitAddPut( UUID existingContentID; String expectedContentIDString; - ContentMapping contentMapping = new ContentMapping(persist); - StoreIndexElement existing = expectedIndex.get(storeKey); if (existing == null && putValueId != null) { // Check for a Delete-op in the same commit, representing a rename operation. @@ -412,6 +417,6 @@ private void commitAddPut( private String contentIdFromContent(@Nonnull @jakarta.annotation.Nonnull ObjId contentValueId) throws ObjNotFoundException { - return new ContentMapping(persist).fetchContent(contentValueId).getId(); + return contentMapping.fetchContent(contentValueId).getId(); } } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index 43ed000cc0d..6462e73ad60 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -34,7 +34,7 @@ import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.ImmutableCommit; -import org.projectnessie.versioned.Put; +import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.StoreWorker; import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndexElement; @@ -132,7 +132,6 @@ public Commit commitObjToCommit( if (fetchAdditionalInfo) { ContentKey key; - ContentMapping contentMapping = new ContentMapping(persist); IndexesLogic indexesLogic = indexesLogic(persist); for (StoreIndexElement op : indexesLogic.commitOperations(commitObj)) { key = storeKeyToKey(op.key()); @@ -140,11 +139,10 @@ public Commit commitObjToCommit( if (key != null) { CommitOp c = op.content(); if (c.action().exists()) { - commit.addOperations( - Put.of( - key, - contentMapping.fetchContent( - requireNonNull(c.value(), "Required value pointer is null")))); + ObjId objId = requireNonNull(c.value(), "Required value pointer is null"); + ContentValueObj contentValue = + persist.fetchTypedObj(objId, VALUE, ContentValueObj.class); + commit.addOperations(LazyPut.of(key, contentValue.payload(), contentValue.data())); } else { commit.addOperations(Delete.of(key)); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java index 74624af119b..f74b0f53b4d 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java @@ -17,6 +17,7 @@ import java.util.Optional; import org.projectnessie.model.CommitMeta; +import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeResult; @@ -28,6 +29,7 @@ interface Merge { MergeResult merge( Optional retryState, + BranchName fromBranch, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java index f8081148afb..c4de17d3cad 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java @@ -32,6 +32,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; @@ -54,6 +55,7 @@ final class MergeIndividualImpl extends BaseMergeTransplantIndividual implements @Override public MergeResult merge( Optional retryState, + BranchName fromBranch, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -70,7 +72,10 @@ public MergeResult merge( } ImmutableMergeResult.Builder mergeResult = - prepareMergeResult().commonAncestor(objIdToHash(commonAncestorId)); + prepareMergeResult() + .resultType(ResultType.MERGE) + .sourceBranch(fromBranch) + .commonAncestor(objIdToHash(commonAncestorId)); // Fast-forward, if possible if (commonAncestorId.equals(headId()) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java index 95da59e95de..88a000a87ae 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java @@ -30,6 +30,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.persist.ObjId; @@ -51,6 +52,7 @@ final class MergeSquashImpl extends BaseMergeTransplantSquash implements Merge { @Override public MergeResult merge( Optional retryState, + BranchName fromBranch, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -62,7 +64,10 @@ public MergeResult merge( SourceCommitsAndParent sourceCommits = loadSourceCommitsForMerge(fromId, commonAncestorId); ImmutableMergeResult.Builder mergeResult = - prepareMergeResult().commonAncestor(objIdToHash(commonAncestorId)); + prepareMergeResult() + .resultType(ResultType.MERGE) + .sourceBranch(fromBranch) + .commonAncestor(objIdToHash(commonAncestorId)); return squash(dryRun, mergeResult, mergeBehaviors, updateCommitMetadata, sourceCommits, fromId); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java index 30b67d8bfb0..27abcf197df 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Optional; import org.projectnessie.model.CommitMeta; +import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeResult; @@ -29,6 +30,7 @@ interface Transplant { MergeResult transplant( Optional retryState, + BranchName sourceBranch, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java index 50ffd7e0d37..d6990639bff 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java @@ -28,6 +28,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.persist.Persist; @@ -48,6 +49,7 @@ final class TransplantIndividualImpl extends BaseMergeTransplantIndividual imple @Override public MergeResult transplant( Optional retryState, + BranchName sourceBranch, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -55,7 +57,8 @@ public MergeResult transplant( throws ReferenceNotFoundException, RetryException, ReferenceConflictException { SourceCommitsAndParent sourceCommits = loadSourceCommitsForTransplant(sequenceToTransplant); - ImmutableMergeResult.Builder mergeResult = prepareMergeResult(); + ImmutableMergeResult.Builder mergeResult = + prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceBranch(sourceBranch); return individualCommits( updateCommitMetadata, dryRun, mergeResult, mergeBehaviors, sourceCommits); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java index a8c99ed7b22..42d97a6d562 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java @@ -28,6 +28,7 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.persist.Persist; @@ -48,6 +49,7 @@ final class TransplantSquashImpl extends BaseMergeTransplantSquash implements Tr @Override public MergeResult transplant( Optional retryState, + BranchName sourceBranch, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -55,7 +57,8 @@ public MergeResult transplant( throws ReferenceNotFoundException, RetryException, ReferenceConflictException { SourceCommitsAndParent sourceCommits = loadSourceCommitsForTransplant(sequenceToTransplant); - ImmutableMergeResult.Builder mergeResult = prepareMergeResult(); + ImmutableMergeResult.Builder mergeResult = + prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceBranch(sourceBranch); return squash(dryRun, mergeResult, mergeBehaviors, updateCommitMetadata, sourceCommits, null); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java index 2180ae23fbe..2f713e60e33 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java @@ -72,10 +72,14 @@ import org.projectnessie.model.MergeKeyBehavior; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Diff; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.GetNamedRefsParams.RetrieveOptions; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.ImmutableReferenceAssignedResult; +import org.projectnessie.versioned.ImmutableReferenceCreatedResult; +import org.projectnessie.versioned.ImmutableReferenceDeletedResult; import org.projectnessie.versioned.ImmutableReferenceInfo; import org.projectnessie.versioned.ImmutableRepositoryInformation; import org.projectnessie.versioned.KeyEntry; @@ -87,7 +91,10 @@ import org.projectnessie.versioned.Ref; import org.projectnessie.versioned.RefLogDetails; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceInfo.CommitsAheadBehind; import org.projectnessie.versioned.ReferenceNotFoundException; @@ -165,7 +172,7 @@ public Hash hashOnReference(NamedRef namedRef, Optional hashOnReference) } @Override - public Hash create(NamedRef namedRef, Optional targetHash) + public ReferenceCreatedResult create(NamedRef namedRef, Optional targetHash) throws ReferenceNotFoundException, ReferenceAlreadyExistsException { ReferenceLogic referenceLogic = referenceLogic(persist); try { @@ -190,8 +197,11 @@ public Hash create(NamedRef namedRef, Optional targetHash) // as the tag being created) already exists. throw referenceAlreadyExists(namedRef); } catch (RefNotFoundException good) { - return objIdToHash( - referenceLogic.createReference(namedRefToRefName(namedRef), objId).pointer()); + Reference reference = referenceLogic.createReference(namedRefToRefName(namedRef), objId); + return ImmutableReferenceCreatedResult.builder() + .namedRef(namedRef) + .hash(objIdToHash(reference.pointer())) + .build(); } } catch (RefAlreadyExistsException e) { throw referenceAlreadyExists(namedRef); @@ -203,7 +213,8 @@ public Hash create(NamedRef namedRef, Optional targetHash) } @Override - public void assign(NamedRef namedRef, Optional expectedHash, Hash targetHash) + public ReferenceAssignedResult assign( + NamedRef namedRef, Optional expectedHash, Hash targetHash) throws ReferenceNotFoundException, ReferenceConflictException { String refName = namedRefToRefName(namedRef); ReferenceLogic referenceLogic = referenceLogic(persist); @@ -228,6 +239,12 @@ public void assign(NamedRef namedRef, Optional expectedHash, Hash targetHa } referenceLogic.assignReference(expected, newPointer); + return ImmutableReferenceAssignedResult.builder() + .namedRef(namedRef) + .previousHash(objIdToHash(expected.pointer())) + .currentHash(objIdToHash(newPointer)) + .build(); + } catch (RefNotFoundException e) { throw referenceNotFound(namedRef); } catch (RefConditionFailedException e) { @@ -239,7 +256,7 @@ public void assign(NamedRef namedRef, Optional expectedHash, Hash targetHa } @Override - public Hash delete(NamedRef namedRef, Optional hash) + public ReferenceDeletedResult delete(NamedRef namedRef, Optional hash) throws ReferenceNotFoundException, ReferenceConflictException { String refName = namedRefToRefName(namedRef); ReferenceLogic referenceLogic = referenceLogic(persist); @@ -251,7 +268,11 @@ public Hash delete(NamedRef namedRef, Optional hash) ? hashToObjId(hash.get()) : referenceLogic.getReference(refName).pointer(); referenceLogic.deleteReference(refName, expected); - return objIdToHash(expected); + return ImmutableReferenceDeletedResult.builder() + .namedRef(namedRef) + .hash(objIdToHash(expected)) + .build(); + } catch (RefNotFoundException e) { throw referenceNotFound(namedRef); } catch (RefConditionFailedException e) { @@ -595,7 +616,7 @@ public Map getValues(Ref ref, Collection keys) } @Override - public Hash commit( + public CommitResult commit( @Nonnull @jakarta.annotation.Nonnull BranchName branch, @Nonnull @jakarta.annotation.Nonnull Optional referenceHash, @Nonnull @jakarta.annotation.Nonnull CommitMeta metadata, @@ -615,6 +636,7 @@ public Hash commit( @Override public MergeResult merge( + BranchName fromBranch, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -644,13 +666,20 @@ public MergeResult merge( persist, supplier, (merge, retryState) -> - merge.merge(retryState, fromHash, updateCommitMetadata, mergeBehaviors, dryRun)); + merge.merge( + retryState, + fromBranch, + fromHash, + updateCommitMetadata, + mergeBehaviors, + dryRun)); return mergeTransplantResponse(mergeResult); } @Override public MergeResult transplant( + BranchName sourceBranch, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -682,6 +711,7 @@ public MergeResult transplant( (transplant, retryState) -> transplant.transplant( retryState, + sourceBranch, sequenceToTransplant, updateCommitMetadata, mergeBehaviors, diff --git a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java index 0956fdfd847..baecbcc66d0 100644 --- a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java +++ b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java @@ -50,7 +50,7 @@ import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.ImmutableCommit; -import org.projectnessie.versioned.Put; +import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.objtypes.CommitOp; @@ -226,7 +226,9 @@ public void commitsWithAdditionalInfo() throws Exception { .hash(objIdToHash(id)) .parentHash(objIdToHash(EMPTY_OBJ_ID)) .commitMeta(referenceCommitMeta) - .addOperations(Delete.of(ContentKey.of("bar")), Put.of(ContentKey.of("foo"), table)) + .addOperations( + Delete.of(ContentKey.of("bar")), + LazyPut.of(ContentKey.of("foo"), tableObj.payload(), tableObj.data())) .build(); Commit c = contentMapping.commitObjToCommit(true, commitObj); diff --git a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestRefMapping.java b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestRefMapping.java index cf1840b4268..b54a9607f47 100644 --- a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestRefMapping.java +++ b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestRefMapping.java @@ -18,6 +18,7 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.projectnessie.versioned.storage.common.indexes.StoreKey.key; import static org.projectnessie.versioned.storage.common.logic.CommitConflict.ConflictType.CONTENT_ID_DIFFERS; @@ -265,7 +266,7 @@ public void resolveRefs() throws Exception { ReferenceLogic referenceLogic = referenceLogic(persist); RefMapping refMapping = new RefMapping(persist); - ObjId commitId = generateCommit(EMPTY_OBJ_ID, "foo", 42); + ObjId commitId = generateCommit(EMPTY_OBJ_ID, "foo", 42).id(); Reference branch = referenceLogic.createReference(REFS_HEADS + "branch", commitId); Reference tag = referenceLogic.createReference(REFS_TAGS + "tag", commitId); @@ -357,20 +358,21 @@ private List generateCommits(String msg) throws Exception { ObjId head = EMPTY_OBJ_ID; List r = new ArrayList<>(); for (int i = 0; i < 10; i++) { - head = generateCommit(head, msg, i); + head = generateCommit(head, msg, i).id(); r.add(head); } return r; } - private ObjId generateCommit(ObjId head, String msg, int i) throws Exception { - return commitLogic(persist) - .doCommit( - newCommitBuilder() - .parentCommitId(head) - .message("commit " + msg + " " + i) - .headers(EMPTY_COMMIT_HEADERS) - .build(), - emptyList()); + private CommitObj generateCommit(ObjId head, String msg, int i) throws Exception { + return requireNonNull( + commitLogic(persist) + .doCommit( + newCommitBuilder() + .parentCommitId(head) + .message("commit " + msg + " " + i) + .headers(EMPTY_COMMIT_HEADERS) + .build(), + emptyList())); } } diff --git a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestVersionStoreImpl.java b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestVersionStoreImpl.java index 7adcaf33d77..166ea26b3f0 100644 --- a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestVersionStoreImpl.java +++ b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestVersionStoreImpl.java @@ -65,7 +65,7 @@ public void commitWithInfiniteConcurrentConflict( VersionStore store = new VersionStoreImpl(persist); BranchName branch = BranchName.of("branch1"); - Hash branch1 = store.create(branch, Optional.empty()); + Hash branch1 = store.create(branch, Optional.empty()).getHash(); AtomicInteger intercepted = new AtomicInteger(); @@ -119,7 +119,7 @@ public void commitWithSingleConcurrentConflict() throws Exception { VersionStore store = new VersionStoreImpl(persist); BranchName branch = BranchName.of("branch1"); - Hash branch1 = store.create(branch, Optional.empty()); + Hash branch1 = store.create(branch, Optional.empty()).getHash(); AtomicBoolean intercepted = new AtomicBoolean(); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java index 6b5649bae4c..8dcbaa6642f 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java @@ -115,13 +115,13 @@ public void assignReferenceToFreshMain() } BranchName testBranch = BranchName.of("testBranch"); - Hash testBranchHash = store.create(testBranch, Optional.empty()); + Hash testBranchHash = store.create(testBranch, Optional.empty()).getHash(); store.assign(testBranch, Optional.of(testBranchHash), main.getHash()); soft.assertThat(store.getNamedRef(testBranch.getName(), GetNamedRefsParams.DEFAULT).getHash()) .isEqualTo(main.getHash()); TagName testTag = TagName.of("testTag"); - Hash testTagHash = store.create(testTag, Optional.empty()); + Hash testTagHash = store.create(testTag, Optional.empty()).getHash(); store.assign(testTag, Optional.of(testTagHash), main.getHash()); soft.assertThat(store.getNamedRef(testTag.getName(), GetNamedRefsParams.DEFAULT).getHash()) .isEqualTo(main.getHash()); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java index 69104392ef1..b61997b269b 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java @@ -56,7 +56,7 @@ protected AbstractCommitLog(VersionStore store) { @Test public void commitLogPaging() throws Exception { BranchName branch = BranchName.of("commitLogPaging"); - Hash createHash = store().create(branch, Optional.empty()); + Hash createHash = store().create(branch, Optional.empty()).getHash(); int commits = 95; // this should be enough Hash[] commitHashes = new Hash[commits]; @@ -77,7 +77,10 @@ public void commitLogPaging() throws Exception { Put op = value != null ? Put.of(key, onRef(str, value.getId())) : Put.of(key, newOnRef(str)); commitHashes[i] = - store().commit(branch, Optional.of(parent), msg.build(), ImmutableList.of(op)); + store() + .commit(branch, Optional.of(parent), msg.build(), ImmutableList.of(op)) + .getCommit() + .getHash(); messages.add( msg.hash(commitHashes[i].asString()).addParentCommitHashes(parent.asString()).build()); @@ -119,7 +122,7 @@ public void commitLogPaging() throws Exception { @Test public void commitLogExtended() throws Exception { BranchName branch = BranchName.of("commitLogExtended"); - Hash firstParent = store().create(branch, Optional.empty()); + Hash firstParent = store().create(branch, Optional.empty()).getHash(); int numCommits = 10; diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java index 4e7430e324c..b94281e199f 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java @@ -85,7 +85,7 @@ protected AbstractCommits(VersionStore store) { public void commitToBranch() throws Exception { final BranchName branch = BranchName.of("foo"); - final Hash createHash = store().create(branch, Optional.empty()); + final Hash createHash = store().create(branch, Optional.empty()).getHash(); final Hash initialHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(createHash).isEqualTo(initialHash); @@ -95,7 +95,9 @@ public void commitToBranch() throws Exception { branch, Optional.of(initialHash), CommitMeta.fromMessage("Some commit"), - Collections.emptyList()); + Collections.emptyList()) + .getCommit() + .getHash(); final Hash commitHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(commitHash).isEqualTo(commitHash0); @@ -142,7 +144,7 @@ public void commitToBranch() throws Exception { public void commitSomeOperations() throws Exception { BranchName branch = BranchName.of("foo"); - Hash base = store().create(branch, Optional.empty()); + Hash base = store().create(branch, Optional.empty()).getHash(); Hash initialCommit = commit("Initial Commit") @@ -251,7 +253,7 @@ public void commitSomeOperations() throws Exception { public void commitNonConflictingOperations() throws Exception { BranchName branch = BranchName.of("foo"); - Hash base = store().create(branch, Optional.empty()); + Hash base = store().create(branch, Optional.empty()).getHash(); Hash initialCommit = commit("Initial Commit") diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java index 92b10ba83a5..601f75e1bcc 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java @@ -29,6 +29,8 @@ import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.Put; @@ -63,7 +65,7 @@ void recreateTable() throws Exception { // commit just something to have a "real" common ancestor and not "beginning of time", which // means no-common-ancestor Content initialState = newOnRef("value"); - Hash ancestor = + CommitResult ancestor = store() .commit( branch, @@ -71,9 +73,10 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("create table"), singletonList(Put.of(key, initialState))); soft.assertThat(contentWithoutId(store().getValue(branch, key))).isEqualTo(initialState); - soft.assertThat(contentWithoutId(store().getValue(ancestor, key))).isEqualTo(initialState); + soft.assertThat(contentWithoutId(store().getValue(ancestor.getCommit().getHash(), key))) + .isEqualTo(initialState); - Hash delete = + CommitResult delete = store() .commit( branch, @@ -81,10 +84,10 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("drop table"), ImmutableList.of(Delete.of(key))); soft.assertThat(store().getValue(branch, key)).isNull(); - soft.assertThat(store().getValue(delete, key)).isNull(); + soft.assertThat(store().getValue(delete.getCommit().getHash(), key)).isNull(); Content recreateState = newOnRef("value"); - Hash recreate = + CommitResult recreate = store() .commit( branch, @@ -92,6 +95,7 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("drop table"), ImmutableList.of(Put.of(key, recreateState))); soft.assertThat(contentWithoutId(store().getValue(branch, key))).isEqualTo(recreateState); - soft.assertThat(contentWithoutId(store().getValue(recreate, key))).isEqualTo(recreateState); + soft.assertThat(contentWithoutId(store().getValue(recreate.getCommit().getHash(), key))) + .isEqualTo(recreateState); } } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java index 944b571875a..f903fdf67d5 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java @@ -61,13 +61,15 @@ void duplicateTableOnBranches() throws Throwable { branch0, Optional.empty(), CommitMeta.fromMessage("initial commit"), - ImmutableList.of(Put.of(ContentKey.of("unrelated-table"), newOnRef("value")))); + ImmutableList.of(Put.of(ContentKey.of("unrelated-table"), newOnRef("value")))) + .getCommit() + .getHash(); // Create a table with the same name on two branches. BranchName branch1 = BranchName.of("globalStateDuplicateTable-branch1"); BranchName branch2 = BranchName.of("globalStateDuplicateTable-branch2"); - soft.assertThat(store().create(branch1, Optional.of(ancestor))).isEqualTo(ancestor); - soft.assertThat(store().create(branch2, Optional.of(ancestor))).isEqualTo(ancestor); + soft.assertThat(store().create(branch1, Optional.of(ancestor)).getHash()).isEqualTo(ancestor); + soft.assertThat(store().create(branch2, Optional.of(ancestor)).getHash()).isEqualTo(ancestor); List putForBranch1; List putForBranch2; diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java index f18071af194..2f232bff0eb 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java @@ -47,8 +47,9 @@ import org.projectnessie.model.MergeBehavior; import org.projectnessie.model.Namespace; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Delete; -import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.VersionStore; @@ -264,7 +265,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp Namespace ns = Namespace.of("ns"); Namespace ns2 = Namespace.of("ns2"); - Hash rootHead = + CommitResult rootHead = store() .commit( root, @@ -275,7 +276,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp : asList(Put.of(ns.toContentKey(), ns), Put.of(ns2.toContentKey(), ns2))); BranchName branch = BranchName.of("branch"); - store().create(branch, Optional.of(rootHead)); + store().create(branch, Optional.of(rootHead.getCommit().getHash())); if (mode.createNamespaceOnTarget) { store() @@ -287,7 +288,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp } ContentKey key = ContentKey.of(ns, "foo"); - Hash commit1 = + CommitResult commit1 = store() .commit( branch, @@ -295,7 +296,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp fromMessage("create table ns.foo"), singletonList(Put.of(key, newOnRef("foo")))); - Hash commit2 = + CommitResult commit2 = store() .commit( branch, @@ -315,6 +316,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp ? () -> store() .merge( + branch, store().hashOnReference(branch, Optional.empty()), root, Optional.empty(), @@ -327,9 +329,10 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp : () -> store() .transplant( + branch, root, Optional.empty(), - asList(commit1, commit2), + asList(commit1.getCommit().getHash(), commit2.getCommit().getHash()), METADATA_REWRITER, mode.individualCommits, emptyMap(), diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java index 6765f9af016..dd80521e4b0 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java @@ -33,6 +33,7 @@ import org.projectnessie.versioned.Diff; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ImmutableCommit; +import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.Ref; @@ -177,9 +178,10 @@ protected static List operationsWithoutCo return operations.stream() .map( op -> { - if (op instanceof Put) { - Put put = (Put) op; - return Put.of(put.getKey(), contentWithoutId(put.getValue())); + if (op instanceof LazyPut) { + LazyPut put = (LazyPut) op; + Content content = put.getValue(); + return Put.of(put.getKey(), contentWithoutId(content)); } return op; }) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java index f3e2be4c25e..0bbbfe8d2f7 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java @@ -33,6 +33,8 @@ import org.projectnessie.model.ContentKey; import org.projectnessie.model.MergeBehavior; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.VersionStore; @@ -68,7 +70,7 @@ void mergeTransplant(boolean merge, boolean individual) throws Exception { BranchName branch = BranchName.of("branch"); store().create(root, Optional.empty()); - Hash rootHead = + CommitResult rootHead = store() .commit( root, @@ -76,7 +78,7 @@ void mergeTransplant(boolean merge, boolean individual) throws Exception { CommitMeta.fromMessage("common ancestor"), singletonList(Put.of(ContentKey.of("dummy"), newOnRef("dummy")))); - store().create(branch, Optional.of(rootHead)); + store().create(branch, Optional.of(rootHead.getCommit().getHash())); soft.assertThatCode( () -> @@ -108,6 +110,7 @@ void mergeTransplant(boolean merge, boolean individual) throws Exception { if (merge) { store() .merge( + branch, commit2, root, Optional.empty(), @@ -120,6 +123,7 @@ void mergeTransplant(boolean merge, boolean individual) throws Exception { } else { store() .transplant( + branch, root, Optional.empty(), asList(commit1, commit2), diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferenceNotFound.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferenceNotFound.java index ed16e6fbf8e..cf9f72110c2 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferenceNotFound.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferenceNotFound.java @@ -207,6 +207,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.transplant( + BranchName.of("source"), BranchName.of("this-one-should-not-exist"), Optional.empty(), singletonList(s.hashOnReference(BranchName.of("main"), Optional.empty())), @@ -222,6 +223,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.transplant( + BranchName.of("source"), BranchName.of("main"), Optional.of(Hash.of("12341234123412341234123412341234123412341234")), singletonList(Hash.of("12341234123412341234123412341234123412341234")), @@ -236,6 +238,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.transplant( + BranchName.of("source"), BranchName.of("main"), Optional.empty(), singletonList(Hash.of("12341234123412341234123412341234123412341234")), @@ -280,6 +283,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.merge( + BranchName.of("source"), Hash.of("12341234123412341234123412341234123412341234"), BranchName.of("main"), Optional.empty(), @@ -295,6 +299,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.merge( + BranchName.of("source"), s.noAncestorHash(), BranchName.of("main"), Optional.of(Hash.of("12341234123412341234123412341234123412341234")), @@ -309,6 +314,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.merge( + BranchName.of("source"), Hash.of("12341234123412341234123412341234123412341234"), BranchName.of("main"), Optional.empty(), @@ -324,6 +330,7 @@ public CommitMeta squash(List metadata) { .function( s -> s.merge( + BranchName.of("source"), s.noAncestorHash(), BranchName.of("main"), Optional.of(Hash.of("12341234123412341234123412341234123412341234")), diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java index 6f6dbc7bf52..0b4d2fab41a 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java @@ -69,12 +69,13 @@ public void createAndDeleteBranch() throws Exception { soft.assertThat(hash).isNotNull(); final BranchName anotherBranch = BranchName.of("bar"); - final Hash createHash = store().create(anotherBranch, Optional.of(hash)); + final Hash createHash = store().create(anotherBranch, Optional.of(hash)).getHash(); final Hash commitHash = commit("Some Commit").toBranch(anotherBranch); soft.assertThat(commitHash).isNotEqualTo(createHash); final BranchName anotherAnotherBranch = BranchName.of("baz"); - final Hash otherCreateHash = store().create(anotherAnotherBranch, Optional.of(commitHash)); + final Hash otherCreateHash = + store().create(anotherAnotherBranch, Optional.of(commitHash)).getHash(); soft.assertThat(otherCreateHash).isEqualTo(commitHash); List> namedRefs; @@ -177,7 +178,7 @@ public void createAndDeleteTag() throws Exception { @Test void getNamedRef() throws VersionStoreException { final BranchName branch = BranchName.of("getNamedRef"); - Hash hashFromCreate = store().create(branch, Optional.empty()); + Hash hashFromCreate = store().create(branch, Optional.empty()).getHash(); soft.assertThat(store().hashOnReference(branch, Optional.empty())).isEqualTo(hashFromCreate); final Hash firstCommitHash = commit("First Commit").toBranch(branch); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java index 70a4bc66b61..29ba763881e 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java @@ -35,6 +35,7 @@ import org.projectnessie.model.ImmutableCommitMeta; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.Operation; import org.projectnessie.versioned.Put; @@ -96,7 +97,7 @@ void singleBranchManyUsers(SingleBranchParam param) throws Exception { int numCommits = 20; Hash[] hashesKnownByUser = new Hash[numUsers]; - Hash createHash = store().create(branch, Optional.empty()); + Hash createHash = store().create(branch, Optional.empty()).getHash(); Arrays.fill(hashesKnownByUser, createHash); List expectedValues = new ArrayList<>(); @@ -114,7 +115,7 @@ void singleBranchManyUsers(SingleBranchParam param) throws Exception { List ops = singleBranchManyUsersOps(branch, commitNum, user, hashKnownByUser, key); - Hash commitHash; + CommitResult commitHash; try { commitHash = store().commit(branch, Optional.of(hashKnownByUser), msg.build(), ops); } catch (ReferenceConflictException inconsistentValueException) { @@ -127,13 +128,13 @@ void singleBranchManyUsers(SingleBranchParam param) throws Exception { } } - parent = commitHash; + parent = commitHash.getCommit().getHash(); - expectedValues.add(msg.hash(commitHash.asString()).build()); + expectedValues.add(msg.hash(parent.asString()).build()); assertNotEquals(hashKnownByUser, commitHash); - hashesKnownByUser[user] = commitHash; + hashesKnownByUser[user] = parent; } } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index a84c34ba9c8..b4bc615168a 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -17,6 +17,7 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.projectnessie.versioned.testworker.OnRefOnly.newOnRef; import com.google.common.collect.ImmutableMap; @@ -40,7 +41,10 @@ import org.projectnessie.model.MergeKeyBehavior; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.LazyPut; +import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.ReferenceConflictException; @@ -52,6 +56,7 @@ @ExtendWith(SoftAssertionsExtension.class) public abstract class AbstractTransplant extends AbstractNestedVersionStore { + @InjectSoftAssertions protected SoftAssertions soft; private static final String T_1 = "t1"; @@ -69,6 +74,8 @@ public abstract class AbstractTransplant extends AbstractNestedVersionStore { private static final OnRefOnly V_4_1 = newOnRef("v4_1"); private static final OnRefOnly V_5_1 = newOnRef("v5_1"); + private static final BranchName sourceBranch = BranchName.of("foo"); + protected AbstractTransplant(VersionStore store) { super(store); } @@ -98,15 +105,18 @@ public CommitMeta squash(List metadata) { @BeforeEach protected void setupCommits() throws VersionStoreException { - final BranchName branch = BranchName.of("foo"); - store().create(branch, Optional.empty()); + store().create(sourceBranch, Optional.empty()); - initialHash = store().hashOnReference(branch, Optional.empty()); + initialHash = store().hashOnReference(sourceBranch, Optional.empty()); firstCommit = - commit("Initial Commit").put(T_1, V_1_1).put(T_2, V_2_1).put(T_3, V_3_1).toBranch(branch); + commit("Initial Commit") + .put(T_1, V_1_1) + .put(T_2, V_2_1) + .put(T_3, V_3_1) + .toBranch(sourceBranch); - Content t1 = store().getValue(branch, ContentKey.of("t1")); + Content t1 = store().getValue(sourceBranch, ContentKey.of("t1")); secondCommit = commit("Second Commit") @@ -114,11 +124,11 @@ protected void setupCommits() throws VersionStoreException { .delete(T_2) .delete(T_3) .put(T_4, V_4_1) - .toBranch(branch); + .toBranch(sourceBranch); - thirdCommit = commit("Third Commit").put(T_2, V_2_2).unchanged(T_4).toBranch(branch); + thirdCommit = commit("Third Commit").put(T_2, V_2_2).unchanged(T_4).toBranch(sourceBranch); - commits = commitsList(branch, false); + commits = commitsList(sourceBranch, false); } @ParameterizedTest @@ -153,19 +163,32 @@ private BranchName checkTransplantOnEmptyBranch( MetadataRewriter commitMetaModify, boolean individualCommits) throws VersionStoreException { final BranchName newBranch = BranchName.of("bar_1"); - store().create(newBranch, Optional.empty()); + Hash targetHead = store().create(newBranch, Optional.empty()).getHash(); - store() - .transplant( - newBranch, - Optional.of(initialHash), - Arrays.asList(firstCommit, secondCommit, thirdCommit), - commitMetaModify, - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .transplant( + sourceBranch, + newBranch, + Optional.of(initialHash), + Arrays.asList(firstCommit, secondCommit, thirdCommit), + commitMetaModify, + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); + + checkAddedCommits(individualCommits, targetHead, result); + + if (individualCommits) { + // Since we fast-forwarded the target branch, the transplanted commits and the new target + // commits are identical. + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .extracting(Commit::getHash) + .containsExactly(firstCommit, secondCommit, thirdCommit); + } soft.assertThat( contentsWithoutId( store() @@ -190,25 +213,152 @@ private BranchName checkTransplantOnEmptyBranch( return newBranch; } + private void checkAddedCommits( + boolean individualCommits, Hash targetHead, MergeResult result) { + if (individualCommits) { + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .satisfiesExactly( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Initial Commit"); + soft.assertThat(c.getOperations()) + .hasSize(3) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_1_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_2_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_3)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_3_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); + soft.assertThat(c.getOperations()) + .hasSize(4) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_1_2); + }, + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of(T_2)), + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of(T_3)), + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_4_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(1).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Third Commit"); + soft.assertThat(c.getOperations()) + .hasSize(1) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_2_2); + } + // Unchanged operation not retained + ); + }); + } else { + soft.assertThat(result.getAddedCommits()) + .singleElement() + .satisfies( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()) + .contains("Initial Commit") + .contains("Second Commit") + .contains("Third Commit"); + soft.assertThat(c.getOperations()) + // old storage model keeps the Delete operation when a key is Put then Deleted, + // see https://github.com/projectnessie/nessie/pull/6472 + .hasSizeBetween(3, 4) + .anySatisfy( + o -> { + if (c.getOperations().size() == 4) { + soft.assertThat(o).isInstanceOf(Delete.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + } + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_1_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_2_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); + soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) + .isEqualTo(V_4_1); + }); + }); + } + } + @ParameterizedTest @ValueSource(booleans = {false, true}) protected void checkTransplantWithPreviousCommit(boolean individualCommits) throws VersionStoreException { final BranchName newBranch = BranchName.of("bar_2"); store().create(newBranch, Optional.empty()); - commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); + Hash targetHead = commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); - store() - .transplant( - newBranch, - Optional.of(initialHash), - Arrays.asList(firstCommit, secondCommit, thirdCommit), - createMetadataRewriter(""), - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .transplant( + sourceBranch, + newBranch, + Optional.of(initialHash), + Arrays.asList(firstCommit, secondCommit, thirdCommit), + createMetadataRewriter(""), + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); + + checkAddedCommits(individualCommits, targetHead, result); assertThat( contentsWithoutId( store() @@ -246,6 +396,7 @@ protected void checkTransplantWithConflictingCommit(boolean individualCommits, b () -> store() .transplant( + sourceBranch, newBranch, Optional.of(initialHash), Arrays.asList(firstCommit, secondCommit, thirdCommit), @@ -271,6 +422,7 @@ protected void checkTransplantWithDelete(boolean individualCommits) throws Versi store() .transplant( + sourceBranch, newBranch, Optional.of(initialHash), Arrays.asList(firstCommit, secondCommit, thirdCommit), @@ -311,6 +463,7 @@ protected void checkTransplantOnNonExistingBranch(boolean individualCommits, boo () -> store() .transplant( + sourceBranch, newBranch, Optional.of(initialHash), Arrays.asList(firstCommit, secondCommit, thirdCommit), @@ -340,6 +493,7 @@ protected void checkTransplantWithNonExistingCommit(boolean individualCommits, b () -> store() .transplant( + sourceBranch, newBranch, Optional.of(initialHash), Collections.singletonList(Hash.of("1234567890abcdef")), @@ -365,6 +519,7 @@ protected void checkTransplantWithNoExpectedHash(boolean individualCommits) store() .transplant( + sourceBranch, newBranch, Optional.empty(), Arrays.asList(firstCommit, secondCommit, thirdCommit), @@ -410,6 +565,7 @@ protected void checkTransplantWithCommitsInWrongOrder(boolean individualCommits, () -> store() .transplant( + sourceBranch, newBranch, Optional.empty(), Arrays.asList(secondCommit, firstCommit, thirdCommit), @@ -447,6 +603,7 @@ protected void checkInvalidBranchHash(boolean individualCommits, boolean dryRun) () -> store() .transplant( + sourceBranch, newBranch, Optional.of(unrelatedCommit), Arrays.asList(firstCommit, secondCommit, thirdCommit), @@ -465,19 +622,46 @@ protected void checkInvalidBranchHash(boolean individualCommits, boolean dryRun) protected void transplantBasic(boolean individualCommits) throws VersionStoreException { final BranchName newBranch = BranchName.of("bar_2"); store().create(newBranch, Optional.empty()); - commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); + Hash targetHead = commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); - store() - .transplant( - newBranch, - Optional.of(initialHash), - Arrays.asList(firstCommit, secondCommit), - createMetadataRewriter(""), - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .transplant( + sourceBranch, + newBranch, + Optional.of(initialHash), + Arrays.asList(firstCommit, secondCommit), + createMetadataRewriter(""), + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); + + if (individualCommits) { + soft.assertThat(result.getAddedCommits()) + .hasSize(2) + .satisfiesExactly( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Initial Commit"); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); + }); + } else { + soft.assertThat(result.getAddedCommits()) + .singleElement() + .satisfies( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()) + .contains("Initial Commit") + .contains("Second Commit"); + }); + } soft.assertThat( contentsWithoutId( store() @@ -510,7 +694,9 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt target, Optional.empty(), CommitMeta.fromMessage("target 1"), - singletonList(Put.of(key1, V_1_1))); + singletonList(Put.of(key1, V_1_1))) + .getCommit() + .getHash(); targetHead = store() @@ -518,7 +704,9 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt target, Optional.of(targetHead), CommitMeta.fromMessage("target 2"), - singletonList(Put.of(key2, V_2_1))); + singletonList(Put.of(key2, V_2_1))) + .getCommit() + .getHash(); // Add two commits to the source branch, with conflicting changes to key1 and key2 @@ -528,7 +716,9 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt source, Optional.empty(), CommitMeta.fromMessage("source 1"), - singletonList(Put.of(key1, V_1_2))); + singletonList(Put.of(key1, V_1_2))) + .getCommit() + .getHash(); Hash source2 = store() @@ -536,12 +726,15 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt source, Optional.of(source1), CommitMeta.fromMessage("source 2"), - singletonList(Put.of(key2, V_2_2))); + singletonList(Put.of(key2, V_2_2))) + .getCommit() + .getHash(); // Transplant the source branch into the target branch, with a drop of key1 and key2 store() .transplant( + source, target, Optional.of(targetHead), Arrays.asList(source1, source2), diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java index 68338607ff7..02dee9ffc17 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java @@ -162,7 +162,8 @@ public Hash toBranch(BranchName branchName) fromLatest ? Optional.of(store.hashOnReference(branchName, Optional.empty())) : referenceHash; - Hash commitHash = store.commit(branchName, reference, metadata, operations); + Hash commitHash = + store.commit(branchName, reference, metadata, operations).getCommit().getHash(); Hash storeHash = store.hashOnReference(branchName, Optional.empty()); Assertions.assertEquals(storeHash, commitHash); return commitHash; diff --git a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractExportImport.java b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractExportImport.java index 6b5a16eb49d..8557c69f67d 100644 --- a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractExportImport.java +++ b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractExportImport.java @@ -43,6 +43,7 @@ import org.junit.jupiter.api.io.TempDir; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.ImmutableReferenceCreatedResult; import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.persist.adapter.CommitLogEntry; @@ -229,7 +230,10 @@ public void manyExportFiles(@TempDir Path targetDir) throws Exception { assertThat(hash).isEqualTo(intToHash(refNum)); assertThat(createdReferences.get(refNum)).isFalse(); createdReferences.set(refNum); - return hash; + return ImmutableReferenceCreatedResult.builder() + .namedRef(ref) + .hash(hash) + .build(); } default: throw new UnsupportedOperationException(method.toString()); diff --git a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java index ac3d7904466..146a5f73d9b 100644 --- a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java +++ b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java @@ -35,6 +35,7 @@ import org.projectnessie.nessie.relocated.protobuf.ByteString; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.CommitMetaSerializer; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ReferenceInfo; @@ -133,7 +134,7 @@ public void multipleBranches( Hash parent = databaseAdapter.noAncestorHash(); for (; commitSeqMain <= commitsAtBeginningOfTime; commitSeqMain++) { - parent = addCommit(0, commitSeqMain); + parent = addCommit(0, commitSeqMain).getCommit().getHash(); totalCommits++; } @@ -145,7 +146,7 @@ public void multipleBranches( } for (int i = 0; i < ((branch == branches) ? commitsAtHead : commitsBetweenBranches); i++) { - parent = addCommit(0, commitSeqMain++); + parent = addCommit(0, commitSeqMain++).getCommit().getHash(); totalCommits++; } } @@ -231,7 +232,7 @@ static List allCommits() { } } - Hash addCommit(int branch, int commitSeq) throws Exception { + CommitResult addCommit(int branch, int commitSeq) throws Exception { return databaseAdapter.commit( ImmutableCommitParams.builder() .toBranch(branch == 0 ? BranchName.of("main") : BranchName.of("branch-" + branch)) diff --git a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java index 54b21d7d05a..cc34d0eb95d 100644 --- a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java +++ b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java @@ -112,11 +112,11 @@ static Stream scenarios() { main = commit10(vs, 0, mainBranch, main); BranchName branch = BranchName.of("a"); - Hash a = vs.create(branch, Optional.of(vs.noAncestorHash())); + Hash a = vs.create(branch, Optional.of(vs.noAncestorHash())).getHash(); a = commit10(vs, 0, branch, a); branch = BranchName.of("b"); - Hash b = vs.create(branch, Optional.of(vs.noAncestorHash())); + Hash b = vs.create(branch, Optional.of(vs.noAncestorHash())).getHash(); b = commit10(vs, 0, branch, b); headsAndForks.addHeads(main.asBytes()); @@ -134,11 +134,11 @@ static Stream scenarios() { main = commit10(vs, 0, mainBranch, main); BranchName branch = BranchName.of("a"); - Hash a = vs.create(branch, Optional.of(vs.noAncestorHash())); + Hash a = vs.create(branch, Optional.of(vs.noAncestorHash())).getHash(); a = commit10(vs, 0, branch, a); branch = BranchName.of("b"); - Hash b = vs.create(branch, Optional.of(vs.noAncestorHash())); + Hash b = vs.create(branch, Optional.of(vs.noAncestorHash())).getHash(); b = commit10(vs, 0, branch, b); vs.delete(BranchName.of("a"), Optional.of(a)); @@ -161,13 +161,13 @@ static Stream scenarios() { main = commit10(vs, 0, mainBranch, main); BranchName branch = BranchName.of("a"); - Hash a = vs.create(branch, Optional.of(main)); + Hash a = vs.create(branch, Optional.of(main)).getHash(); headsAndForks.addForkPoints(main.asBytes()); a = commit10(vs, 0, branch, a); main = commit10(vs, 10, mainBranch, main); branch = BranchName.of("b"); - Hash b = vs.create(branch, Optional.of(a)); + Hash b = vs.create(branch, Optional.of(a)).getHash(); headsAndForks.addForkPoints(a.asBytes()); b = commit10(vs, 0, branch, b); a = commit10(vs, 10, BranchName.of("a"), a); @@ -187,13 +187,14 @@ static Stream scenarios() { main = commit10(vs, 0, mainBranch, main); BranchName branch = BranchName.of("a"); - Hash a = vs.create(branch, Optional.of(main)); + Hash a = vs.create(branch, Optional.of(main)).getHash(); headsAndForks.addForkPoints(main.asBytes()); a = commit10(vs, 0, branch, a); main = commit10(vs, 10, mainBranch, main); vs.merge( + branch, a, mainBranch, Optional.of(main), @@ -329,19 +330,22 @@ private static Hash commit10(VersionStore versionStore, int offset, BranchName b for (int i = 0; i < 10; i++) { int commit = offset + i; head = - versionStore.commit( - branch, - Optional.of(head), - CommitMeta.fromMessage("commit #" + commit + " " + branch), - Collections.singletonList( - Put.of( - ContentKey.of(branch.getName() + "-c-" + commit), - IcebergTable.of( - "meta+" + branch.getName() + "-c-" + commit + "-" + head.asString(), - 42, - 43, - 44, - 45)))); + versionStore + .commit( + branch, + Optional.of(head), + CommitMeta.fromMessage("commit #" + commit + " " + branch), + Collections.singletonList( + Put.of( + ContentKey.of(branch.getName() + "-c-" + commit), + IcebergTable.of( + "meta+" + branch.getName() + "-c-" + commit + "-" + head.asString(), + 42, + 43, + 44, + 45)))) + .getCommit() + .getHash(); } return head; } From 3dec3a8665fd0ceb0bf541875d3c35fa561fc312 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 21 Apr 2023 15:37:24 +0200 Subject: [PATCH 02/26] Fix: source ref is not always a branch --- .../services/impl/TreeApiImpl.java | 11 +++++++---- .../persist/adapter/MetadataRewriteParams.java | 8 ++++---- .../nontx/NonTransactionalDatabaseAdapter.java | 4 ++-- .../persist/store/PersistVersionStore.java | 10 +++++----- .../persist/tests/AbstractEvents.java | 4 ++-- .../persist/tests/AbstractMergeTransplant.java | 18 +++++++++--------- .../persist/tx/TxDatabaseAdapter.java | 4 ++-- .../versioned/EventsVersionStore.java | 8 ++++---- .../projectnessie/versioned/MergeResult.java | 4 ++-- .../versioned/MetricsVersionStore.java | 8 ++++---- .../versioned/TracingVersionStore.java | 8 ++++---- .../projectnessie/versioned/VersionStore.java | 8 ++++---- .../versioned/TestEventsVersionStore.java | 8 ++++---- .../versioned/TestMetricsVersionStore.java | 4 ++-- .../versioned/TestTracingVersionStore.java | 4 ++-- .../versioned/storage/versionstore/Merge.java | 4 ++-- .../versionstore/MergeIndividualImpl.java | 5 +++-- .../storage/versionstore/MergeSquashImpl.java | 5 +++-- .../storage/versionstore/Transplant.java | 4 ++-- .../versionstore/TransplantIndividualImpl.java | 5 +++-- .../versionstore/TransplantSquashImpl.java | 5 +++-- .../storage/versionstore/VersionStoreImpl.java | 8 ++++---- .../versioned/tests/AbstractMerge.java | 2 ++ 23 files changed, 79 insertions(+), 70 deletions(-) diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java index 844560b16e8..667895acb97 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java @@ -570,8 +570,10 @@ public MergeResponse transplantCommitsIntoBranch( BranchName targetBranch = BranchName.of(branchName); String lastHash = hashesToTransplant.get(hashesToTransplant.size() - 1); + WithHash namedRefWithHash = namedRefWithHashOrThrow(fromRefName, lastHash); + startAccessCheck() - .canViewReference(namedRefWithHashOrThrow(fromRefName, lastHash).getValue()) + .canViewReference(namedRefWithHash.getValue()) .canCommitChangeAgainstReference(targetBranch) .checkAndThrow(); @@ -591,7 +593,7 @@ public MergeResponse transplantCommitsIntoBranch( MergeResult result = getStore() .transplant( - BranchName.of(fromRefName), + namedRefWithHash.getValue(), targetBranch, into, transplants, @@ -643,8 +645,9 @@ public MergeResponse mergeRefIntoBranch( validateCommitMeta(commitMeta); BranchName targetBranch = BranchName.of(branchName); + WithHash namedRefWithHash = namedRefWithHashOrThrow(fromRefName, fromHash); startAccessCheck() - .canViewReference(namedRefWithHashOrThrow(fromRefName, fromHash).getValue()) + .canViewReference(namedRefWithHash.getValue()) .canCommitChangeAgainstReference(targetBranch) .checkAndThrow(); @@ -654,7 +657,7 @@ public MergeResponse mergeRefIntoBranch( MergeResult result = getStore() .merge( - BranchName.of(fromRefName), + namedRefWithHash.getValue(), toHash(fromRefName, fromHash), targetBranch, into, diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java index 1bb1cb0a1b2..44eb4e93a69 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/MetadataRewriteParams.java @@ -19,14 +19,14 @@ import org.immutables.value.Value; import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; -import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.MergeType; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; public interface MetadataRewriteParams extends ToBranchParams { - /** Branch to merge or transplant from. */ - BranchName getFromBranch(); + /** Ref to merge or transplant from. */ + NamedRef getFromRef(); /** Whether to keep the individual commits and do not squash the commits to merge. */ @Value.Default @@ -51,7 +51,7 @@ default MergeType getDefaultMergeType() { @SuppressWarnings({"override", "UnusedReturnValue"}) interface Builder extends ToBranchParams.Builder { - B fromBranch(BranchName fromBranch); + B fromRef(NamedRef fromBranch); B keepIndividualCommits(boolean keepIndividualCommits); diff --git a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java index c9e307e76bc..7f4ac145447 100644 --- a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java +++ b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java @@ -242,7 +242,7 @@ public MergeResult merge(MergeParams mergeParams) ImmutableMergeResult.Builder mergeResult = MergeResult.builder() .resultType(ResultType.MERGE) - .sourceBranch(mergeParams.getFromBranch()); + .sourceRef(mergeParams.getFromRef()); mergeResultHolder.set(mergeResult); Hash currentHead = Hash.of(refHead.getHash()); @@ -306,7 +306,7 @@ public MergeResult transplant(TransplantParams transplantParams) ImmutableMergeResult.Builder mergeResult = MergeResult.builder() .resultType(ResultType.TRANSPLANT) - .sourceBranch(transplantParams.getFromBranch()); + .sourceRef(transplantParams.getFromRef()); mergeResultHolder.set(mergeResult); Hash currentHead = Hash.of(refHead.getHash()); diff --git a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java index df78653b009..955fac0b4c9 100644 --- a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java +++ b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java @@ -183,7 +183,7 @@ public CommitResult commit( @Override public MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -199,7 +199,7 @@ public MergeResult transplant( MergeResult adapterMergeResult = databaseAdapter.transplant( TransplantParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceRef) .toBranch(targetBranch) .expectedHead(referenceHash) .sequenceToTransplant(sequenceToTransplant) @@ -221,7 +221,7 @@ public MergeResult transplant( @Override public MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -237,7 +237,7 @@ public MergeResult merge( MergeResult adapterMergeResult = databaseAdapter.merge( MergeParams.builder() - .fromBranch(fromBranch) + .fromRef(fromRef) .toBranch(toBranch) .expectedHead(expectedHash) .mergeFromHash(fromHash) @@ -290,7 +290,7 @@ private MergeResult storeMergeResult( ImmutableMergeResult.Builder storeResult = ImmutableMergeResult.builder() .resultType(adapterMergeResult.getResultType()) - .sourceBranch(adapterMergeResult.getSourceBranch()) + .sourceRef(adapterMergeResult.getSourceRef()) .targetBranch(adapterMergeResult.getTargetBranch()) .effectiveTargetHash(adapterMergeResult.getEffectiveTargetHash()) .commonAncestor(adapterMergeResult.getCommonAncestor()) diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java index 8ef6024ef5a..fc815a58a76 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java @@ -298,7 +298,7 @@ public void eventMerge( adapter.merge( MergeParams.builder() .mergeFromHash(committed) - .fromBranch(source) + .fromRef(source) .toBranch(main) .updateCommitMetadata(updater) .build()); @@ -375,7 +375,7 @@ public void eventTransplant( TransplantParams.builder() .addSequenceToTransplant(committed) .updateCommitMetadata(updater) - .fromBranch(source) + .fromRef(source) .toBranch(main) .build()); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java index 71174460831..e50ee27522b 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java @@ -88,7 +88,7 @@ void merge(int numCommits, boolean keepIndividualCommits) throws Exception { numCommits, (commitHashes, i) -> MergeParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) .mergeFromHash(commitHashes[i]), @@ -103,7 +103,7 @@ void merge(int numCommits, boolean keepIndividualCommits) throws Exception { () -> databaseAdapter.merge( MergeParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .toBranch(branch2) .mergeFromHash( databaseAdapter.hashOnReference(sourceBranch, Optional.empty())) @@ -154,7 +154,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception numCommits, (commitHashes, i) -> TransplantParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) .sequenceToTransplant(Arrays.asList(commitHashes).subList(0, i + 1)), @@ -171,7 +171,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception databaseAdapter .transplant( TransplantParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .toBranch(conflict) .expectedHead(Optional.of(noConflictHead)) .addSequenceToTransplant(commits) @@ -188,7 +188,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception databaseAdapter .transplant( TransplantParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .toBranch(conflict) .addSequenceToTransplant(commits) .updateCommitMetadata(metadataUpdater) @@ -203,7 +203,7 @@ void transplant(int numCommits, boolean keepIndividualCommits) throws Exception () -> databaseAdapter.transplant( TransplantParams.builder() - .fromBranch(sourceBranch) + .fromRef(sourceBranch) .toBranch(conflict) .updateCommitMetadata(metadataUpdater) .keepIndividualCommits(keepIndividualCommits) @@ -348,7 +348,7 @@ Hash mergeTransplantSuccess( .isEqualTo( expectedMergeResult .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) - .sourceBranch(source) + .sourceRef(source) .targetBranch(target) .resultantTargetHash(mainHead) .addedCommits(mergeResult.getAddedCommits()) @@ -366,7 +366,7 @@ Hash mergeTransplantSuccess( .isEqualTo( expectedMergeResult .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) - .sourceBranch(source) + .sourceRef(source) .targetBranch(target) .resultantTargetHash(targetHead) .wasApplied(true) @@ -475,7 +475,7 @@ private MergeResult conflictExpectedMergeResult( MergeResult.builder() .resultType(merge ? ResultType.MERGE : ResultType.TRANSPLANT) .resultantTargetHash(conflictHead) - .sourceBranch(BranchName.of("branch")) + .sourceRef(BranchName.of("branch")) .targetBranch(conflict) .effectiveTargetHash(conflictHead) .expectedHash(conflictBase) diff --git a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java index ca1a8ca9d80..87b9285773c 100644 --- a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java +++ b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java @@ -248,7 +248,7 @@ public MergeResult merge(MergeParams mergeParams) ImmutableMergeResult.Builder mergeResult = MergeResult.builder() .resultType(ResultType.MERGE) - .sourceBranch(mergeParams.getFromBranch()); + .sourceRef(mergeParams.getFromRef()); mergeResultHolder.set(mergeResult); List writtenCommits = new ArrayList<>(); @@ -317,7 +317,7 @@ public MergeResult transplant(TransplantParams transplantParams) ImmutableMergeResult.Builder mergeResult = MergeResult.builder() .resultType(ResultType.TRANSPLANT) - .sourceBranch(transplantParams.getFromBranch()); + .sourceRef(transplantParams.getFromRef()); mergeResultHolder.set(mergeResult); diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java index b3d88d9d47e..f5fa3b77b45 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java @@ -68,7 +68,7 @@ public CommitResult commit( @Override public MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -81,7 +81,7 @@ public MergeResult transplant( throws ReferenceNotFoundException, ReferenceConflictException { MergeResult result = delegate.transplant( - sourceBranch, + sourceRef, targetBranch, referenceHash, sequenceToTransplant, @@ -99,7 +99,7 @@ public MergeResult transplant( @Override public MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -112,7 +112,7 @@ public MergeResult merge( throws ReferenceNotFoundException, ReferenceConflictException { MergeResult result = delegate.merge( - fromBranch, + fromRef, fromHash, toBranch, expectedHash, diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java index 4564fd7e96e..26b7e19178a 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java @@ -48,8 +48,8 @@ default boolean wasSuccessful() { @jakarta.annotation.Nullable Hash getCommonAncestor(); - /** Name of the source branch. */ - BranchName getSourceBranch(); + /** The source ref. */ + NamedRef getSourceRef(); /** Name of the target branch. */ BranchName getTargetBranch(); diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java index 1764e686c4f..a12de8b0346 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MetricsVersionStore.java @@ -104,7 +104,7 @@ public CommitResult commit( @Override public MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -120,7 +120,7 @@ public MergeResult transplant( "transplant", () -> delegate.transplant( - sourceBranch, + sourceRef, targetBranch, referenceHash, sequenceToTransplant, @@ -134,7 +134,7 @@ public MergeResult transplant( @Override public MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -150,7 +150,7 @@ public MergeResult merge( "merge", () -> delegate.merge( - fromBranch, + fromRef, fromHash, toBranch, expectedHash, diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java index 3b6f6bdbe3f..878dcd3e5d6 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java @@ -134,7 +134,7 @@ public CommitResult commit( @Override public MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -156,7 +156,7 @@ public MergeResult transplant( .setAttribute(TAG_TRANSPLANTS, safeSize(sequenceToTransplant)), () -> delegate.transplant( - sourceBranch, + sourceRef, targetBranch, referenceHash, sequenceToTransplant, @@ -170,7 +170,7 @@ public MergeResult transplant( @Override public MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -192,7 +192,7 @@ public MergeResult merge( .setAttribute(TAG_EXPECTED_HASH, safeToString(expectedHash)), () -> delegate.merge( - fromBranch, + fromRef, fromHash, toBranch, expectedHash, diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java index 9a6c02cfd01..c86bb1dfd39 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/VersionStore.java @@ -114,7 +114,7 @@ default CommitResult commit( * to concurrent readers/writers. The sequence to transplant must be contiguous, in order and * share a common ancestor with the target branch. * - * @param sourceBranch The branch we're transplanting from + * @param sourceRef The named ref we're transplanting from * @param targetBranch The branch we're transplanting to * @param referenceHash The hash to use as a reference for conflict detection. If not present, do * not perform conflict detection @@ -135,7 +135,7 @@ default CommitResult commit( * sequenceToTransplant} is not present in the store. */ MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -162,7 +162,7 @@ MergeResult transplant( *
  • the expected branch hash does not match the actual branch hash * * - * @param fromBranch The branch we are merging from + * @param fromRef The named ref we are merging from * @param fromHash The hash we are using to get additional commits * @param toBranch The branch that we are merging into * @param expectedHash The current head of the branch to validate before updating (optional). @@ -182,7 +182,7 @@ MergeResult transplant( * the store. */ MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java index 00b28c49b0c..5fe6f4e5402 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java @@ -135,7 +135,7 @@ void testTransplantDryRun() throws Exception { boolean dryRun = true; MergeResult expectedResult = MergeResult.builder() - .sourceBranch(branch1) + .sourceRef(branch1) .targetBranch(branch2) .resultType(ResultType.TRANSPLANT) .effectiveTargetHash(hash1) @@ -188,7 +188,7 @@ void testTransplantSuccessful() throws Exception { boolean dryRun = false; MergeResult expectedResult = MergeResult.builder() - .sourceBranch(branch1) + .sourceRef(branch1) .targetBranch(branch2) .resultType(ResultType.TRANSPLANT) .effectiveTargetHash(hash1) @@ -289,7 +289,7 @@ void testMergeDryRun() throws Exception { boolean dryRun = true; MergeResult expectedResult = MergeResult.builder() - .sourceBranch(branch1) + .sourceRef(branch1) .targetBranch(branch2) .resultType(ResultType.MERGE) .effectiveTargetHash(hash1) @@ -342,7 +342,7 @@ void testMergeSuccessful() throws Exception { boolean dryRun = false; MergeResult expectedResult = MergeResult.builder() - .sourceBranch(branch1) + .sourceRef(branch1) .targetBranch(branch2) .resultType(ResultType.MERGE) .effectiveTargetHash(hash1) diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java index 1ef58680d25..99f99ac5b0f 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java @@ -124,7 +124,7 @@ public CommitMeta squash(List metadata) { MergeResult dummyMergeResult = MergeResult.builder() .resultType(ResultType.MERGE) - .sourceBranch(BranchName.of("foo")) + .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); @@ -132,7 +132,7 @@ public CommitMeta squash(List metadata) { MergeResult dummyTransplantResult = MergeResult.builder() .resultType(ResultType.TRANSPLANT) - .sourceBranch(BranchName.of("foo")) + .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java index 12eccfd267e..2ce04ffcefe 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java @@ -118,7 +118,7 @@ public CommitMeta squash(List metadata) { MergeResult dummyMergeResult = MergeResult.builder() .resultType(ResultType.MERGE) - .sourceBranch(BranchName.of("foo")) + .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); @@ -126,7 +126,7 @@ public CommitMeta squash(List metadata) { MergeResult dummyTransplantResult = MergeResult.builder() .resultType(ResultType.TRANSPLANT) - .sourceBranch(BranchName.of("foo")) + .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java index f74b0f53b4d..59935258e7d 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Merge.java @@ -17,11 +17,11 @@ import java.util.Optional; import org.projectnessie.model.CommitMeta; -import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; @@ -29,7 +29,7 @@ interface Merge { MergeResult merge( Optional retryState, - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java index c4de17d3cad..55ebf9552a2 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeIndividualImpl.java @@ -30,6 +30,7 @@ import org.projectnessie.versioned.ImmutableMergeResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.ResultType; @@ -55,7 +56,7 @@ final class MergeIndividualImpl extends BaseMergeTransplantIndividual implements @Override public MergeResult merge( Optional retryState, - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -74,7 +75,7 @@ public MergeResult merge( ImmutableMergeResult.Builder mergeResult = prepareMergeResult() .resultType(ResultType.MERGE) - .sourceBranch(fromBranch) + .sourceRef(fromRef) .commonAncestor(objIdToHash(commonAncestorId)); // Fast-forward, if possible diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java index 88a000a87ae..a8b99f444bf 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/MergeSquashImpl.java @@ -28,6 +28,7 @@ import org.projectnessie.versioned.ImmutableMergeResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.ResultType; @@ -52,7 +53,7 @@ final class MergeSquashImpl extends BaseMergeTransplantSquash implements Merge { @Override public MergeResult merge( Optional retryState, - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -66,7 +67,7 @@ public MergeResult merge( ImmutableMergeResult.Builder mergeResult = prepareMergeResult() .resultType(ResultType.MERGE) - .sourceBranch(fromBranch) + .sourceRef(fromRef) .commonAncestor(objIdToHash(commonAncestorId)); return squash(dryRun, mergeResult, mergeBehaviors, updateCommitMetadata, sourceCommits, fromId); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java index 27abcf197df..1533f0a0b08 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/Transplant.java @@ -18,11 +18,11 @@ import java.util.List; import java.util.Optional; import org.projectnessie.model.CommitMeta; -import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.storage.common.logic.CommitRetry.RetryException; @@ -30,7 +30,7 @@ interface Transplant { MergeResult transplant( Optional retryState, - BranchName sourceBranch, + NamedRef sourceRef, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java index d6990639bff..a648ea19bcb 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantIndividualImpl.java @@ -26,6 +26,7 @@ import org.projectnessie.versioned.ImmutableMergeResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.ResultType; @@ -49,7 +50,7 @@ final class TransplantIndividualImpl extends BaseMergeTransplantIndividual imple @Override public MergeResult transplant( Optional retryState, - BranchName sourceBranch, + NamedRef sourceRef, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -58,7 +59,7 @@ public MergeResult transplant( SourceCommitsAndParent sourceCommits = loadSourceCommitsForTransplant(sequenceToTransplant); ImmutableMergeResult.Builder mergeResult = - prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceBranch(sourceBranch); + prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceRef(sourceRef); return individualCommits( updateCommitMetadata, dryRun, mergeResult, mergeBehaviors, sourceCommits); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java index 42d97a6d562..ba7dd9fa149 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/TransplantSquashImpl.java @@ -26,6 +26,7 @@ import org.projectnessie.versioned.ImmutableMergeResult; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; +import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.ResultType; @@ -49,7 +50,7 @@ final class TransplantSquashImpl extends BaseMergeTransplantSquash implements Tr @Override public MergeResult transplant( Optional retryState, - BranchName sourceBranch, + NamedRef sourceRef, List sequenceToTransplant, MetadataRewriter updateCommitMetadata, MergeBehaviors mergeBehaviors, @@ -58,7 +59,7 @@ public MergeResult transplant( SourceCommitsAndParent sourceCommits = loadSourceCommitsForTransplant(sequenceToTransplant); ImmutableMergeResult.Builder mergeResult = - prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceBranch(sourceBranch); + prepareMergeResult().resultType(ResultType.TRANSPLANT).sourceRef(sourceRef); return squash(dryRun, mergeResult, mergeBehaviors, updateCommitMetadata, sourceCommits, null); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java index 2f713e60e33..03f925c7a85 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java @@ -636,7 +636,7 @@ public CommitResult commit( @Override public MergeResult merge( - BranchName fromBranch, + NamedRef fromRef, Hash fromHash, BranchName toBranch, Optional expectedHash, @@ -668,7 +668,7 @@ public MergeResult merge( (merge, retryState) -> merge.merge( retryState, - fromBranch, + fromRef, fromHash, updateCommitMetadata, mergeBehaviors, @@ -679,7 +679,7 @@ public MergeResult merge( @Override public MergeResult transplant( - BranchName sourceBranch, + NamedRef sourceRef, BranchName targetBranch, Optional referenceHash, List sequenceToTransplant, @@ -711,7 +711,7 @@ public MergeResult transplant( (transplant, retryState) -> transplant.transplant( retryState, - sourceBranch, + sourceRef, sequenceToTransplant, updateCommitMetadata, mergeBehaviors, diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index 8868a576680..5c13ca899cb 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -547,6 +547,8 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio // compare "effective" merge-result with re-constructed merge-result .isEqualTo( MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceRef(sourceBranch) .wasApplied(true) .wasSuccessful(true) .commonAncestor(initialHash) From f67ade8d2b40ed5dca6402c0920b99bf7fcd53b8 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 21 Apr 2023 18:33:13 +0200 Subject: [PATCH 03/26] Add missing method --- .../org/projectnessie/versioned/EventsVersionStore.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java index f5fa3b77b45..d428406bbb5 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java @@ -153,6 +153,13 @@ public ReferenceDeletedResult delete(NamedRef ref, Optional hash) return result; } + @Nonnull + @jakarta.annotation.Nonnull + @Override + public RepositoryInformation getRepositoryInformation() { + return delegate.getRepositoryInformation(); + } + @Override public Hash hashOnReference(NamedRef namedReference, Optional hashOnReference) throws ReferenceNotFoundException { From 9a37d138ebb330aaca5ffa2da0dd88e6f4e72bee Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 21 Apr 2023 18:34:12 +0200 Subject: [PATCH 04/26] Remove LazyPut --- .../services/impl/TreeApiImpl.java | 5 +- .../persist/store/PersistVersionStore.java | 3 +- .../org/projectnessie/versioned/LazyPut.java | 63 ------ .../java/org/projectnessie/versioned/Put.java | 28 ++- .../storage/versionstore/ContentMapping.java | 4 +- .../versionstore/TestContentMapping.java | 4 +- .../versioned/tests/AbstractMerge.java | 207 ++++++++++++++++++ .../tests/AbstractNestedVersionStore.java | 5 +- .../versioned/tests/AbstractTransplant.java | 46 ++-- 9 files changed, 260 insertions(+), 105 deletions(-) delete mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java index 667895acb97..f62787989e0 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java @@ -111,7 +111,6 @@ import org.projectnessie.versioned.GetNamedRefsParams.RetrieveOptions; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.KeyEntry; -import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MergeConflictException; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.NamedRef; @@ -483,8 +482,8 @@ private ImmutableLogEntry commitToLogEntry(boolean fetchAll, Commit commit) { .forEach( op -> { ContentKey key = op.getKey(); - if (op instanceof LazyPut) { - Content content = ((LazyPut) op).getValue(); + if (op instanceof Put) { + Content content = ((Put) op).getValue(); logEntry.addOperations(Operation.Put.of(key, content)); } if (op instanceof Delete) { diff --git a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java index 955fac0b4c9..91492e95b0f 100644 --- a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java +++ b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java @@ -55,7 +55,6 @@ import org.projectnessie.versioned.ImmutableRefLogDetails; import org.projectnessie.versioned.ImmutableRepositoryInformation; import org.projectnessie.versioned.KeyEntry; -import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MergeConflictException; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MergeType; @@ -515,7 +514,7 @@ private BiConsumer enhancerForCommitLog .forEach( put -> commitBuilder.addOperations( - LazyPut.of( + Put.of( put.getKey(), put.getPayload(), put.getValue(), diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java b/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java deleted file mode 100644 index 9d75455b0a8..00000000000 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/LazyPut.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2020 Dremio - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.projectnessie.versioned; - -import java.util.function.Supplier; -import org.immutables.value.Value; -import org.projectnessie.model.Content; -import org.projectnessie.model.ContentKey; -import org.projectnessie.nessie.relocated.protobuf.ByteString; -import org.projectnessie.versioned.store.DefaultStoreWorker; - -/** - * A PUT operation that has been retrieved from the version store. The content value is kept in its - * raw (serialized) form; deserialization happens lazily, on first access to {@link #getValue()}. - */ -@Value.Immutable -public interface LazyPut extends Operation { - - int getPayload(); - - ByteString getRawValue(); - - @Value.Lazy - @SuppressWarnings("deprecation") - default Content getValue() { - return DefaultStoreWorker.instance() - .valueFromStore((byte) getPayload(), getRawValue(), getGlobalStateSupplier()); - } - - /** TODO remove global state supplier completely when it's removed from VersionStore. */ - @Value.Default - @Value.Auxiliary - default Supplier getGlobalStateSupplier() { - return () -> null; - } - - static LazyPut of(ContentKey key, int payload, ByteString value) { - return of(key, payload, value, () -> null); - } - - static LazyPut of( - ContentKey key, int payload, ByteString value, Supplier globalStateSupplier) { - return ImmutableLazyPut.builder() - .key(key) - .payload(payload) - .rawValue(value) - .globalStateSupplier(globalStateSupplier) - .build(); - } -} diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index 5ac760dc142..2c7bbaa0b0c 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -15,10 +15,13 @@ */ package org.projectnessie.versioned; +import java.util.function.Supplier; import javax.annotation.Nonnull; import org.immutables.value.Value; import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; +import org.projectnessie.nessie.relocated.protobuf.ByteString; +import org.projectnessie.versioned.store.DefaultStoreWorker; /** * A PUT operation provided by the client in order to set a new value in a commit. Can optionally @@ -32,7 +35,12 @@ public interface Put extends Operation { * * @return the value */ - Content getValue(); + @Value.Lazy + default Content getValue() { + return getValueSupplier().get(); + } + + Supplier getValueSupplier(); /** * Creates a put-operation for the given key and value. @@ -55,6 +63,22 @@ public interface Put extends Operation { static Put of( @Nonnull @jakarta.annotation.Nonnull ContentKey key, @Nonnull @jakarta.annotation.Nonnull Content value) { - return ImmutablePut.builder().key(key).value(value).build(); + return ImmutablePut.builder().key(key).valueSupplier(() -> value).build(); + } + + static Put of(ContentKey key, int payload, ByteString value) { + return of(key, payload, value, () -> null); + } + + @SuppressWarnings("deprecation") + static Put of( + ContentKey key, int payload, ByteString value, Supplier globalStateSupplier) { + return ImmutablePut.builder() + .key(key) + .valueSupplier( + () -> + DefaultStoreWorker.instance() + .valueFromStore((byte) payload, value, globalStateSupplier)) + .build(); } } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index 6462e73ad60..f94f10ccbd3 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -34,7 +34,7 @@ import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.ImmutableCommit; -import org.projectnessie.versioned.LazyPut; +import org.projectnessie.versioned.Put; import org.projectnessie.versioned.StoreWorker; import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndexElement; @@ -142,7 +142,7 @@ public Commit commitObjToCommit( ObjId objId = requireNonNull(c.value(), "Required value pointer is null"); ContentValueObj contentValue = persist.fetchTypedObj(objId, VALUE, ContentValueObj.class); - commit.addOperations(LazyPut.of(key, contentValue.payload(), contentValue.data())); + commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); } else { commit.addOperations(Delete.of(key)); } diff --git a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java index baecbcc66d0..3560d0881bd 100644 --- a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java +++ b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java @@ -50,7 +50,7 @@ import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.ImmutableCommit; -import org.projectnessie.versioned.LazyPut; +import org.projectnessie.versioned.Put; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.objtypes.CommitObj; import org.projectnessie.versioned.storage.common.objtypes.CommitOp; @@ -228,7 +228,7 @@ public void commitsWithAdditionalInfo() throws Exception { .commitMeta(referenceCommitMeta) .addOperations( Delete.of(ContentKey.of("bar")), - LazyPut.of(ContentKey.of("foo"), tableObj.payload(), tableObj.data())) + Put.of(ContentKey.of("foo"), tableObj.payload(), tableObj.data())) .build(); Commit c = contentMapping.commitObjToCommit(true, commitObj); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index 5c13ca899cb..bab48cb34d6 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -468,6 +468,120 @@ private void doMergeIntoEmpty( ContentKey.of("t4"), V_4_1)); } + private void checkTargetCommits( + boolean individualCommits, Hash targetHead, MergeResult result) { + if (individualCommits) { + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .satisfiesExactly( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()).contains("First Commit"); + soft.assertThat(c.getOperations()) + .hasSize(3) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_3_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).contains("Second Commit"); + soft.assertThat(c.getOperations()) + .hasSize(4) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); + }, + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of("t2")), + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of("t3")), + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t4")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(1).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).contains("Third Commit"); + soft.assertThat(c.getOperations()) + .hasSize(1) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); + } + // Unchanged operation not retained + ); + }); + } else { + soft.assertThat(result.getAddedCommits()) + .singleElement() + .satisfies( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()) + .contains("First Commit") + .contains("Second Commit") + .contains("Third Commit"); + soft.assertThat(c.getOperations()) + // old storage model keeps the Delete operation when a key is Put then Deleted, + // see https://github.com/projectnessie/nessie/pull/6472 + .hasSizeBetween(3, 4) + .anySatisfy( + o -> { + if (c.getOperations().size() == 4) { + soft.assertThat(o).isInstanceOf(Delete.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + } + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t4")); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); + }); + }); + } + } + @SuppressWarnings("deprecation") @ParameterizedTest @ValueSource(booleans = {false, true}) @@ -1051,6 +1165,33 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .containsEntry(key3, VALUE_5) .containsEntry(key4, VALUE_6); + soft.assertThat(result.getAddedCommits()) + .singleElement() + .satisfies( + commit -> { + if (individualCommits) { + soft.assertThat(commit.getCommitMeta().getMessage()) + .isEqualTo("commit 2, merge-force-1"); + // commit 4 was skipped because empty after drop of conflictingKey2 + } else { + soft.assertThat(commit.getCommitMeta().getMessage()) + .contains("commit 2, merge-force-1") + .contains("commit 4, merge-force-1"); + } + soft.assertThat(commit.getParentHash()) + .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getOperations()) + .satisfiesExactlyInAnyOrder( + op -> { + soft.assertThat(op.getKey()).isEqualTo(conflictingKey1); + soft.assertThat(contentWithoutId(((Put) op).getValue())).isEqualTo(VALUE_2); + }, + op -> { + soft.assertThat(op.getKey()).isEqualTo(key3); + soft.assertThat(contentWithoutId(((Put) op).getValue())).isEqualTo(VALUE_5); + }); + }); + // reset merge-into branch store().assign(mergeInto, Optional.empty(), mergeIntoHead); @@ -1075,6 +1216,72 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .containsEntry(conflictingKey2, VALUE_4) // value as in "mergeFrom" .containsEntry(key3, VALUE_5) .containsEntry(key4, VALUE_6); + + if (individualCommits) { + soft.assertThat(result2.getAddedCommits()) + .hasSize(2) + .satisfiesExactly( + commit -> { + soft.assertThat(commit.getCommitMeta().getMessage()) + .isEqualTo("commit 2, merge-all-force"); + soft.assertThat(commit.getParentHash()) + .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getOperations()) + .satisfiesExactlyInAnyOrder( + op -> { + soft.assertThat(op.getKey()).isEqualTo(conflictingKey1); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_2); + }, + op -> { + soft.assertThat(op.getKey()).isEqualTo(key3); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_5); + }); + }, + commit -> { + soft.assertThat(commit.getCommitMeta().getMessage()) + .isEqualTo("commit 4, merge-all-force"); + soft.assertThat(commit.getParentHash()) + .isEqualTo(result2.getAddedCommits().get(0).getHash()); + soft.assertThat(commit.getOperations()) + .singleElement() + .satisfies( + op -> { + soft.assertThat(op.getKey()).isEqualTo(conflictingKey2); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_4); + }); + }); + } else { + soft.assertThat(result2.getAddedCommits()) + .singleElement() + .satisfies( + commit -> { + soft.assertThat(commit.getCommitMeta().getMessage()) + .contains("commit 2, merge-all-force") + .contains("commit 4, merge-all-force"); + soft.assertThat(commit.getParentHash()) + .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getOperations()) + .satisfiesExactlyInAnyOrder( + op -> { + soft.assertThat(op.getKey()).isEqualTo(conflictingKey1); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_2); + }, + op -> { + soft.assertThat(op.getKey()).isEqualTo(conflictingKey2); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_4); + }, + op -> { + soft.assertThat(op.getKey()).isEqualTo(key3); + soft.assertThat(contentWithoutId(((Put) op).getValue())) + .isEqualTo(VALUE_5); + }); + }); + } } @ParameterizedTest diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java index dd80521e4b0..723826cbdcf 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNestedVersionStore.java @@ -33,7 +33,6 @@ import org.projectnessie.versioned.Diff; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ImmutableCommit; -import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.Put; import org.projectnessie.versioned.Ref; @@ -178,8 +177,8 @@ protected static List operationsWithoutCo return operations.stream() .map( op -> { - if (op instanceof LazyPut) { - LazyPut put = (LazyPut) op; + if (op instanceof Put) { + Put put = (Put) op; Content content = put.getValue(); return Put.of(put.getKey(), contentWithoutId(content)); } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index b4bc615168a..cddec5b811c 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -43,7 +43,6 @@ import org.projectnessie.versioned.Commit; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.Hash; -import org.projectnessie.versioned.LazyPut; import org.projectnessie.versioned.MergeResult; import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.Put; @@ -226,22 +225,19 @@ private void checkAddedCommits( .hasSize(3) .satisfiesExactlyInAnyOrder( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_1_1); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_1); }, o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_2_1); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_1); }, o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_3)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_3_1); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_3_1); }); }, c -> { @@ -252,10 +248,9 @@ private void checkAddedCommits( .hasSize(4) .satisfiesExactlyInAnyOrder( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_1_2); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); }, o -> soft.assertThat(o) @@ -268,10 +263,9 @@ private void checkAddedCommits( .extracting(Delete::getKey) .isEqualTo(ContentKey.of(T_3)), o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_4_1); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); }); }, c -> { @@ -282,10 +276,9 @@ private void checkAddedCommits( .hasSize(1) .satisfiesExactlyInAnyOrder( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_2_2); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); } // Unchanged operation not retained ); @@ -313,24 +306,21 @@ private void checkAddedCommits( }) .anySatisfy( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_1_2); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); }) .anySatisfy( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_2_2); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); }) .anySatisfy( o -> { - soft.assertThat(o).isInstanceOf(LazyPut.class); + soft.assertThat(o).isInstanceOf(Put.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); - soft.assertThat(contentWithoutId(((LazyPut) o).getValue())) - .isEqualTo(V_4_1); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); }); }); } From 684620649c89098e81be788ee681338be8124c40 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 21 Apr 2023 19:17:40 +0200 Subject: [PATCH 05/26] Remove LazyPut 2 (fix equals issue) --- .../java/org/projectnessie/versioned/Put.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index 2c7bbaa0b0c..b45fa0dfbe1 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -15,8 +15,10 @@ */ package org.projectnessie.versioned; +import java.util.Objects; import java.util.function.Supplier; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import org.immutables.value.Value; import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; @@ -28,7 +30,7 @@ * declare whether the prior hash must match. */ @Value.Immutable -public interface Put extends Operation { +public abstract class Put implements Operation { /** * The value to store for this operation. @@ -36,14 +38,14 @@ public interface Put extends Operation { * @return the value */ @Value.Lazy - default Content getValue() { + public Content getValue() { return getValueSupplier().get(); } - Supplier getValueSupplier(); + protected abstract Supplier getValueSupplier(); /** - * Creates a put-operation for the given key and value. + * Creates an (eagerly-evaluated) put-operation for the given key and value. * *

    {@code value} with a {@code null} content ID is required when creating/adding new * content. @@ -60,18 +62,27 @@ default Content getValue() { */ @Nonnull @jakarta.annotation.Nonnull - static Put of( + public static Put of( @Nonnull @jakarta.annotation.Nonnull ContentKey key, @Nonnull @jakarta.annotation.Nonnull Content value) { return ImmutablePut.builder().key(key).valueSupplier(() -> value).build(); } - static Put of(ContentKey key, int payload, ByteString value) { + /** Creates a lazily-evaluated put-operation for the given key, payload and ByteString value. */ + @Nonnull + @jakarta.annotation.Nonnull + public static Put of(ContentKey key, int payload, ByteString value) { return of(key, payload, value, () -> null); } + /** + * Creates a lazily-evaluated put-operation for the given key, payload, ByteString value and + * global state supplier. + */ @SuppressWarnings("deprecation") - static Put of( + @Nonnull + @jakarta.annotation.Nonnull + public static Put of( ContentKey key, int payload, ByteString value, Supplier globalStateSupplier) { return ImmutablePut.builder() .key(key) @@ -81,4 +92,23 @@ static Put of( .valueFromStore((byte) payload, value, globalStateSupplier)) .build(); } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Put)) { + return false; + } + Put that = (Put) o; + return this.shouldMatchHash() == that.shouldMatchHash() + && this.getKey().equals(that.getKey()) + && this.getValue().equals(that.getValue()); + } + + @Override + public int hashCode() { + return Objects.hash(shouldMatchHash(), getKey(), getValue()); + } } From eadceda4dd8a0785cddc30c1c61c20d1f6fcf3e3 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 21 Apr 2023 19:18:35 +0200 Subject: [PATCH 06/26] Extract getCommitHash --- .../quarkus/cli/ITExportImport.java | 2 +- .../quarkus/cli/ITNessieInfo.java | 3 +- .../services/impl/NamespaceApiImpl.java | 3 +- .../services/impl/TreeApiImpl.java | 3 +- .../persist/adapter/CommitLogEntry.java | 4 +- .../persist/tests/AbstractCommitLogScan.java | 3 +- .../tests/AbstractCommitScenarios.java | 19 ++-- .../versioned/persist/tests/AbstractDiff.java | 2 +- .../persist/tests/AbstractEvents.java | 12 +- .../tests/AbstractGetNamedReferences.java | 3 +- .../persist/tests/AbstractManyCommits.java | 2 +- .../persist/tests/AbstractManyKeys.java | 15 +-- .../tests/AbstractMergeTransplant.java | 4 +- .../persist/tests/AbstractReferences.java | 9 +- .../org/projectnessie/versioned/Commit.java | 3 +- .../projectnessie/versioned/CommitResult.java | 9 +- .../org/projectnessie/versioned/Hashable.java | 21 ++++ .../versioned/TestMetricsVersionStore.java | 7 +- .../versioned/TestTracingVersionStore.java | 7 +- .../versioned/tests/AbstractCommitLog.java | 3 +- .../versioned/tests/AbstractCommits.java | 3 +- .../versioned/tests/AbstractContents.java | 6 +- .../tests/AbstractDuplicateTable.java | 3 +- .../versioned/tests/AbstractMerge.java | 105 ++++++++++-------- .../tests/AbstractNamespaceValidation.java | 4 +- .../tests/AbstractNoNamespaceValidation.java | 2 +- .../versioned/tests/AbstractSingleBranch.java | 2 +- .../versioned/tests/AbstractTransplant.java | 12 +- .../versioned/tests/CommitBuilder.java | 3 +- .../AbstractITCommitLogOptimization.java | 4 +- .../versioned/transfer/BaseExportImport.java | 3 +- 31 files changed, 148 insertions(+), 133 deletions(-) create mode 100644 versioned/spi/src/main/java/org/projectnessie/versioned/Hashable.java diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java index a661ea235d7..849ab8b18ce 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITExportImport.java @@ -257,7 +257,7 @@ private static void populateRepository(DatabaseAdapter adapter) .toStoreOnReferenceState( IcebergTable.of("meta", 42, 43, 44, 45, tableId)))) .build()); - adapter.create(branchFoo, main.getCommit().getHash()); + adapter.create(branchFoo, main.getCommitHash()); adapter.commit( ImmutableCommitParams.builder() .toBranch(branchFoo) diff --git a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java index a7b2adfe189..12084248d79 100644 --- a/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java +++ b/servers/quarkus-cli/src/intTest/java/org/projectnessie/quarkus/cli/ITNessieInfo.java @@ -60,8 +60,7 @@ public void testMainHash(QuarkusMainLauncher launcher, DatabaseAdapter adapter) .toBranch(BranchName.of("main")) .commitMetaSerialized(ByteString.copyFrom(new byte[] {1, 2, 3})) .build()) - .getCommit() - .getHash(); + .getCommitHash(); LaunchResult result = launcher.launch("info"); assertThat(result.getOutput()).contains(hash.asString()); diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java index ceb7684c2df..7e6ae624218 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/NamespaceApiImpl.java @@ -366,7 +366,6 @@ private Hash commit( Collections.singletonList(contentOperation), validator, (k, c) -> {}) - .getCommit() - .getHash(); + .getCommitHash(); } } diff --git a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java index f62787989e0..461ed222f95 100644 --- a/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java +++ b/servers/services/src/main/java/org/projectnessie/services/impl/TreeApiImpl.java @@ -956,8 +956,7 @@ public CommitResponse commitMultipleOperations( (key, cid) -> { commitResponse.addAddedContents(addedContent(key, cid)); }) - .getCommit() - .getHash(); + .getCommitHash(); return commitResponse.targetBranch(Branch.of(branch, newHash.asString())).build(); } catch (ReferenceNotFoundException e) { diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/CommitLogEntry.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/CommitLogEntry.java index 3edc8fbe243..d6917c11f66 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/CommitLogEntry.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/CommitLogEntry.java @@ -21,13 +21,15 @@ import org.projectnessie.model.ContentKey; import org.projectnessie.nessie.relocated.protobuf.ByteString; import org.projectnessie.versioned.Hash; +import org.projectnessie.versioned.Hashable; /** Represents a commit-log-entry stored in the database. */ @Value.Immutable -public interface CommitLogEntry { +public interface CommitLogEntry extends Hashable { /** Creation timestamp in microseconds since epoch. */ long getCreatedTime(); + @Override Hash getHash(); /** diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java index 0be13ee33a2..7639135e25e 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitLogScan.java @@ -219,8 +219,7 @@ private Hash addCommits( payload, DefaultStoreWorker.instance().toStoreOnReferenceState(c))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); committed.accept(head); } return head; diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java index 18e5f17254c..7e32e726fcd 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractCommitScenarios.java @@ -133,8 +133,7 @@ void commitRenameTable(RenameTable param) throws Exception { .commitMetaSerialized(ByteString.copyFromUtf8("dummy commit meta " + i)) .addUnchanged(dummyKey) .build()) - .getCommit() - .getHash(); + .getCommitHash(); } catch (ReferenceNotFoundException | ReferenceConflictException e) { throw new RuntimeException(e); } @@ -161,7 +160,7 @@ void commitRenameTable(RenameTable param) throws Exception { contentId, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(initialContent))); - Hash hashInitial = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash hashInitial = databaseAdapter.commit(commit.build()).getCommitHash(); List beforeRename = IntStream.range(0, param.afterInitialCommits) @@ -179,7 +178,7 @@ void commitRenameTable(RenameTable param) throws Exception { contentId, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(renamContent))); - Hash hashRename = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash hashRename = databaseAdapter.commit(commit.build()).getCommitHash(); List beforeDelete = IntStream.range(0, param.afterRenameCommits) @@ -191,7 +190,7 @@ void commitRenameTable(RenameTable param) throws Exception { .toBranch(branch) .commitMetaSerialized(ByteString.copyFromUtf8("delete table")) .addDeletes(newKey); - Hash hashDelete = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash hashDelete = databaseAdapter.commit(commit.build()).getCommitHash(); List afterDelete = IntStream.range(0, param.afterDeleteCommits) @@ -281,7 +280,7 @@ void commit(int tablesPerCommit) throws Exception { (byte) payloadForContent(c), DefaultStoreWorker.instance().toStoreOnReferenceState(c))); } - Hash head = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash head = databaseAdapter.commit(commit.build()).getCommitHash(); for (int commitNum = 0; commitNum < 3; commitNum++) { commit = @@ -301,7 +300,7 @@ void commit(int tablesPerCommit) throws Exception { DefaultStoreWorker.instance().toStoreOnReferenceState(newContent))); } - Hash newHead = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash newHead = databaseAdapter.commit(commit.build()).getCommitHash(); assertThat(newHead).isNotEqualTo(head); head = newHead; } @@ -451,8 +450,7 @@ public void smallEmbeddedKeyLists( (byte) payloadForContent(onRefNation), stateNation)) .build()) - .getCommit() - .getHash(); + .getCommitHash(); Hash commitRegion = mine.commit( @@ -467,8 +465,7 @@ public void smallEmbeddedKeyLists( (byte) payloadForContent(onRefRegion), stateRegion)) .build()) - .getCommit() - .getHash(); + .getCommitHash(); List nonExistentKey = Collections.singletonList(ContentKey.of("non_existent")); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java index f2c55a17e86..f279b99a6c2 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractDiff.java @@ -70,7 +70,7 @@ void diff() throws Exception { (byte) payloadForContent(c), DefaultStoreWorker.instance().toStoreOnReferenceState(c))); } - commits[i] = databaseAdapter.commit(commit.build()).getCommit().getHash(); + commits[i] = databaseAdapter.commit(commit.build()).getCommitHash(); } try (Stream diff = diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java index fc815a58a76..9ad841999c2 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractEvents.java @@ -180,8 +180,7 @@ public void eventAssignRef( .commitMetaSerialized(meta) .addPuts(put) .build()) - .getCommit() - .getHash(); + .getCommitHash(); events.events.clear(); @@ -230,8 +229,7 @@ public void eventCommit( .commitMetaSerialized(meta) .addPuts(put) .build()) - .getCommit() - .getHash(); + .getCommitHash(); assertThat(events.events) .hasSize(1) @@ -288,8 +286,7 @@ public void eventMerge( .commitMetaSerialized(meta) .addPuts(put) .build()) - .getCommit() - .getHash(); + .getCommitHash(); events.events.clear(); @@ -364,8 +361,7 @@ public void eventTransplant( .commitMetaSerialized(meta) .addPuts(put) .build()) - .getCommit() - .getHash(); + .getCommitHash(); events.events.clear(); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java index 5802feba2f0..e533c91182b 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractGetNamedReferences.java @@ -400,8 +400,7 @@ private Hash dummyCommit(BranchName branch, Hash expectedHash, int num) throws E (byte) 42, ByteString.copyFromUtf8("dummy content"))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); } private void verifyReferences(ExpectedNamedReference... references) diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java index 0e6e16e6b29..4899557cc04 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyCommits.java @@ -84,7 +84,7 @@ void manyCommits(int numCommits) throws Exception { fixed, payload, DefaultStoreWorker.instance().toStoreOnReferenceState(c))); - Hash hash = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash hash = databaseAdapter.commit(commit.build()).getCommitHash(); commits[i] = hash; } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java index 5c537bdcee6..a222e0afa89 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractManyKeys.java @@ -212,8 +212,7 @@ void enhanceKeyListWithCommitId( DefaultStoreWorker.instance() .toStoreOnReferenceState(onRef("r" + i, "c" + i)))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); keyToCommit.put(key, hash); } @@ -273,8 +272,7 @@ void enhanceKeyListWithCommitId( DefaultStoreWorker.instance() .toStoreOnReferenceState(onRef("pf" + i, "cpf" + i)))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); keyToCommit.put(key, hash); } @@ -343,8 +341,7 @@ void pointContentKeyLookups( (byte) payloadForContent(val), val.serialized())) .build()) - .getCommit() - .getHash(); + .getCommitHash(); } for (int i = 0; i < keyNum; i++) { @@ -505,8 +502,7 @@ private static Hash makeEmptyCommits( .toBranch(toBranch) .commitMetaSerialized(ByteString.EMPTY) .build()) - .getCommit() - .getHash(); + .getCommitHash(); } Preconditions.checkNotNull(head); return head; @@ -618,8 +614,7 @@ private void testManyKeysProgressive(List names, DatabaseAdapter databas DefaultStoreWorker.instance() .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + name)))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); activeKeys.add(key); } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java index e50ee27522b..f26ab084ee3 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java @@ -279,7 +279,7 @@ Hash[] mergeTransplant( commit.addPuts( KeyWithBytes.of(key, ContentId.of("C" + k), (byte) payloadForContent(value), onRef)); } - commits[i] = databaseAdapter.commit(commit.build()).getCommit().getHash(); + commits[i] = databaseAdapter.commit(commit.build()).getCommitHash(); } List commitLogEntries; @@ -416,7 +416,7 @@ void mergeTransplantConflict( (byte) payloadForContent(conflictValue), DefaultStoreWorker.instance().toStoreOnReferenceState(conflictValue))); } - Hash conflictHead = databaseAdapter.commit(commit.build()).getCommit().getHash(); + Hash conflictHead = databaseAdapter.commit(commit.build()).getCommitHash(); List expectedSourceCommits = commitLogEntries.subList(commits.length - 1 - 2, commits.length); diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java index 529c0848938..745e326b646 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractReferences.java @@ -155,8 +155,7 @@ void verifyNotFoundAndConflictExceptionsForUnreachableCommit() throws Exception (byte) payloadForContent(hello), hello.serialized())) .build()) - .getCommit() - .getHash(); + .getCommitHash(); assertAll( () -> @@ -230,8 +229,7 @@ void assign() throws Exception { (byte) payloadForContent(hello), hello.serialized())) .build()) - .getCommit() - .getHash(); + .getCommitHash(); } Hash expect = beginning; @@ -363,8 +361,7 @@ void manyReferences() throws Exception { DefaultStoreWorker.instance() .toStoreOnReferenceState(OnRefOnly.newOnRef("c" + commit)))) .build()) - .getCommit() - .getHash(); + .getCommitHash(); refHeads.put(ref, newHead); } } diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Commit.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Commit.java index e522d604880..5bc3bb4277f 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Commit.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Commit.java @@ -21,11 +21,12 @@ import org.projectnessie.model.CommitMeta; @Value.Immutable -public interface Commit { +public interface Commit extends Hashable { static ImmutableCommit.Builder builder() { return ImmutableCommit.builder(); } + @Override Hash getHash(); CommitMeta getCommitMeta(); diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java index c3f470c1e81..622e6e265ce 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/CommitResult.java @@ -18,7 +18,7 @@ import org.immutables.value.Value; @Value.Immutable -public interface CommitResult extends Result { +public interface CommitResult extends Result { @Override default ResultType getResultType() { @@ -29,7 +29,12 @@ default ResultType getResultType() { BranchName getTargetBranch(); - static ImmutableCommitResult.Builder builder() { + @Value.Derived + default Hash getCommitHash() { + return getCommit().getHash(); + } + + static ImmutableCommitResult.Builder builder() { return ImmutableCommitResult.builder(); } } diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Hashable.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Hashable.java new file mode 100644 index 00000000000..2769430b7d3 --- /dev/null +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Hashable.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Dremio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.projectnessie.versioned; + +public interface Hashable { + + Hash getHash(); +} diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java index 99f99ac5b0f..d02ffaa1a9b 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java @@ -112,13 +112,14 @@ public CommitMeta squash(List metadata) { } }; - CommitResult dummyCommitResult = - CommitResult.builder() + CommitResult dummyCommitResult = + CommitResult.builder() .targetBranch(BranchName.of("foo")) .commit( Commit.builder() .hash(Hash.of("cafebabe")) - .commitMeta(CommitMeta.fromMessage("log#1"))) + .commitMeta(CommitMeta.fromMessage("log#1")) + .build()) .build(); MergeResult dummyMergeResult = diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java index 2ce04ffcefe..bc1ae5b2039 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java @@ -106,13 +106,14 @@ public CommitMeta squash(List metadata) { } }; - CommitResult dummyCommitResult = - CommitResult.builder() + CommitResult dummyCommitResult = + CommitResult.builder() .targetBranch(BranchName.of("foo")) .commit( Commit.builder() .hash(Hash.of("cafebabe")) - .commitMeta(CommitMeta.fromMessage("log#1"))) + .commitMeta(CommitMeta.fromMessage("log#1")) + .build()) .build(); MergeResult dummyMergeResult = diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java index b61997b269b..71551195bfc 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommitLog.java @@ -79,8 +79,7 @@ public void commitLogPaging() throws Exception { commitHashes[i] = store() .commit(branch, Optional.of(parent), msg.build(), ImmutableList.of(op)) - .getCommit() - .getHash(); + .getCommitHash(); messages.add( msg.hash(commitHashes[i].asString()).addParentCommitHashes(parent.asString()).build()); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java index b94281e199f..faf8e10a2a6 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java @@ -96,8 +96,7 @@ public void commitToBranch() throws Exception { Optional.of(initialHash), CommitMeta.fromMessage("Some commit"), Collections.emptyList()) - .getCommit() - .getHash(); + .getCommitHash(); final Hash commitHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(commitHash).isEqualTo(commitHash0); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java index 601f75e1bcc..42a7fe78ed0 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractContents.java @@ -73,7 +73,7 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("create table"), singletonList(Put.of(key, initialState))); soft.assertThat(contentWithoutId(store().getValue(branch, key))).isEqualTo(initialState); - soft.assertThat(contentWithoutId(store().getValue(ancestor.getCommit().getHash(), key))) + soft.assertThat(contentWithoutId(store().getValue(ancestor.getCommitHash(), key))) .isEqualTo(initialState); CommitResult delete = @@ -84,7 +84,7 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("drop table"), ImmutableList.of(Delete.of(key))); soft.assertThat(store().getValue(branch, key)).isNull(); - soft.assertThat(store().getValue(delete.getCommit().getHash(), key)).isNull(); + soft.assertThat(store().getValue(delete.getCommitHash(), key)).isNull(); Content recreateState = newOnRef("value"); CommitResult recreate = @@ -95,7 +95,7 @@ void recreateTable() throws Exception { CommitMeta.fromMessage("drop table"), ImmutableList.of(Put.of(key, recreateState))); soft.assertThat(contentWithoutId(store().getValue(branch, key))).isEqualTo(recreateState); - soft.assertThat(contentWithoutId(store().getValue(recreate.getCommit().getHash(), key))) + soft.assertThat(contentWithoutId(store().getValue(recreate.getCommitHash(), key))) .isEqualTo(recreateState); } } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java index f903fdf67d5..edfa116c079 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractDuplicateTable.java @@ -62,8 +62,7 @@ void duplicateTableOnBranches() throws Throwable { Optional.empty(), CommitMeta.fromMessage("initial commit"), ImmutableList.of(Put.of(ContentKey.of("unrelated-table"), newOnRef("value")))) - .getCommit() - .getHash(); + .getCommitHash(); // Create a table with the same name on two branches. BranchName branch1 = BranchName.of("globalStateDuplicateTable-branch1"); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index bab48cb34d6..eacb97325fd 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -890,7 +890,8 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio MergeBehavior.NORMAL, false, false); - soft.assertThat(mergeResult1.getResultantTargetHash()).isEqualTo(etl1); + soft.assertThat(mergeResult1.getResultantTargetHash()).isEqualTo(etl1.getCommitHash()); + soft.assertThat(mergeResult1.getAddedCommits()).containsExactly(etl1.getCommit()); Hash etl2 = store() @@ -911,7 +912,8 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio MergeBehavior.NORMAL, false, false); - soft.assertThat(mergeResult2.getResultantTargetHash()).isEqualTo(etl2); + soft.assertThat(mergeResult2.getResultantTargetHash()).isEqualTo(etl2.getCommitHash()); + soft.assertThat(mergeResult2.getAddedCommits()).containsExactly(etl2.getCommit()); soft.assertThat(contentWithoutId(store().getValue(review, key))).isEqualTo(VALUE_2); } @@ -1039,7 +1041,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - mergeFromHash, + sourceBranch, + mergeFromHash.getCommitHash(), mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1061,7 +1064,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - mergeFromHash, + sourceBranch, + mergeFromHash.getCommitHash(), mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1085,7 +1089,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - mergeFromHash, + sourceBranch, + mergeFromHash.getCommitHash(), mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1109,7 +1114,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - mergeFromHash, + sourceBranch, + mergeFromHash.getCommitHash(), mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1137,24 +1143,26 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu } }; - soft.assertThat(mergeIntoHeadSupplier.get()).isEqualTo(mergeIntoHead); + soft.assertThat(mergeIntoHeadSupplier.get()).isEqualTo(mergeIntoHead.getCommitHash()); // Merge with force-merge of conflictingKey1 + drop of conflictingKey2 - store() - .merge( - mergeFromHash, - mergeInto, - Optional.empty(), - createMetadataRewriter(", merge-force-1"), - individualCommits, - ImmutableMap.of( - conflictingKey1, - MergeKeyBehavior.of(conflictingKey1, MergeBehavior.FORCE), - conflictingKey2, - MergeKeyBehavior.of(conflictingKey2, MergeBehavior.DROP)), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .merge( + sourceBranch, + mergeFromHash.getCommitHash(), + mergeInto, + Optional.empty(), + createMetadataRewriter(", merge-force-1"), + individualCommits, + ImmutableMap.of( + conflictingKey1, + MergeKeyBehavior.of(conflictingKey1, MergeBehavior.FORCE), + conflictingKey2, + MergeKeyBehavior.of(conflictingKey2, MergeBehavior.DROP)), + MergeBehavior.NORMAL, + false, + false); soft.assertThat( contentsWithoutId( store.getValues( @@ -1178,8 +1186,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .contains("commit 2, merge-force-1") .contains("commit 4, merge-force-1"); } - soft.assertThat(commit.getParentHash()) - .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1193,20 +1200,22 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu }); // reset merge-into branch - store().assign(mergeInto, Optional.empty(), mergeIntoHead); + store().assign(mergeInto, Optional.empty(), mergeIntoHead.getCommitHash()); // Merge with force-merge of conflictingKey1 + drop of conflictingKey2 - store() - .merge( - mergeFromHash, - mergeInto, - Optional.empty(), - createMetadataRewriter(", merge-all-force"), - individualCommits, - Collections.emptyMap(), - MergeBehavior.FORCE, - false, - false); + MergeResult result2 = + store() + .merge( + sourceBranch, + mergeFromHash.getCommitHash(), + mergeInto, + Optional.empty(), + createMetadataRewriter(", merge-all-force"), + individualCommits, + Collections.emptyMap(), + MergeBehavior.FORCE, + false, + false); soft.assertThat( contentsWithoutId( store.getValues( @@ -1224,8 +1233,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu commit -> { soft.assertThat(commit.getCommitMeta().getMessage()) .isEqualTo("commit 2, merge-all-force"); - soft.assertThat(commit.getParentHash()) - .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1261,8 +1269,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu soft.assertThat(commit.getCommitMeta().getMessage()) .contains("commit 2, merge-all-force") .contains("commit 4, merge-all-force"); - soft.assertThat(commit.getParentHash()) - .isEqualTo(mergeIntoHead.getCommit().getHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1398,7 +1405,8 @@ protected void mergeEmptyCommit(boolean individualCommits, boolean dryRun) target, Optional.empty(), CommitMeta.fromMessage("target 1"), - singletonList(Put.of(key1, VALUE_1))); + singletonList(Put.of(key1, VALUE_1))) + .getCommitHash(); targetHead = store() @@ -1406,7 +1414,8 @@ protected void mergeEmptyCommit(boolean individualCommits, boolean dryRun) target, Optional.of(targetHead), CommitMeta.fromMessage("target 2"), - singletonList(Put.of(key2, VALUE_1))); + singletonList(Put.of(key2, VALUE_1))) + .getCommitHash(); // Add two commits to the source branch, with conflicting changes to key1 and key2 @@ -1416,7 +1425,8 @@ protected void mergeEmptyCommit(boolean individualCommits, boolean dryRun) source, Optional.empty(), CommitMeta.fromMessage("source 1"), - singletonList(Put.of(key1, VALUE_2))); + singletonList(Put.of(key1, VALUE_2))) + .getCommitHash(); sourceHead = store() @@ -1424,7 +1434,8 @@ protected void mergeEmptyCommit(boolean individualCommits, boolean dryRun) source, Optional.of(sourceHead), CommitMeta.fromMessage("source 2"), - singletonList(Put.of(key2, VALUE_2))); + singletonList(Put.of(key2, VALUE_2))) + .getCommitHash(); // Merge the source branch into the target branch, with a drop of key1 and key2 @@ -1466,7 +1477,8 @@ public void mergeFromAndIntoHead(boolean dryRun) throws Exception { branch, Optional.empty(), CommitMeta.fromMessage("commit 1"), - singletonList(Put.of(key1, VALUE_1))); + singletonList(Put.of(key1, VALUE_1))) + .getCommitHash(); Hash commit2 = store() @@ -1474,7 +1486,8 @@ public void mergeFromAndIntoHead(boolean dryRun) throws Exception { branch, Optional.empty(), CommitMeta.fromMessage("commit 2"), - singletonList(Put.of(key2, VALUE_2))); + singletonList(Put.of(key2, VALUE_2))) + .getCommitHash(); soft.assertThatIllegalArgumentException() .isThrownBy( diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java index 2f232bff0eb..cff047e8b76 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNamespaceValidation.java @@ -276,7 +276,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp : asList(Put.of(ns.toContentKey(), ns), Put.of(ns2.toContentKey(), ns2))); BranchName branch = BranchName.of("branch"); - store().create(branch, Optional.of(rootHead.getCommit().getHash())); + store().create(branch, Optional.of(rootHead.getCommitHash())); if (mode.createNamespaceOnTarget) { store() @@ -332,7 +332,7 @@ void mergeTransplantWithCommonButRemovedNamespace(NamespaceValidationMergeTransp branch, root, Optional.empty(), - asList(commit1.getCommit().getHash(), commit2.getCommit().getHash()), + asList(commit1.getCommitHash(), commit2.getCommitHash()), METADATA_REWRITER, mode.individualCommits, emptyMap(), diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java index 0bbbfe8d2f7..62cc71dfdeb 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractNoNamespaceValidation.java @@ -78,7 +78,7 @@ void mergeTransplant(boolean merge, boolean individual) throws Exception { CommitMeta.fromMessage("common ancestor"), singletonList(Put.of(ContentKey.of("dummy"), newOnRef("dummy")))); - store().create(branch, Optional.of(rootHead.getCommit().getHash())); + store().create(branch, Optional.of(rootHead.getCommitHash())); soft.assertThatCode( () -> diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java index 29ba763881e..ee5b433b8c8 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractSingleBranch.java @@ -128,7 +128,7 @@ void singleBranchManyUsers(SingleBranchParam param) throws Exception { } } - parent = commitHash.getCommit().getHash(); + parent = commitHash.getCommitHash(); expectedValues.add(msg.hash(parent.asString()).build()); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index cddec5b811c..cf363808ebd 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -685,8 +685,7 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt Optional.empty(), CommitMeta.fromMessage("target 1"), singletonList(Put.of(key1, V_1_1))) - .getCommit() - .getHash(); + .getCommitHash(); targetHead = store() @@ -695,8 +694,7 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt Optional.of(targetHead), CommitMeta.fromMessage("target 2"), singletonList(Put.of(key2, V_2_1))) - .getCommit() - .getHash(); + .getCommitHash(); // Add two commits to the source branch, with conflicting changes to key1 and key2 @@ -707,8 +705,7 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt Optional.empty(), CommitMeta.fromMessage("source 1"), singletonList(Put.of(key1, V_1_2))) - .getCommit() - .getHash(); + .getCommitHash(); Hash source2 = store() @@ -717,8 +714,7 @@ protected void transplantEmptyCommit(boolean individualCommits) throws VersionSt Optional.of(source1), CommitMeta.fromMessage("source 2"), singletonList(Put.of(key2, V_2_2))) - .getCommit() - .getHash(); + .getCommitHash(); // Transplant the source branch into the target branch, with a drop of key1 and key2 diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java index 02dee9ffc17..c2ed3070035 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/CommitBuilder.java @@ -162,8 +162,7 @@ public Hash toBranch(BranchName branchName) fromLatest ? Optional.of(store.hashOnReference(branchName, Optional.empty())) : referenceHash; - Hash commitHash = - store.commit(branchName, reference, metadata, operations).getCommit().getHash(); + Hash commitHash = store.commit(branchName, reference, metadata, operations).getCommitHash(); Hash storeHash = store.hashOnReference(branchName, Optional.empty()); Assertions.assertEquals(storeHash, commitHash); return commitHash; diff --git a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java index 146a5f73d9b..facbea052d0 100644 --- a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java +++ b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/AbstractITCommitLogOptimization.java @@ -134,7 +134,7 @@ public void multipleBranches( Hash parent = databaseAdapter.noAncestorHash(); for (; commitSeqMain <= commitsAtBeginningOfTime; commitSeqMain++) { - parent = addCommit(0, commitSeqMain).getCommit().getHash(); + parent = addCommit(0, commitSeqMain).getCommitHash(); totalCommits++; } @@ -146,7 +146,7 @@ public void multipleBranches( } for (int i = 0; i < ((branch == branches) ? commitsAtHead : commitsBetweenBranches); i++) { - parent = addCommit(0, commitSeqMain++).getCommit().getHash(); + parent = addCommit(0, commitSeqMain++).getCommitHash(); totalCommits++; } } diff --git a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java index cc34d0eb95d..2f212a51874 100644 --- a/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java +++ b/versioned/transfer/src/testFixtures/java/org/projectnessie/versioned/transfer/BaseExportImport.java @@ -344,8 +344,7 @@ private static Hash commit10(VersionStore versionStore, int offset, BranchName b 43, 44, 45)))) - .getCommit() - .getHash(); + .getCommitHash(); } return head; } From 73255c9ac8145059b36f074f83ff1eed7a4da77a Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 24 Apr 2023 16:47:05 +0200 Subject: [PATCH 07/26] Throw RE from commitObjToCommit --- .../versioned/storage/versionstore/BaseCommitHelper.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java index 26648f9052b..eafb3a0717e 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java @@ -520,7 +520,7 @@ ImmutableMergeResult mergeSquashFastForward( CommitObj source, ImmutableMergeResult.Builder result, MergeBehaviors mergeBehaviors) - throws RetryException, ReferenceNotFoundException { + throws RetryException { result.wasSuccessful(true); IndexesLogic indexesLogic = indexesLogic(persist); @@ -737,12 +737,14 @@ MergeResult finishMergeTransplant( return mergeResult.build(); } - Commit commitObjToCommit(CommitObj newCommit) throws ReferenceNotFoundException { + Commit commitObjToCommit(CommitObj newCommit) { try { ContentMapping contentMapping = new ContentMapping(persist); return contentMapping.commitObjToCommit(true, newCommit); } catch (ObjNotFoundException e) { - throw referenceNotFound(e); + // This should never happen, since we just created the commit object; + // if it does, it's a pretty serious state corruption. + throw new RuntimeException(e); } } } From d964a08c68f3787f6d3221111ddcfe0af668438e Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 24 Apr 2023 17:06:22 +0200 Subject: [PATCH 08/26] Fetch all puts at once --- .../storage/versionstore/ContentMapping.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index f94f10ccbd3..6f6d004e4fb 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -25,6 +25,7 @@ import static org.projectnessie.versioned.storage.versionstore.TypeMapping.toCommitMeta; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.Nonnull; import org.projectnessie.model.CommitMeta; @@ -133,6 +134,7 @@ public Commit commitObjToCommit( if (fetchAdditionalInfo) { ContentKey key; IndexesLogic indexesLogic = indexesLogic(persist); + Map objIds = new LinkedHashMap<>(); for (StoreIndexElement op : indexesLogic.commitOperations(commitObj)) { key = storeKeyToKey(op.key()); // Note: key==null, if not the "main universe" or not a "content" discriminator @@ -140,14 +142,22 @@ public Commit commitObjToCommit( CommitOp c = op.content(); if (c.action().exists()) { ObjId objId = requireNonNull(c.value(), "Required value pointer is null"); - ContentValueObj contentValue = - persist.fetchTypedObj(objId, VALUE, ContentValueObj.class); - commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); + objIds.put(objId, key); } else { commit.addOperations(Delete.of(key)); } } } + if (!objIds.isEmpty()) { + Obj[] objs = persist.fetchObjs(objIds.keySet().toArray(new ObjId[0])); + for (int i = 0; i < objIds.size(); i++) { + Obj obj = objs[i]; + assert obj instanceof ContentValueObj; + ContentValueObj contentValue = (ContentValueObj) obj; + key = objIds.get(obj.id()); + commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); + } + } } return commit.commitMeta(commitMeta).build(); From b325a8e6945f58397aaaef2e5c988775dae7a32a Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 24 Apr 2023 17:06:37 +0200 Subject: [PATCH 09/26] Add Put.toString --- .../main/java/org/projectnessie/versioned/Put.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index b45fa0dfbe1..45fc7069913 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -15,6 +15,7 @@ */ package org.projectnessie.versioned; +import com.google.common.base.MoreObjects; import java.util.Objects; import java.util.function.Supplier; import javax.annotation.Nonnull; @@ -111,4 +112,14 @@ public boolean equals(@Nullable Object o) { public int hashCode() { return Objects.hash(shouldMatchHash(), getKey(), getValue()); } + + @Override + public String toString() { + return MoreObjects.toStringHelper("Put") + .omitNullValues() + .add("shouldMatchHash", shouldMatchHash()) + .add("key", getKey()) + .add("value", getValue()) + .toString(); + } } From 146af71d9c6d5d9cf34e18dbbcd0aa23ef3d8e07 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 24 Apr 2023 17:13:44 +0200 Subject: [PATCH 10/26] cleanup --- .../storage/versionstore/ContentMapping.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index 6f6d004e4fb..81d16c5aa1e 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -132,29 +132,28 @@ public Commit commitObjToCommit( CommitMeta commitMeta = toCommitMeta(commitObj); if (fetchAdditionalInfo) { - ContentKey key; IndexesLogic indexesLogic = indexesLogic(persist); - Map objIds = new LinkedHashMap<>(); + Map idsToKeys = new LinkedHashMap<>(); for (StoreIndexElement op : indexesLogic.commitOperations(commitObj)) { - key = storeKeyToKey(op.key()); + ContentKey key = storeKeyToKey(op.key()); // Note: key==null, if not the "main universe" or not a "content" discriminator if (key != null) { CommitOp c = op.content(); if (c.action().exists()) { ObjId objId = requireNonNull(c.value(), "Required value pointer is null"); - objIds.put(objId, key); + idsToKeys.put(objId, key); } else { commit.addOperations(Delete.of(key)); } } } - if (!objIds.isEmpty()) { - Obj[] objs = persist.fetchObjs(objIds.keySet().toArray(new ObjId[0])); - for (int i = 0; i < objIds.size(); i++) { - Obj obj = objs[i]; + if (!idsToKeys.isEmpty()) { + ObjId[] ids = idsToKeys.keySet().toArray(new ObjId[0]); + Obj[] objs = persist.fetchObjs(ids); + for (Obj obj : objs) { assert obj instanceof ContentValueObj; ContentValueObj contentValue = (ContentValueObj) obj; - key = objIds.get(obj.id()); + ContentKey key = idsToKeys.get(obj.id()); commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); } } From 58718c69a49d99c5dc41f950dcc2b887a1aec856 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Mon, 24 Apr 2023 17:18:42 +0200 Subject: [PATCH 11/26] Fix errors --- .../versioned/EventsVersionStore.java | 7 - .../projectnessie/versioned/MergeResult.java | 2 +- .../versioned/TestMetricsVersionStore.java | 8 +- .../versioned/TestTracingVersionStore.java | 8 +- .../commontests/AbstractCommitLogicTests.java | 34 ++-- .../storage/versionstore/CommitImpl.java | 2 + .../versionstore/VersionStoreImpl.java | 7 +- .../versioned/tests/AbstractMerge.java | 190 ++++++++++++------ 8 files changed, 163 insertions(+), 95 deletions(-) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java index d428406bbb5..b0e5c8ea3ee 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java @@ -220,11 +220,4 @@ public PaginationIterator getDiffs(Ref from, Ref to, String pagingToken) public Stream getRefLog(Hash refLogId) throws RefLogNotFoundException { return delegate.getRefLog(refLogId); } - - @Nonnull - @jakarta.annotation.Nonnull - @Override - public RepositoryInformation getRepositoryInformation() { - return delegate.getRepositoryInformation(); - } } diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java index 26b7e19178a..b17e5c7162b 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java @@ -135,7 +135,7 @@ enum ConflictType { UNRESOLVABLE } - static ImmutableMergeResult.Builder builder() { + static ImmutableMergeResult.Builder builder() { return ImmutableMergeResult.builder(); } } diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java index d02ffaa1a9b..746a2b33ea7 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestMetricsVersionStore.java @@ -122,16 +122,16 @@ public CommitMeta squash(List metadata) { .build()) .build(); - MergeResult dummyMergeResult = - MergeResult.builder() + MergeResult dummyMergeResult = + MergeResult.builder() .resultType(ResultType.MERGE) .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); - MergeResult dummyTransplantResult = - MergeResult.builder() + MergeResult dummyTransplantResult = + MergeResult.builder() .resultType(ResultType.TRANSPLANT) .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java index bc1ae5b2039..0279b62fdaa 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestTracingVersionStore.java @@ -116,16 +116,16 @@ public CommitMeta squash(List metadata) { .build()) .build(); - MergeResult dummyMergeResult = - MergeResult.builder() + MergeResult dummyMergeResult = + MergeResult.builder() .resultType(ResultType.MERGE) .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) .effectiveTargetHash(Hash.of("123456")) .build(); - MergeResult dummyTransplantResult = - MergeResult.builder() + MergeResult dummyTransplantResult = + MergeResult.builder() .resultType(ResultType.TRANSPLANT) .sourceRef(BranchName.of("foo")) .targetBranch(BranchName.of("bar")) diff --git a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java index 84ae49c0f0f..1a4cacb6333 100644 --- a/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java +++ b/versioned/storage/common-tests/src/main/java/org/projectnessie/versioned/storage/commontests/AbstractCommitLogicTests.java @@ -648,14 +648,15 @@ void commitWithModifiedExpectedValue() throws Exception { ObjId tip = requireNonNull( - commitLogic.doCommit( - newCommitBuilder() - .headers(EMPTY_COMMIT_HEADERS) - .message("msg foo") - .parentCommitId(EMPTY_OBJ_ID) - .addAdds(commitAdd(key, 0, correctValue, null, null)) - .build(), - emptyList())); + commitLogic.doCommit( + newCommitBuilder() + .headers(EMPTY_COMMIT_HEADERS) + .message("msg foo") + .parentCommitId(EMPTY_OBJ_ID) + .addAdds(commitAdd(key, 0, correctValue, null, null)) + .build(), + emptyList())) + .id(); // Put the correct expected value into the Commit-ADD operation, but "break" it in the callback // by adding a wrong expected value-ID. @@ -714,14 +715,15 @@ void commitWithModifiedCommittedValue() throws Exception { ObjId tip = requireNonNull( - commitLogic.doCommit( - newCommitBuilder() - .headers(EMPTY_COMMIT_HEADERS) - .message("msg foo") - .parentCommitId(EMPTY_OBJ_ID) - .addAdds(commitAdd(key, 0, initialValue, null, null)) - .build(), - emptyList())); + commitLogic.doCommit( + newCommitBuilder() + .headers(EMPTY_COMMIT_HEADERS) + .message("msg foo") + .parentCommitId(EMPTY_OBJ_ID) + .addAdds(commitAdd(key, 0, initialValue, null, null)) + .build(), + emptyList())) + .id(); CommitObj commit = commitLogic.buildCommitObj( diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java index 1ca02e5e087..4e5391545a8 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/CommitImpl.java @@ -417,6 +417,8 @@ private void commitAddPut( private String contentIdFromContent(@Nonnull @jakarta.annotation.Nonnull ObjId contentValueId) throws ObjNotFoundException { + // TODO pre-load these objects, so they are bulk-loaded and in turn available via the cache + // https://github.com/projectnessie/nessie/issues/6673 return contentMapping.fetchContent(contentValueId).getId(); } } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java index 03f925c7a85..d4e92441cfd 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/VersionStoreImpl.java @@ -667,12 +667,7 @@ public MergeResult merge( supplier, (merge, retryState) -> merge.merge( - retryState, - fromRef, - fromHash, - updateCommitMetadata, - mergeBehaviors, - dryRun)); + retryState, fromRef, fromHash, updateCommitMetadata, mergeBehaviors, dryRun)); return mergeTransplantResponse(mergeResult); } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index eacb97325fd..9e3e537b8ec 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -51,6 +51,8 @@ import org.projectnessie.model.MergeKeyBehavior; import org.projectnessie.versioned.BranchName; import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; +import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.MergeConflictException; @@ -61,6 +63,7 @@ import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; +import org.projectnessie.versioned.ResultType; import org.projectnessie.versioned.VersionStore; import org.projectnessie.versioned.VersionStoreException; import org.projectnessie.versioned.paging.PaginationIterator; @@ -162,6 +165,7 @@ protected void mergeKeyBehaviorValidation(boolean dryRun) throws Exception { () -> store() .merge( + MAIN_BRANCH, thirdCommit, targetBranch, Optional.empty(), @@ -184,6 +188,7 @@ protected void mergeKeyBehaviorValidation(boolean dryRun) throws Exception { () -> store() .merge( + MAIN_BRANCH, thirdCommit, targetBranch, Optional.empty(), @@ -207,6 +212,7 @@ protected void mergeKeyBehaviorValidation(boolean dryRun) throws Exception { () -> store() .merge( + MAIN_BRANCH, thirdCommit, targetBranch, Optional.empty(), @@ -261,6 +267,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto () -> store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -281,6 +288,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto () -> store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -307,6 +315,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto () -> store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -331,6 +340,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto () -> store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -358,6 +368,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto () -> store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -375,6 +386,7 @@ protected void mergeResolveConflict(boolean individualCommits) throws VersionSto MergeResult result = store() .merge( + sourceBranch, sourceHead, MAIN_BRANCH, Optional.empty(), @@ -440,17 +452,21 @@ private void doMergeIntoEmpty( BranchName newBranch, MetadataRewriter metadataRewriter) throws ReferenceNotFoundException, ReferenceConflictException { - store() - .merge( - thirdCommit, - newBranch, - Optional.of(initialHash), - metadataRewriter, - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .merge( + MAIN_BRANCH, + thirdCommit, + newBranch, + Optional.of(initialHash), + metadataRewriter, + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); + + checkTargetCommits(individualCommits, initialHash, result); soft.assertThat( contentsWithoutId( store() @@ -555,7 +571,7 @@ private void checkTargetCommits( .hasSizeBetween(3, 4) .anySatisfy( o -> { - if (c.getOperations().size() == 4) { + if (c.getOperations() != null && c.getOperations().size() == 4) { soft.assertThat(o).isInstanceOf(Delete.class); soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); } @@ -595,6 +611,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio MergeResult dryMergeResult = store() .merge( + MAIN_BRANCH, firstCommit, newBranch, Optional.of(initialHash), @@ -622,6 +639,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio MergeResult mergeResult = store() .merge( + MAIN_BRANCH, firstCommit, newBranch, Optional.of(initialHash), @@ -655,6 +673,12 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio Put.of(ContentKey.of("t2"), V_2_1), Put.of(ContentKey.of("t3"), V_3_1))))); soft.assertThat(mergeResult.getTargetCommits()).isNull(); + // The branch was fast-forwarded to firstCommit, so the only added commit is firstCommit + // itself + soft.assertThat(mergeResult.getAddedCommits()) + .singleElement() + .extracting("hash") + .isEqualTo(firstCommit); soft.assertThat(mergeResult.getDetails()) .containsKeys(ContentKey.of("t1"), ContentKey.of("t2"), ContentKey.of("t3")); soft.assertThat(mergeResult) @@ -662,7 +686,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio .isEqualTo( MergeResult.builder() .resultType(ResultType.MERGE) - .sourceRef(sourceBranch) + .sourceRef(MAIN_BRANCH) .wasApplied(true) .wasSuccessful(true) .commonAncestor(initialHash) @@ -671,6 +695,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio .effectiveTargetHash(initialHash) .expectedHash(initialHash) .addAllSourceCommits(mergeResult.getSourceCommits()) + .addAllAddedCommits(mergeResult.getAddedCommits()) .putAllDetails(mergeResult.getDetails()) .build()) // compare "effective" merge-result with dry-run merge-result @@ -691,17 +716,19 @@ protected void mergeIntoEmptyBranch1Commit(boolean individualCommits) MetadataRewriter metadataRewriter = createMetadataRewriter(""); - store() - .merge( - firstCommit, - newBranch, - Optional.of(initialHash), - metadataRewriter, - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .merge( + MAIN_BRANCH, + firstCommit, + newBranch, + Optional.of(initialHash), + metadataRewriter, + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); soft.assertThat( contentsWithoutId( store() @@ -720,6 +747,10 @@ protected void mergeIntoEmptyBranch1Commit(boolean individualCommits) // not modifying commit meta, will just "fast forward" soft.assertThat(store().hashOnReference(newBranch, Optional.empty())).isEqualTo(firstCommit); + soft.assertThat(result.getAddedCommits()) + .singleElement() + .extracting(Commit::getParentHash, Commit::getHash) + .containsExactly(initialHash, firstCommit); List mergedCommit = commitsList(newBranch, false).subList(0, 1); assertCommitMeta(soft, mergedCommit, commits.subList(2, 3), metadataRewriter); @@ -785,6 +816,7 @@ protected void mergeIntoNonConflictingBranch(boolean individualCommits) MergeResult result = store() .merge( + MAIN_BRANCH, thirdCommit, newBranch, Optional.empty(), @@ -858,6 +890,30 @@ protected void mergeIntoNonConflictingBranch(boolean individualCommits) c3 -> assertThat(c3).extracting(Commit::getHash).isEqualTo(newCommit), c4 -> assertThat(c4).extracting(Commit::getHash).isEqualTo(initialHash)); } + if (individualCommits) { + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .satisfiesExactly( + commit -> { + soft.assertThat(commit.getParentHash()).isEqualTo(newCommit); + soft.assertThat(commit.getCommitMeta().getMessage()).isEqualTo("First Commit"); + }, + commit -> { + soft.assertThat(commit.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(commit.getCommitMeta().getMessage()).isEqualTo("Second Commit"); + }, + commit -> { + soft.assertThat(commit.getParentHash()) + .isEqualTo(result.getAddedCommits().get(1).getHash()); + soft.assertThat(commit.getCommitMeta().getMessage()).isEqualTo("Third Commit"); + }); + } else { + soft.assertThat(result.getAddedCommits()) + .singleElement() + .extracting(Commit::getParentHash) + .isEqualTo(newCommit); + } } @ParameterizedTest @@ -870,7 +926,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio store().create(review, Optional.of(initialHash)); MetadataRewriter metadataRewriter = createMetadataRewriter(""); - Hash etl1 = + CommitResult etl1 = store() .commit( etl, @@ -881,6 +937,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio MergeResult mergeResult1 = store() .merge( + etl, store().hashOnReference(etl, Optional.empty()), review, Optional.empty(), @@ -893,7 +950,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio soft.assertThat(mergeResult1.getResultantTargetHash()).isEqualTo(etl1.getCommitHash()); soft.assertThat(mergeResult1.getAddedCommits()).containsExactly(etl1.getCommit()); - Hash etl2 = + CommitResult etl2 = store() .commit( etl, @@ -903,6 +960,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio MergeResult mergeResult2 = store() .merge( + etl, store().hashOnReference(etl, Optional.empty()), review, Optional.empty(), @@ -928,17 +986,19 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version MetadataRewriter metadataRewriter = createMetadataRewriter(""); - store() - .merge( - thirdCommit, - newBranch, - Optional.empty(), - metadataRewriter, - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); + MergeResult result = + store() + .merge( + MAIN_BRANCH, + thirdCommit, + newBranch, + Optional.empty(), + metadataRewriter, + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); soft.assertThat( contentsWithoutId( store() @@ -957,7 +1017,7 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version ContentKey.of("t4"), V_4_1, ContentKey.of("t5"), V_5_1)); - final List commits = commitsList(newBranch, false); + final List commits = commitsList(newBranch, true); if (individualCommits) { soft.assertThat(commits) .hasSize(5) @@ -967,6 +1027,12 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version c -> assertThat(c.getHash()).isEqualTo(newCommit), c -> assertThat(c.getHash()).isEqualTo(firstCommit), c -> assertThat(c.getHash()).isEqualTo(initialHash)); + soft.assertThat(result.getAddedCommits()) + .hasSize(2) + .satisfiesExactly( + c -> assertThat(c).isEqualTo(commits.get(1)), + c -> assertThat(c).isEqualTo(commits.get(0))); + } else { soft.assertThat(commits) .hasSize(4) @@ -978,6 +1044,8 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version c -> assertThat(c.getHash()).isEqualTo(firstCommit), c -> assertThat(c.getHash()).isEqualTo(initialHash)); + soft.assertThat(result.getAddedCommits()).singleElement().isEqualTo(commits.get(0)); + soft.assertThat(commits) .first() .extracting(Commit::getCommitMeta) @@ -1026,14 +1094,16 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu mergeInto, Optional.empty(), CommitMeta.fromMessage("commit 3"), - Arrays.asList(Put.of(conflictingKey2, VALUE_3), Put.of(key4, VALUE_6))); + Arrays.asList(Put.of(conflictingKey2, VALUE_3), Put.of(key4, VALUE_6))) + .getCommitHash(); Hash mergeFromHash = store() .commit( mergeFrom, Optional.empty(), CommitMeta.fromMessage("commit 4"), - singletonList(Put.of(conflictingKey2, VALUE_4))); + singletonList(Put.of(conflictingKey2, VALUE_4))) + .getCommitHash(); StorageAssertions checkpoint = storageCheckpoint(); // "Plain" merge attempt - all keys default to MergeBehavior.NORMAL @@ -1041,8 +1111,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1064,8 +1134,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1089,8 +1159,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1114,8 +1184,8 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu () -> store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(""), @@ -1143,14 +1213,14 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu } }; - soft.assertThat(mergeIntoHeadSupplier.get()).isEqualTo(mergeIntoHead.getCommitHash()); + soft.assertThat(mergeIntoHeadSupplier.get()).isEqualTo(mergeIntoHead); // Merge with force-merge of conflictingKey1 + drop of conflictingKey2 MergeResult result = store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(", merge-force-1"), @@ -1186,7 +1256,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .contains("commit 2, merge-force-1") .contains("commit 4, merge-force-1"); } - soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1200,14 +1270,14 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu }); // reset merge-into branch - store().assign(mergeInto, Optional.empty(), mergeIntoHead.getCommitHash()); + store().assign(mergeInto, Optional.empty(), mergeIntoHead); // Merge with force-merge of conflictingKey1 + drop of conflictingKey2 MergeResult result2 = store() .merge( - sourceBranch, - mergeFromHash.getCommitHash(), + mergeFrom, + mergeFromHash, mergeInto, Optional.empty(), createMetadataRewriter(", merge-all-force"), @@ -1233,7 +1303,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu commit -> { soft.assertThat(commit.getCommitMeta().getMessage()) .isEqualTo("commit 2, merge-all-force"); - soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1269,7 +1339,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu soft.assertThat(commit.getCommitMeta().getMessage()) .contains("commit 2, merge-all-force") .contains("commit 4, merge-all-force"); - soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead.getCommitHash()); + soft.assertThat(commit.getParentHash()).isEqualTo(mergeIntoHead); soft.assertThat(commit.getOperations()) .satisfiesExactlyInAnyOrder( op -> { @@ -1309,6 +1379,7 @@ protected void mergeIntoConflictingBranch(boolean individualCommits, boolean dry () -> store() .merge( + MAIN_BRANCH, thirdCommit, newBranch, Optional.of(initialHash), @@ -1338,6 +1409,7 @@ protected void mergeIntoNonExistingBranch(boolean individualCommits, boolean dry () -> store() .merge( + MAIN_BRANCH, thirdCommit, newBranch, Optional.of(initialHash), @@ -1367,6 +1439,7 @@ protected void mergeIntoNonExistingReference(boolean individualCommits, boolean () -> store() .merge( + MAIN_BRANCH, Hash.of("1234567890abcdef"), newBranch, Optional.of(initialHash), @@ -1441,6 +1514,7 @@ protected void mergeEmptyCommit(boolean individualCommits, boolean dryRun) store() .merge( + source, sourceHead, target, Optional.ofNullable(targetHead), @@ -1494,6 +1568,7 @@ public void mergeFromAndIntoHead(boolean dryRun) throws Exception { () -> store() .merge( + branch, commit2, branch, Optional.of(commit1), @@ -1509,6 +1584,7 @@ public void mergeFromAndIntoHead(boolean dryRun) throws Exception { () -> store() .merge( + branch, commit1, branch, Optional.of(commit2), From f57a7201eaf189d1a4b1dc9434cfa5bbe5d635ca Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 26 Apr 2023 15:33:08 +0200 Subject: [PATCH 12/26] Minor nits --- .../src/main/java/org/projectnessie/versioned/Put.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index 45fc7069913..7ae99b5cfe2 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -26,10 +26,7 @@ import org.projectnessie.nessie.relocated.protobuf.ByteString; import org.projectnessie.versioned.store.DefaultStoreWorker; -/** - * A PUT operation provided by the client in order to set a new value in a commit. Can optionally - * declare whether the prior hash must match. - */ +/** Setting a new value. Can optionally declare whether the prior hash must match. */ @Value.Immutable public abstract class Put implements Operation { @@ -94,6 +91,9 @@ public static Put of( .build(); } + // Redefine equals() and hashCode() because even if getValue() is @Lazy, + // we want it in the computation, and not getValueSupplier(). + @Override public boolean equals(@Nullable Object o) { if (this == o) { From 4a1678ca39e3ba9ac0b2cbc8717e0231619d730a Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 27 Apr 2023 18:59:23 +0200 Subject: [PATCH 13/26] Use soft assertions --- .../storage/common/logic/TestIndexesLogicImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java index d18eacec865..e56cd51f492 100644 --- a/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java +++ b/versioned/storage/common/src/test/java/org/projectnessie/versioned/storage/common/logic/TestIndexesLogicImpl.java @@ -17,7 +17,6 @@ import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; -import static org.assertj.core.api.Assertions.assertThat; import static org.projectnessie.versioned.storage.common.indexes.StoreIndexElement.indexElement; import static org.projectnessie.versioned.storage.common.indexes.StoreIndexes.newStoreIndex; import static org.projectnessie.versioned.storage.common.indexes.StoreKey.key; @@ -78,9 +77,10 @@ public void completeIndexesInCommitChain(boolean discrete) throws Exception { } ObjId secondaryHeadId = secondary.get(0); CommitObj secondaryHead = commitLogic.fetchCommit(secondaryHeadId); - assertThat(secondaryHead).isNotNull(); + soft.assertThat(secondaryHead).isNotNull(); soft.assertThatIllegalArgumentException() - .isThrownBy(() -> indexesLogic.buildCompleteIndex(secondaryHead, Optional.empty())); + .isThrownBy( + () -> indexesLogic.buildCompleteIndex(requireNonNull(secondaryHead), Optional.empty())); // add incomplete commit, with a reference to a set of other incomplete commits, // simulating a merge @@ -96,9 +96,9 @@ public void completeIndexesInCommitChain(boolean discrete) throws Exception { ObjId headId = tail.get(0); CommitObj head = commitLogic.fetchCommit(headId); - assertThat(head).isNotNull(); + soft.assertThat(head).isNotNull(); soft.assertThatIllegalArgumentException() - .isThrownBy(() -> indexesLogic.buildCompleteIndex(head, Optional.empty())); + .isThrownBy(() -> indexesLogic.buildCompleteIndex(requireNonNull(head), Optional.empty())); soft.assertThat(indexesLogic.findCommitsWithIncompleteIndex(headId)) .isEqualTo(tail.subList(0, 6)); From 8829c1170a0d78e6a0135fccacbabeff3fbcf9af Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 27 Apr 2023 19:02:58 +0200 Subject: [PATCH 14/26] Use two lists --- .../storage/versionstore/ContentMapping.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index 81d16c5aa1e..0b599f9434e 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -24,8 +24,9 @@ import static org.projectnessie.versioned.storage.versionstore.TypeMapping.storeKeyToKey; import static org.projectnessie.versioned.storage.versionstore.TypeMapping.toCommitMeta; +import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import org.projectnessie.model.CommitMeta; @@ -133,7 +134,8 @@ public Commit commitObjToCommit( if (fetchAdditionalInfo) { IndexesLogic indexesLogic = indexesLogic(persist); - Map idsToKeys = new LinkedHashMap<>(); + List ids = new ArrayList<>(); + List keys = new ArrayList<>(); for (StoreIndexElement op : indexesLogic.commitOperations(commitObj)) { ContentKey key = storeKeyToKey(op.key()); // Note: key==null, if not the "main universe" or not a "content" discriminator @@ -141,19 +143,20 @@ public Commit commitObjToCommit( CommitOp c = op.content(); if (c.action().exists()) { ObjId objId = requireNonNull(c.value(), "Required value pointer is null"); - idsToKeys.put(objId, key); + ids.add(objId); + keys.add(key); } else { commit.addOperations(Delete.of(key)); } } } - if (!idsToKeys.isEmpty()) { - ObjId[] ids = idsToKeys.keySet().toArray(new ObjId[0]); - Obj[] objs = persist.fetchObjs(ids); - for (Obj obj : objs) { + if (!ids.isEmpty()) { + Obj[] objs = persist.fetchObjs(ids.toArray(new ObjId[0])); + for (int i = 0; i < objs.length; i++) { + Obj obj = objs[i]; + ContentKey key = keys.get(i); assert obj instanceof ContentValueObj; ContentValueObj contentValue = (ContentValueObj) obj; - ContentKey key = idsToKeys.get(obj.id()); commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); } } From 5abb22b93f2273d3686f42df7d6aca84bb5a0dec Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Thu, 27 Apr 2023 19:06:22 +0200 Subject: [PATCH 15/26] Rename factory method --- .../versioned/persist/store/PersistVersionStore.java | 2 +- .../spi/src/main/java/org/projectnessie/versioned/Put.java | 6 +++--- .../versioned/storage/versionstore/ContentMapping.java | 2 +- .../versioned/storage/versionstore/TestContentMapping.java | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java index 91492e95b0f..55022d5ddf0 100644 --- a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java +++ b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java @@ -514,7 +514,7 @@ private BiConsumer enhancerForCommitLog .forEach( put -> commitBuilder.addOperations( - Put.of( + Put.ofLazy( put.getKey(), put.getPayload(), put.getValue(), diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java index 7ae99b5cfe2..f4825f70fb1 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/Put.java @@ -69,8 +69,8 @@ public static Put of( /** Creates a lazily-evaluated put-operation for the given key, payload and ByteString value. */ @Nonnull @jakarta.annotation.Nonnull - public static Put of(ContentKey key, int payload, ByteString value) { - return of(key, payload, value, () -> null); + public static Put ofLazy(ContentKey key, int payload, ByteString value) { + return ofLazy(key, payload, value, () -> null); } /** @@ -80,7 +80,7 @@ public static Put of(ContentKey key, int payload, ByteString value) { @SuppressWarnings("deprecation") @Nonnull @jakarta.annotation.Nonnull - public static Put of( + public static Put ofLazy( ContentKey key, int payload, ByteString value, Supplier globalStateSupplier) { return ImmutablePut.builder() .key(key) diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java index 0b599f9434e..1a8a0719dd5 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/ContentMapping.java @@ -157,7 +157,7 @@ public Commit commitObjToCommit( ContentKey key = keys.get(i); assert obj instanceof ContentValueObj; ContentValueObj contentValue = (ContentValueObj) obj; - commit.addOperations(Put.of(key, contentValue.payload(), contentValue.data())); + commit.addOperations(Put.ofLazy(key, contentValue.payload(), contentValue.data())); } } } diff --git a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java index 3560d0881bd..acfe35e95af 100644 --- a/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java +++ b/versioned/storage/store/src/test/java/org/projectnessie/versioned/storage/versionstore/TestContentMapping.java @@ -228,7 +228,7 @@ public void commitsWithAdditionalInfo() throws Exception { .commitMeta(referenceCommitMeta) .addOperations( Delete.of(ContentKey.of("bar")), - Put.of(ContentKey.of("foo"), tableObj.payload(), tableObj.data())) + Put.ofLazy(ContentKey.of("foo"), tableObj.payload(), tableObj.data())) .build(); Commit c = contentMapping.commitObjToCommit(true, commitObj); From aec5a3f84db73a6c9c713cc0d2f305db95a33ee9 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 28 Apr 2023 11:02:51 +0200 Subject: [PATCH 16/26] Remove AtomicReference result holders --- .../persist/adapter/spi/TryLoopState.java | 21 +- .../persist/adapter/spi/TestTryLoopState.java | 25 +- .../NonTransactionalDatabaseAdapter.java | 323 ++++++++---------- .../persist/tx/TxDatabaseAdapter.java | 311 ++++++++--------- 4 files changed, 302 insertions(+), 378 deletions(-) diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TryLoopState.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TryLoopState.java index dd43d47fb74..5a3f2d1fc59 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TryLoopState.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/TryLoopState.java @@ -21,12 +21,11 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Function; -import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ReferenceRetryFailureException; import org.projectnessie.versioned.persist.adapter.DatabaseAdapterConfig; /** Retry-logic for attempts for compare-and-swap-like operations. */ -public class TryLoopState implements AutoCloseable { +public class TryLoopState implements AutoCloseable { private static final String TAG_ATTEMPT = "try-loop.attempt"; private static final String TAG_RETRIES = "try-loop.retries"; @@ -38,8 +37,8 @@ public class TryLoopState implements AutoCloseable { private final long t0; private final long maxTime; private final int maxRetries; - private final Function retryErrorMessage; - private final BiConsumer completionNotifier; + private final Function, String> retryErrorMessage; + private final BiConsumer> completionNotifier; private final long maxSleep; private final long initialLowerBound; private final long initialUpperBound; @@ -51,10 +50,10 @@ public class TryLoopState implements AutoCloseable { TryLoopState( String opName, - Function retryErrorMessage, + Function, String> retryErrorMessage, DatabaseAdapterConfig config, MonotonicClock monotonicClock, - BiConsumer completionNotifier) { + BiConsumer> completionNotifier) { this.opName = opName; this.retryErrorMessage = retryErrorMessage; this.maxTime = TimeUnit.MILLISECONDS.toNanos(config.getCommitTimeout()); @@ -68,12 +67,12 @@ public class TryLoopState implements AutoCloseable { start(); } - public static TryLoopState newTryLoopState( + public static TryLoopState newTryLoopState( String opName, - Function retryErrorMessage, - BiConsumer completionNotifier, + Function, String> retryErrorMessage, + BiConsumer> completionNotifier, DatabaseAdapterConfig config) { - return new TryLoopState( + return new TryLoopState<>( "try-loop." + opName, retryErrorMessage, config, @@ -101,7 +100,7 @@ public long getDuration(TimeUnit timeUnit) { * Called when the operation succeeded. The current implementation is rather a no-op, but can be * used to track/trace/monitor successes. */ - public Hash success(Hash result) { + public R success(R result) { completionNotifier.accept(true, this); return result; } diff --git a/versioned/persist/adapter/src/test/java/org/projectnessie/versioned/persist/adapter/spi/TestTryLoopState.java b/versioned/persist/adapter/src/test/java/org/projectnessie/versioned/persist/adapter/spi/TestTryLoopState.java index 548b5ff0777..c9bd7ce522c 100644 --- a/versioned/persist/adapter/src/test/java/org/projectnessie/versioned/persist/adapter/spi/TestTryLoopState.java +++ b/versioned/persist/adapter/src/test/java/org/projectnessie/versioned/persist/adapter/spi/TestTryLoopState.java @@ -34,6 +34,7 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; +import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ReferenceRetryFailureException; import org.projectnessie.versioned.persist.adapter.DatabaseAdapterConfig; import org.projectnessie.versioned.persist.adapter.spi.TryLoopState.MonotonicClock; @@ -53,8 +54,8 @@ void doesNotSleepLongerThanMax(long maxSleep) throws Exception { long lower = initialLower; long upper = initialUpper; - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries, Long.MAX_VALUE, 1, upper, maxSleep), @@ -130,8 +131,8 @@ void retriesWithinBounds(int retries) throws Exception { Arrays.fill(times, 0L); MonotonicClock clock = mockedClock(0L, times); - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries, 42L), @@ -156,8 +157,8 @@ void retryUnsuccessful() throws Exception { Arrays.fill(times, 0L); MonotonicClock clock = mockedClock(0L, times); - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries, 42L), @@ -188,8 +189,8 @@ void retriesOutOfBounds(int retries) throws Exception { Arrays.fill(times, 0L); MonotonicClock clock = mockedClock(0L, times); - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries - 1, 42L), @@ -221,8 +222,8 @@ void sleepDurations() throws Exception { // Must be "big" enough so that the upper/lower sleep-time-bounds doubling exceed this value long timeoutMillis = 42L; - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries, timeoutMillis), @@ -273,8 +274,8 @@ void retriesOutOfTime(int retries) throws Exception { times[retries - 1] = TimeUnit.MILLISECONDS.toNanos(43L); MonotonicClock clock = mockedClock(0L, times); - TryLoopState tryLoopState = - new TryLoopState( + TryLoopState tryLoopState = + new TryLoopState<>( "test", this::retryErrorMessage, mockedConfig(retries, 42L), diff --git a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java index 7f4ac145447..463afcc4933 100644 --- a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java +++ b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java @@ -50,7 +50,6 @@ import java.util.Spliterators; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.IntFunction; @@ -230,58 +229,51 @@ public MergeResult merge(MergeParams mergeParams) // Note: "beginning-of-time" (aka creating a branch without specifying a "create-from") // creates a new commit-tree that is decoupled from other commit-trees. try { - AtomicReference> mergeResultHolder = - new AtomicReference<>(); - - Hash result = - casOpLoop( - "merge", - mergeParams.getToBranch(), - CasOpVariant.COMMIT, - (ctx, refHead, branchCommits, newKeyLists) -> { - ImmutableMergeResult.Builder mergeResult = - MergeResult.builder() - .resultType(ResultType.MERGE) - .sourceRef(mergeParams.getFromRef()); - mergeResultHolder.set(mergeResult); - - Hash currentHead = Hash.of(refHead.getHash()); - - long timeInMicros = config.currentTimeInMicros(); - - List writtenCommits = new ArrayList<>(); - Hash newHead = - mergeAttempt( - ctx, - timeInMicros, - currentHead, - branchCommits, - newKeyLists, - writtenCommits::add, - mergeResult::addAddedCommits, - mergeParams, - mergeResult); - - return casOpResult( - refHead, - newHead, - null, - () -> - MergeEvent.builder() - .previousHash(currentHead) - .hash(newHead) - .branch(mergeParams.getToBranch()) - .commits(writtenCommits)); - }, - () -> mergeConflictMessage("Retry-failure", mergeParams)); - - ImmutableMergeResult.Builder mergeResult = - Objects.requireNonNull( - mergeResultHolder.get(), "Internal error, merge-result builder not set."); - if (!mergeParams.isDryRun()) { - mergeResult.wasApplied(true); - } - return mergeResult.resultantTargetHash(result).build(); + return casOpLoop( + "merge", + mergeParams.getToBranch(), + CasOpVariant.MERGE, + (ctx, refHead, branchCommits, newKeyLists) -> { + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceRef(mergeParams.getFromRef()); + + Hash currentHead = Hash.of(refHead.getHash()); + + long timeInMicros = config.currentTimeInMicros(); + + List writtenCommits = new ArrayList<>(); + Hash newHead = + mergeAttempt( + ctx, + timeInMicros, + currentHead, + branchCommits, + newKeyLists, + writtenCommits::add, + mergeResult::addAddedCommits, + mergeParams, + mergeResult); + + if (!mergeParams.isDryRun()) { + mergeResult.wasApplied(true); + } + mergeResult.resultantTargetHash(newHead); + + return casOpResult( + refHead, + mergeResult.build(), + null, + () -> + MergeEvent.builder() + .previousHash(currentHead) + .hash(newHead) + .branch(mergeParams.getToBranch()) + .commits(writtenCommits)); + }, + () -> mergeConflictMessage("Retry-failure", mergeParams)); + } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -294,58 +286,51 @@ public MergeResult merge(MergeParams mergeParams) public MergeResult transplant(TransplantParams transplantParams) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference> mergeResultHolder = - new AtomicReference<>(); - - Hash result = - casOpLoop( - "transplant", - transplantParams.getToBranch(), - CasOpVariant.COMMIT, - (ctx, refHead, branchCommits, newKeyLists) -> { - ImmutableMergeResult.Builder mergeResult = - MergeResult.builder() - .resultType(ResultType.TRANSPLANT) - .sourceRef(transplantParams.getFromRef()); - mergeResultHolder.set(mergeResult); - - Hash currentHead = Hash.of(refHead.getHash()); - - long timeInMicros = config.currentTimeInMicros(); - - List writtenCommits = new ArrayList<>(); - Hash newHead = - transplantAttempt( - ctx, - timeInMicros, - currentHead, - branchCommits, - newKeyLists, - writtenCommits::add, - mergeResult::addAddedCommits, - transplantParams, - mergeResult); - - return casOpResult( - refHead, - newHead, - null, - () -> - TransplantEvent.builder() - .previousHash(currentHead) - .hash(newHead) - .branch(transplantParams.getToBranch()) - .commits(writtenCommits)); - }, - () -> transplantConflictMessage("Retry-failure", transplantParams)); - - ImmutableMergeResult.Builder mergeResult = - Objects.requireNonNull( - mergeResultHolder.get(), "Internal error, merge-result builder not set."); - if (!transplantParams.isDryRun()) { - mergeResult.wasApplied(true); - } - return mergeResult.resultantTargetHash(result).build(); + return casOpLoop( + "transplant", + transplantParams.getToBranch(), + CasOpVariant.MERGE, + (ctx, refHead, branchCommits, newKeyLists) -> { + ImmutableMergeResult.Builder mergeResult = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceRef(transplantParams.getFromRef()); + + Hash currentHead = Hash.of(refHead.getHash()); + + long timeInMicros = config.currentTimeInMicros(); + + List writtenCommits = new ArrayList<>(); + Hash newHead = + transplantAttempt( + ctx, + timeInMicros, + currentHead, + branchCommits, + newKeyLists, + writtenCommits::add, + mergeResult::addAddedCommits, + transplantParams, + mergeResult); + + if (!transplantParams.isDryRun()) { + mergeResult.wasApplied(true); + } + mergeResult.resultantTargetHash(newHead); + + return casOpResult( + refHead, + mergeResult.build(), + null, + () -> + TransplantEvent.builder() + .previousHash(currentHead) + .hash(newHead) + .branch(transplantParams.getToBranch()) + .commits(writtenCommits)); + }, + () -> transplantConflictMessage("Retry-failure", transplantParams)); + } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -357,11 +342,7 @@ public MergeResult transplant(TransplantParams transplantParams) public CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException { try { - - AtomicReference> commitResultHolder = - new AtomicReference<>(); - - casOpLoop( + return casOpLoop( "commit", commitParams.getToBranch(), CasOpVariant.COMMIT, @@ -379,11 +360,10 @@ public CommitResult commit(CommitParams commitParams) branchCommits.accept(newHead); commitResult.targetBranch(commitParams.getToBranch()).commit(newBranchCommit); - commitResultHolder.set(commitResult); return casOpResult( refHead, - newHead, + commitResult.build(), null, () -> CommitEvent.builder() @@ -395,12 +375,6 @@ public CommitResult commit(CommitParams commitParams) () -> commitConflictMessage( "Retry-Failure", commitParams.getToBranch(), commitParams.getExpectedHead())); - - ImmutableCommitResult.Builder commitResult = - Objects.requireNonNull( - commitResultHolder.get(), "Internal error, commit-result builder not set."); - - return commitResult.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -412,17 +386,13 @@ public CommitResult commit(CommitParams commitParams) public ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - casOpLoop( + return casOpLoop( "createRef", ref, CasOpVariant.CREATE_REF, (ctx, refHead, branchCommits, newKeyLists) -> { ImmutableReferenceCreatedResult.Builder result = ImmutableReferenceCreatedResult.builder().namedRef(ref); - resultHolder.set(result); if (refHead != null) { throw referenceAlreadyExists(ref); @@ -442,8 +412,8 @@ public ReferenceCreatedResult create(NamedRef ref, Hash target) result.hash(newHead); return casOpResult( - refHead, - hash, + null, + result.build(), refLog -> refLog .setRefName(ByteString.copyFromUtf8(ref.getName())) @@ -454,12 +424,6 @@ public ReferenceCreatedResult create(NamedRef ref, Hash target) () -> ReferenceCreatedEvent.builder().currentHash(newHead).ref(ref)); }, () -> createConflictMessage("Retry-Failure", ref, target)); - - ImmutableReferenceCreatedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceAlreadyExistsException | ReferenceNotFoundException | RuntimeException e) { throw e; } catch (Exception e) { @@ -471,17 +435,13 @@ public ReferenceCreatedResult create(NamedRef ref, Hash target) public ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - casOpLoop( + return casOpLoop( "deleteRef", reference, CasOpVariant.DELETE_REF, (ctx, refHead, branchCommits, newKeyLists) -> { ImmutableReferenceDeletedResult.Builder result = ImmutableReferenceDeletedResult.builder().namedRef(reference); - resultHolder.set(result); Hash currentHead = Hash.of(refHead.getHash()); verifyExpectedHash(currentHead, reference, expectedHead); @@ -490,7 +450,7 @@ public ReferenceDeletedResult delete(NamedRef reference, Optional expected return casOpResult( refHead, - currentHead, + result.build(), refLog -> refLog .setRefName(ByteString.copyFromUtf8(reference.getName())) @@ -501,12 +461,6 @@ public ReferenceDeletedResult delete(NamedRef reference, Optional expected () -> ReferenceDeletedEvent.builder().currentHash(currentHead).ref(reference)); }, () -> deleteConflictMessage("Retry-Failure", reference, expectedHead)); - - ImmutableReferenceDeletedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -519,17 +473,13 @@ public ReferenceAssignedResult assign( NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - casOpLoop( + return casOpLoop( "assignRef", assignee, CasOpVariant.REF_UPDATE, (ctx, refHead, branchCommits, newKeyLists) -> { ImmutableReferenceAssignedResult.Builder result = ImmutableReferenceAssignedResult.builder().namedRef(assignee); - resultHolder.set(result); Hash beforeAssign = Hash.of(refHead.getHash()); verifyExpectedHash(beforeAssign, assignee, expectedHead); @@ -540,7 +490,7 @@ public ReferenceAssignedResult assign( return casOpResult( refHead, - assignTo, + result.build(), refLog -> refLog .setRefName(ByteString.copyFromUtf8(assignee.getName())) @@ -556,12 +506,6 @@ public ReferenceAssignedResult assign( .previousHash(beforeAssign)); }, () -> assignConflictMessage("Retry-Failure", assignee, expectedHead, assignTo)); - - ImmutableReferenceAssignedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -663,7 +607,7 @@ public void updateRepositoryDescription(Function tryState = newTryLoopState( "updateRepositoryDescription", ts -> @@ -793,7 +737,7 @@ protected Hash hashOnRef( * from the return value. */ @FunctionalInterface - public interface CasOp { + public interface CasOp { /** * Applies an operation within a CAS-loop. The implementation gets the current ref-pointer and * must return a {@link CasOpResult} with the reference's new HEAD and function to configure the @@ -808,7 +752,7 @@ public interface CasOp { * @return "new value" that {@link #casOpLoop(String, NamedRef, CasOpVariant, CasOp, Supplier)} * tries to apply */ - CasOpResult apply( + CasOpResult apply( NonTransactionalOperationContext ctx, RefPointer refPointer, Consumer branchCommits, @@ -816,35 +760,37 @@ CasOpResult apply( throws VersionStoreException; } - protected static final class CasOpResult { + protected static final class CasOpResult { final RefPointer currentHead; - final Hash newHead; + final R result; final Consumer refLogEntry; final Supplier> adapterEventBuilder; private CasOpResult( RefPointer currentHead, - Hash newHead, + R result, Consumer refLogEntry, Supplier> adapterEventBuilder) { this.currentHead = currentHead; - this.newHead = newHead; + this.result = result; this.refLogEntry = refLogEntry; this.adapterEventBuilder = adapterEventBuilder; } - public static CasOpResult casOpResult( + public static CasOpResult casOpResult( RefPointer currentHead, - Hash newHead, + R result, Consumer refLogEntry, Supplier> adapterEventBuilder) { - return new CasOpResult(currentHead, newHead, refLogEntry, adapterEventBuilder); + return new CasOpResult<>(currentHead, result, refLogEntry, adapterEventBuilder); } } enum CasOpVariant { - /** For commit/merge/transplant, which add one or more commits to that named reference. */ + /** For commits, which add one commit to that named reference. */ COMMIT(), + /** For merge/transplant, which add one or more commits to that named reference. */ + MERGE(), /** * For {@link #assign(NamedRef, Optional, Hash)}, which only update the updates the HEAD of a * named reference, but does not add a commit. @@ -866,16 +812,16 @@ enum CasOpVariant { * @param retryErrorMessage provides an error-message for a {@link ReferenceConflictException} * when the CAS operation failed to complete within the configured time and number of retries. */ - protected Hash casOpLoop( + protected R casOpLoop( String opName, NamedRef ref, CasOpVariant opVariant, - CasOp casOp, + CasOp casOp, Supplier retryErrorMessage) throws VersionStoreException { NonTransactionalOperationContext ctx = NON_TRANSACTIONAL_OPERATION_CONTEXT; - try (TryLoopState tryState = + try (TryLoopState tryState = newTryLoopState( opName, ts -> @@ -896,7 +842,7 @@ protected Hash casOpLoop( // For all operations, except createReference, verify that the reference exists. throw referenceNotFound(ref); } - CasOpResult result = + CasOpResult result = casOp.apply( ctx, refHead != null ? refHead.getRef() : null, @@ -906,25 +852,48 @@ protected Hash casOpLoop( boolean casSuccess; switch (opVariant) { case CREATE_REF: - casSuccess = createNamedReference(ctx, ref, result.newHead); + ReferenceCreatedResult refCreatedResult = ((ReferenceCreatedResult) result.result); + casSuccess = createNamedReference(ctx, ref, refCreatedResult.getHash()); break; case DELETE_REF: casSuccess = deleteNamedReference(ctx, ref, refHead.getRef()); break; case REF_UPDATE: + ReferenceAssignedResult refAssignedResult = (ReferenceAssignedResult) result.result; + if (refHead.getRef().getHash().equals(refAssignedResult.getCurrentHash().asBytes())) { + // Target branch HEAD did not change + return tryState.success(result.result); + } + casSuccess = + updateNamedReference( + ctx, ref, refHead.getRef(), refAssignedResult.getCurrentHash()); + break; case COMMIT: - if (refHead.getRef().getHash().equals(result.newHead.asBytes())) { + CommitResult commitResult = (CommitResult) result.result; + if (refHead.getRef().getHash().equals(commitResult.getCommitHash().asBytes())) { + // Target branch HEAD did not change + return tryState.success(result.result); + } + casSuccess = + updateNamedReference(ctx, ref, refHead.getRef(), commitResult.getCommitHash()); + break; + case MERGE: + MergeResult mergeResult = ((MergeResult) result.result); + Hash newHash = Objects.requireNonNull(mergeResult.getResultantTargetHash()); + if (refHead.getRef().getHash().equals(newHash.asBytes())) { // Target branch HEAD did not change - return tryState.success(result.newHead); + return tryState.success(result.result); } - casSuccess = updateNamedReference(ctx, ref, refHead.getRef(), result.newHead); + casSuccess = + updateNamedReference( + ctx, ref, refHead.getRef(), mergeResult.getResultantTargetHash()); break; default: throw new UnsupportedOperationException("Unknown opVariant " + opVariant); } if (!casSuccess) { - if (opVariant == CasOpVariant.COMMIT) { + if (opVariant == CasOpVariant.COMMIT || opVariant == CasOpVariant.MERGE) { cleanUpCommitCas(ctx, individualCommits, individualKeyLists); } @@ -937,7 +906,7 @@ protected Hash casOpLoop( if (result.refLogEntry == null) { // No ref-log entry to be written - return tryState.success(result.newHead); + return tryState.success(result.result); } else { // CAS against branch-heads succeeded, now try to write the ref-log-entry @@ -958,7 +927,7 @@ protected Hash casOpLoop( .forEach(newRefLogParents::addRefLogParentsInclHead); if (refLogParentsCas(ctx, stripe, refLogParents, newRefLogParents.build())) { - return tryState.success(result.newHead); + return tryState.success(result.result); } cleanUpRefLogWrite(ctx, Hash.of(newRefLog.getRefLogId())); diff --git a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java index 87b9285773c..7d53f871a75 100644 --- a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java +++ b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java @@ -56,7 +56,6 @@ import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -234,63 +233,56 @@ public MergeResult merge(MergeParams mergeParams) // Note: "beginning-of-time" (aka creating a branch without specifying a "create-from") // creates a new commit-tree that is decoupled from other commit-trees. try { - AtomicReference> mergeResultHolder = - new AtomicReference<>(); - - Hash result = - opLoop( - "merge", - mergeParams.getToBranch(), - false, - (conn, currentHead) -> { - long timeInMicros = config.currentTimeInMicros(); - - ImmutableMergeResult.Builder mergeResult = - MergeResult.builder() - .resultType(ResultType.MERGE) - .sourceRef(mergeParams.getFromRef()); - mergeResultHolder.set(mergeResult); - - List writtenCommits = new ArrayList<>(); - Hash toHead = - mergeAttempt( - conn, - timeInMicros, - currentHead, - h -> {}, - h -> {}, - writtenCommits::add, - mergeResult::addAddedCommits, - mergeParams, - mergeResult); - - if (toHead.equals(currentHead)) { - // nothing done - return opResult(currentHead, null); - } + return opLoop( + "merge", + mergeParams.getToBranch(), + false, + (conn, currentHead) -> { + long timeInMicros = config.currentTimeInMicros(); + + ImmutableMergeResult.Builder result = + MergeResult.builder() + .resultType(ResultType.MERGE) + .sourceRef(mergeParams.getFromRef()); + + List writtenCommits = new ArrayList<>(); + Hash toHead = + mergeAttempt( + conn, + timeInMicros, + currentHead, + h -> {}, + h -> {}, + writtenCommits::add, + result::addAddedCommits, + mergeParams, + result); + + Hash resultHash = + toHead.equals(currentHead) + ? currentHead // nothing done + : tryMoveNamedReference(conn, mergeParams.getToBranch(), currentHead, toHead); + if (resultHash == null) { + return opResult(null, null); + } + result.resultantTargetHash(resultHash); + + if (!mergeParams.isDryRun()) { + result.wasApplied(true); + } + + return opResult( + result.build(), + () -> + MergeEvent.builder() + .previousHash(currentHead) + .hash(resultHash) + .branch(mergeParams.getToBranch()) + .commits(writtenCommits)); + }, + () -> mergeConflictMessage("Conflict", mergeParams), + () -> mergeConflictMessage("Retry-failure", mergeParams)); - Hash resultHash = - tryMoveNamedReference(conn, mergeParams.getToBranch(), currentHead, toHead); - - return opResult( - resultHash, - () -> - MergeEvent.builder() - .previousHash(currentHead) - .hash(resultHash) - .branch(mergeParams.getToBranch()) - .commits(writtenCommits)); - }, - () -> mergeConflictMessage("Conflict", mergeParams), - () -> mergeConflictMessage("Retry-failure", mergeParams)); - - ImmutableMergeResult.Builder mergeResult = - Objects.requireNonNull( - mergeResultHolder.get(), "Internal error, merge-result builder not set."); - if (!mergeParams.isDryRun()) { - mergeResult.wasApplied(true); - } - return mergeResult.resultantTargetHash(result).build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -303,60 +295,55 @@ public MergeResult merge(MergeParams mergeParams) public MergeResult transplant(TransplantParams transplantParams) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference> mergeResultHolder = - new AtomicReference<>(); - - Hash result = - opLoop( - "transplant", - transplantParams.getToBranch(), - false, - (conn, currentHead) -> { - long timeInMicros = config.currentTimeInMicros(); - - ImmutableMergeResult.Builder mergeResult = - MergeResult.builder() - .resultType(ResultType.TRANSPLANT) - .sourceRef(transplantParams.getFromRef()); - - mergeResultHolder.set(mergeResult); - - List writtenCommits = new ArrayList<>(); - Hash targetHead = - transplantAttempt( - conn, - timeInMicros, - currentHead, - h -> {}, - h -> {}, - writtenCommits::add, - mergeResult::addAddedCommits, - transplantParams, - mergeResult); - - Hash resultHash = - tryMoveNamedReference( - conn, transplantParams.getToBranch(), currentHead, targetHead); - - return opResult( - resultHash, - () -> - TransplantEvent.builder() - .previousHash(currentHead) - .hash(resultHash) - .branch(transplantParams.getToBranch()) - .commits(writtenCommits)); - }, - () -> transplantConflictMessage("Conflict", transplantParams), - () -> transplantConflictMessage("Retry-failure", transplantParams)); - - ImmutableMergeResult.Builder mergeResult = - Objects.requireNonNull( - mergeResultHolder.get(), "Internal error, merge-result builder not set."); - if (!transplantParams.isDryRun()) { - mergeResult.wasApplied(true); - } - return mergeResult.resultantTargetHash(result).build(); + return opLoop( + "transplant", + transplantParams.getToBranch(), + false, + (conn, currentHead) -> { + long timeInMicros = config.currentTimeInMicros(); + + ImmutableMergeResult.Builder result = + MergeResult.builder() + .resultType(ResultType.TRANSPLANT) + .sourceRef(transplantParams.getFromRef()); + + List writtenCommits = new ArrayList<>(); + Hash targetHead = + transplantAttempt( + conn, + timeInMicros, + currentHead, + h -> {}, + h -> {}, + writtenCommits::add, + result::addAddedCommits, + transplantParams, + result); + + Hash resultHash = + tryMoveNamedReference( + conn, transplantParams.getToBranch(), currentHead, targetHead); + if (resultHash == null) { + return opResult(null, null); + } + result.resultantTargetHash(resultHash); + + if (!transplantParams.isDryRun()) { + result.wasApplied(true); + } + + return opResult( + result.build(), + () -> + TransplantEvent.builder() + .previousHash(currentHead) + .hash(resultHash) + .branch(transplantParams.getToBranch()) + .commits(writtenCommits)); + }, + () -> transplantConflictMessage("Conflict", transplantParams), + () -> transplantConflictMessage("Retry-failure", transplantParams)); + } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -368,17 +355,14 @@ public MergeResult transplant(TransplantParams transplantParams) public CommitResult commit(CommitParams commitParams) throws ReferenceConflictException, ReferenceNotFoundException { try { - AtomicReference> commitResultHolder = - new AtomicReference<>(); - - opLoop( + return opLoop( "commit", commitParams.getToBranch(), false, (conn, branchHead) -> { long timeInMicros = config.currentTimeInMicros(); - ImmutableCommitResult.Builder commitResult = CommitResult.builder(); + ImmutableCommitResult.Builder result = CommitResult.builder(); CommitLogEntry newBranchCommit = commitAttempt(conn, timeInMicros, branchHead, commitParams, h -> {}); @@ -387,11 +371,14 @@ public CommitResult commit(CommitParams commitParams) tryMoveNamedReference( conn, commitParams.getToBranch(), branchHead, newBranchCommit.getHash()); - commitResult.commit(newBranchCommit).targetBranch(commitParams.getToBranch()); - commitResultHolder.set(commitResult); + if (resultHash == null) { + return opResult(null, null); + } + + result.commit(newBranchCommit).targetBranch(commitParams.getToBranch()); return opResult( - resultHash, + result.build(), () -> CommitEvent.builder() .previousHash(branchHead) @@ -405,12 +392,6 @@ public CommitResult commit(CommitParams commitParams) () -> commitConflictMessage( "Retry-Failure", commitParams.getToBranch(), commitParams.getExpectedHead())); - - ImmutableCommitResult.Builder commitResult = - Objects.requireNonNull( - commitResultHolder.get(), "Internal error, commit-result builder not set."); - - return commitResult.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -423,17 +404,13 @@ public CommitResult commit(CommitParams commitParams) public ReferenceCreatedResult create(NamedRef ref, Hash target) throws ReferenceAlreadyExistsException, ReferenceNotFoundException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - opLoop( + return opLoop( "createRef", ref, true, (conn, nullHead) -> { ImmutableReferenceCreatedResult.Builder result = ImmutableReferenceCreatedResult.builder().namedRef(ref); - resultHolder.set(result); if (checkNamedRefExistence(conn, ref.getName())) { throw referenceAlreadyExists(ref); @@ -460,16 +437,11 @@ public ReferenceCreatedResult create(NamedRef ref, Hash target) result.hash(hash); - return opResult(hash, () -> ReferenceCreatedEvent.builder().currentHash(hash).ref(ref)); + return opResult( + result.build(), () -> ReferenceCreatedEvent.builder().currentHash(hash).ref(ref)); }, () -> createConflictMessage("Conflict", ref, target), () -> createConflictMessage("Retry-Failure", ref, target)); - - ImmutableReferenceCreatedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceAlreadyExistsException | ReferenceNotFoundException | RuntimeException e) { throw e; } catch (Exception e) { @@ -481,17 +453,13 @@ public ReferenceCreatedResult create(NamedRef ref, Hash target) public ReferenceDeletedResult delete(NamedRef reference, Optional expectedHead) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - opLoop( + return opLoop( "deleteRef", reference, false, (conn, pointer) -> { ImmutableReferenceDeletedResult.Builder result = ImmutableReferenceDeletedResult.builder().namedRef(reference); - resultHolder.set(result); verifyExpectedHash(pointer, reference, expectedHead); @@ -503,7 +471,7 @@ public ReferenceDeletedResult delete(NamedRef reference, Optional expected ps.setString(2, reference.getName()); ps.setString(3, pointer.asString()); if (ps.executeUpdate() != 1) { - return null; + return opResult(null, null); } } @@ -518,17 +486,11 @@ public ReferenceDeletedResult delete(NamedRef reference, Optional expected result.hash(commitHash); return opResult( - pointer, + result.build(), () -> ReferenceDeletedEvent.builder().currentHash(commitHash).ref(reference)); }, () -> deleteConflictMessage("Conflict", reference, expectedHead), () -> deleteConflictMessage("Retry-Failure", reference, expectedHead)); - - ImmutableReferenceDeletedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -541,23 +503,22 @@ public ReferenceAssignedResult assign( NamedRef assignee, Optional expectedHead, Hash assignTo) throws ReferenceNotFoundException, ReferenceConflictException { try { - AtomicReference resultHolder = - new AtomicReference<>(); - - opLoop( + return opLoop( "assignRef", assignee, false, (conn, assigneeHead) -> { ImmutableReferenceAssignedResult.Builder result = ImmutableReferenceAssignedResult.builder().namedRef(assignee); - resultHolder.set(result); verifyExpectedHash(assigneeHead, assignee, expectedHead); validateHashExists(conn, assignTo); Hash resultHash = tryMoveNamedReference(conn, assignee, assigneeHead, assignTo); + if (resultHash == null) { + return opResult(null, null); + } commitRefLog( conn, @@ -570,7 +531,7 @@ public ReferenceAssignedResult assign( result.previousHash(assigneeHead).currentHash(assignTo); return opResult( - resultHash, + result.build(), () -> ReferenceAssignedEvent.builder() .currentHash(assignTo) @@ -580,11 +541,6 @@ public ReferenceAssignedResult assign( () -> assignConflictMessage("Conflict", assignee, expectedHead, assignTo), () -> assignConflictMessage("Retry-Failure", assignee, expectedHead, assignTo)); - ImmutableReferenceAssignedResult.Builder result = - Objects.requireNonNull( - resultHolder.get(), "Internal error, reference-result builder not set."); - - return result.build(); } catch (ReferenceNotFoundException | ReferenceConflictException | RuntimeException e) { throw e; } catch (Exception e) { @@ -789,7 +745,7 @@ protected Connection newConnection() { } @FunctionalInterface - public interface LoopOp { + public interface LoopOp { /** * Applies an operation within a CAS-loop. The implementation gets the current global-state and * must return an updated global-state with a different global-id. @@ -807,23 +763,22 @@ public interface LoopOp { * @throws VersionStoreException any other version-store exception * @see #opLoop(String, NamedRef, boolean, LoopOp, Supplier, Supplier) */ - OpResult apply(ConnectionWrapper conn, Hash targetRefHead) + OpResult apply(ConnectionWrapper conn, Hash targetRefHead) throws VersionStoreException, SQLException; } - static final class OpResult { - final Hash head; + static final class OpResult { + final R result; final Supplier> adapterEventBuilder; - private OpResult( - Hash head, Supplier> adapterEventBuilder) { - this.head = head; + private OpResult(R result, Supplier> adapterEventBuilder) { + this.result = result; this.adapterEventBuilder = adapterEventBuilder; } - public static OpResult opResult( - Hash head, Supplier> adapterEventBuilder) { - return new OpResult(head, adapterEventBuilder); + public static OpResult opResult( + R result, Supplier> adapterEventBuilder) { + return new OpResult<>(result, adapterEventBuilder); } } @@ -856,16 +811,16 @@ public static OpResult opResult( * @param retryErrorMessage message producer to represent that no more retries will happen * @see LoopOp#apply(ConnectionWrapper, Hash) */ - protected Hash opLoop( + protected R opLoop( String opName, NamedRef namedReference, boolean createRef, - LoopOp loopOp, + LoopOp loopOp, Supplier conflictErrorMessage, Supplier retryErrorMessage) throws VersionStoreException { try (ConnectionWrapper conn = borrowConnection(); - TryLoopState tryState = + TryLoopState tryState = newTryLoopState( opName, ts -> @@ -880,14 +835,14 @@ protected Hash opLoop( Hash pointer = createRef ? null : fetchNamedRefHead(conn, namedReference); try { - OpResult opResult = loopOp.apply(conn, pointer); + OpResult opResult = loopOp.apply(conn, pointer); repositoryEvent(opResult.adapterEventBuilder); - // The operation succeeded, if it returns a non-null hash value. - if (opResult.head != null) { + // The operation succeeded, if it returns a non-null result. + if (opResult.result != null) { conn.commit(); - return tryState.success(opResult.head); + return tryState.success(opResult.result); } } catch (RetryTransactionException e) { conn.rollback(); From 9c95068f4f563c09fa5727d4d27412305b4e767c Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Sun, 30 Apr 2023 15:49:07 +0200 Subject: [PATCH 17/26] Format --- .../versioned/TracingVersionStore.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java index 878dcd3e5d6..1f47bde2f67 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/TracingVersionStore.java @@ -122,7 +122,8 @@ public CommitResult commit( return TracingVersionStore ., ReferenceNotFoundException, ReferenceConflictException> callWithTwoExceptions( - tracer,"Commit", + tracer, + "Commit", b -> b.setAttribute(TAG_BRANCH, safeRefName(branch)) .setAttribute(TAG_HASH, safeToString(referenceHash)) @@ -210,10 +211,12 @@ public ReferenceAssignedResult assign(NamedRef ref, Optional expectedHash, return TracingVersionStore . callWithTwoExceptions( - tracer,"Assign", + tracer, + "Assign", b -> b.setAttribute(TAG_REF, safeToString(ref)) - .setAttribute(TracingVersionStore.TAG_EXPECTED_HASH, safeToString(expectedHash)) + .setAttribute( + TracingVersionStore.TAG_EXPECTED_HASH, safeToString(expectedHash)) .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), () -> delegate.assign(ref, expectedHash, targetHash)); } @@ -224,7 +227,8 @@ public ReferenceCreatedResult create(NamedRef ref, Optional targetHash) return TracingVersionStore . callWithTwoExceptions( - tracer,"Create", + tracer, + "Create", b -> b.setAttribute(TAG_REF, safeToString(ref)) .setAttribute(TAG_TARGET_HASH, safeToString(targetHash)), @@ -237,9 +241,11 @@ public ReferenceDeletedResult delete(NamedRef ref, Optional hash) return TracingVersionStore . callWithTwoExceptions( - tracer,"Delete", - b -> b.setAttribute(TAG_REF, safeToString(ref)) - .setAttribute(TAG_HASH, safeToString(hash)), + tracer, + "Delete", + b -> + b.setAttribute(TAG_REF, safeToString(ref)) + .setAttribute(TAG_HASH, safeToString(hash)), () -> delegate.delete(ref, hash)); } From df3350b6a89fe731f310fb344da578bd4b18d64f Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 3 May 2023 15:26:54 +0200 Subject: [PATCH 18/26] Don't feed added commits for fast-forwards --- .../adapter/spi/AbstractDatabaseAdapter.java | 10 ++- .../versionstore/BaseCommitHelper.java | 2 - .../BaseMergeTransplantIndividual.java | 12 +-- .../BaseMergeTransplantSquash.java | 12 +-- .../versioned/tests/AbstractMerge.java | 90 ++----------------- 5 files changed, 20 insertions(+), 106 deletions(-) diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java index 72494936132..f48fa2f25e3 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java @@ -626,10 +626,10 @@ protected Hash mergeTransplantCommon( newKeyLists, params.getUpdateCommitMetadata(), mergePredicate, - additionalParents); + additionalParents, + addedCommits); if (squashed != null) { - addedCommits.accept(squashed); if (!params.isDryRun()) { writtenCommits.accept(squashed); toHead = squashed.getHash(); @@ -2114,7 +2114,8 @@ protected CommitLogEntry squashCommits( Consumer newKeyLists, MetadataRewriter rewriteMetadata, Predicate includeKeyPredicate, - Iterable additionalParents) + Iterable additionalParents, + Consumer addedCommits) throws ReferenceConflictException, ReferenceNotFoundException { List commitMeta = new ArrayList<>(); @@ -2188,6 +2189,7 @@ protected CommitLogEntry squashCommits( } writeIndividualCommit(ctx, squashedCommit); + addedCommits.accept(squashedCommit); return squashedCommit; } @@ -2268,13 +2270,13 @@ protected Hash copyCommits( if (!newEntry.getHash().equals(sourceCommit.getHash())) { commitsChronological.set(i, newEntry); + addedCommits.accept(newEntry); } else { // Newly built CommitLogEntry is equal to the CommitLogEntry to transplant. // This can happen, if the commit to transplant has NO_ANCESTOR as its parent. commitsChronological.remove(i); } - addedCommits.accept(newEntry); targetHead = newEntry.getHash(); } return targetHead; diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java index eafb3a0717e..eed1fd43581 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseCommitHelper.java @@ -539,8 +539,6 @@ ImmutableMergeResult mergeSquashFastForward( result.wasApplied(true).resultantTargetHash(objIdToHash(fromId)); } - result.addAddedCommits(commitObjToCommit(source)); - return result.build(); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java index 24733539782..f825f7c0853 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java @@ -42,7 +42,6 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; -import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.indexes.StoreIndexElement; import org.projectnessie.versioned.storage.common.logic.CommitLogic; @@ -102,18 +101,13 @@ MergeResult individualCommits( empty = false; if (!dryRun) { - commitLogic.storeCommit(newCommit, objsToStore); newHead = newCommit.id(); - try { - // We need to fetch the existing commit in order to return the correct object. - // The existing commit may have a different set of parents than the new commit. - newCommit = commitLogic.fetchCommit(newCommit.id()); - } catch (ObjNotFoundException ignored) { - // cannot happen + boolean committed = commitLogic.storeCommit(newCommit, objsToStore); + if (committed) { + mergeResult.addAddedCommits(commitObjToCommit(newCommit)); } } - mergeResult.addAddedCommits(commitObjToCommit(newCommit)); sourceParentIndex = indexesLogic.buildCompleteIndex(sourceCommit, Optional.empty()); targetParentIndex = indexesLogic.buildCompleteIndex(newCommit, Optional.empty()); } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java index ee1e50e627d..68fbf1ceccf 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java @@ -40,7 +40,6 @@ import org.projectnessie.versioned.MetadataRewriter; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceNotFoundException; -import org.projectnessie.versioned.storage.common.exceptions.ObjNotFoundException; import org.projectnessie.versioned.storage.common.indexes.StoreIndex; import org.projectnessie.versioned.storage.common.indexes.StoreKey; import org.projectnessie.versioned.storage.common.logic.CommitLogic; @@ -105,18 +104,13 @@ MergeResult squash( newHead = headId(); } else { CommitLogic commitLogic = commitLogic(persist); - commitLogic.storeCommit(mergeCommit, objsToStore); newHead = mergeCommit.id(); - try { - // We need to fetch the existing commit in order to return the correct object. - // The existing commit may have a different set of parents than the new commit. - mergeCommit = commitLogic.fetchCommit(mergeCommit.id()); - } catch (ObjNotFoundException ignored) { - // cannot happen + boolean committed = commitLogic.storeCommit(mergeCommit, objsToStore); + if (committed) { + mergeResult.addAddedCommits(commitObjToCommit(mergeCommit)); } } - mergeResult.addAddedCommits(commitObjToCommit(mergeCommit)); return finishMergeTransplant(false, mergeResult, newHead, dryRun, hasConflicts); } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index 9e3e537b8ec..f968e7466c1 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -466,7 +466,7 @@ private void doMergeIntoEmpty( false, false); - checkTargetCommits(individualCommits, initialHash, result); + checkAddedCommits(individualCommits, initialHash, result); soft.assertThat( contentsWithoutId( store() @@ -484,77 +484,10 @@ private void doMergeIntoEmpty( ContentKey.of("t4"), V_4_1)); } - private void checkTargetCommits( + private void checkAddedCommits( boolean individualCommits, Hash targetHead, MergeResult result) { if (individualCommits) { - soft.assertThat(result.getAddedCommits()) - .hasSize(3) - .satisfiesExactly( - c -> { - soft.assertThat(c.getParentHash()).isEqualTo(targetHead); - soft.assertThat(c.getCommitMeta().getMessage()).contains("First Commit"); - soft.assertThat(c.getOperations()) - .hasSize(3) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_1); - }, - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_1); - }, - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_3_1); - }); - }, - c -> { - soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); - soft.assertThat(c.getCommitMeta().getMessage()).contains("Second Commit"); - soft.assertThat(c.getOperations()) - .hasSize(4) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); - }, - o -> - soft.assertThat(o) - .asInstanceOf(type(Delete.class)) - .extracting(Delete::getKey) - .isEqualTo(ContentKey.of("t2")), - o -> - soft.assertThat(o) - .asInstanceOf(type(Delete.class)) - .extracting(Delete::getKey) - .isEqualTo(ContentKey.of("t3")), - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t4")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); - }); - }, - c -> { - soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(1).getHash()); - soft.assertThat(c.getCommitMeta().getMessage()).contains("Third Commit"); - soft.assertThat(c.getOperations()) - .hasSize(1) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); - } - // Unchanged operation not retained - ); - }); + soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward } else { soft.assertThat(result.getAddedCommits()) .singleElement() @@ -673,12 +606,8 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio Put.of(ContentKey.of("t2"), V_2_1), Put.of(ContentKey.of("t3"), V_3_1))))); soft.assertThat(mergeResult.getTargetCommits()).isNull(); - // The branch was fast-forwarded to firstCommit, so the only added commit is firstCommit - // itself - soft.assertThat(mergeResult.getAddedCommits()) - .singleElement() - .extracting("hash") - .isEqualTo(firstCommit); + // The branch was fast-forwarded to firstCommit, so no commits added + soft.assertThat(mergeResult.getAddedCommits()).isEmpty(); soft.assertThat(mergeResult.getDetails()) .containsKeys(ContentKey.of("t1"), ContentKey.of("t2"), ContentKey.of("t3")); soft.assertThat(mergeResult) @@ -747,10 +676,7 @@ protected void mergeIntoEmptyBranch1Commit(boolean individualCommits) // not modifying commit meta, will just "fast forward" soft.assertThat(store().hashOnReference(newBranch, Optional.empty())).isEqualTo(firstCommit); - soft.assertThat(result.getAddedCommits()) - .singleElement() - .extracting(Commit::getParentHash, Commit::getHash) - .containsExactly(initialHash, firstCommit); + soft.assertThat(result.getAddedCommits()).isEmpty(); // no new commits List mergedCommit = commitsList(newBranch, false).subList(0, 1); assertCommitMeta(soft, mergedCommit, commits.subList(2, 3), metadataRewriter); @@ -948,7 +874,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio false, false); soft.assertThat(mergeResult1.getResultantTargetHash()).isEqualTo(etl1.getCommitHash()); - soft.assertThat(mergeResult1.getAddedCommits()).containsExactly(etl1.getCommit()); + soft.assertThat(mergeResult1.getAddedCommits()).isEmpty(); // fast-forward, so nothing added CommitResult etl2 = store() @@ -971,7 +897,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio false, false); soft.assertThat(mergeResult2.getResultantTargetHash()).isEqualTo(etl2.getCommitHash()); - soft.assertThat(mergeResult2.getAddedCommits()).containsExactly(etl2.getCommit()); + soft.assertThat(mergeResult2.getAddedCommits()).isEmpty(); // fast-forward, so nothing added soft.assertThat(contentWithoutId(store().getValue(review, key))).isEqualTo(VALUE_2); } From 61e3632e895de0b2c9ae772e41420b9efa4f1d20 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 3 May 2023 17:09:49 +0200 Subject: [PATCH 19/26] Fix some tests after BatchingPersist --- .../versioned/tests/AbstractMerge.java | 96 ++++++++++++++++-- .../versioned/tests/AbstractTransplant.java | 98 ++++++++++++------- 2 files changed, 154 insertions(+), 40 deletions(-) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index f968e7466c1..b8c4c2991c7 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -422,7 +422,7 @@ protected void mergeIntoEmptyBranch3Commits(boolean individualCommits) MetadataRewriter metadataRewriter = createMetadataRewriter(""); - doMergeIntoEmpty(individualCommits, newBranch, metadataRewriter); + doMergeIntoEmpty(individualCommits, newBranch, metadataRewriter, true); if (individualCommits) { // not modifying commit meta, will just "fast forward" @@ -450,7 +450,8 @@ protected void mergeIntoEmptyBranch3Commits(boolean individualCommits) private void doMergeIntoEmpty( boolean individualCommits, BranchName newBranch, - MetadataRewriter metadataRewriter) + MetadataRewriter metadataRewriter, + boolean expectFastForward) throws ReferenceNotFoundException, ReferenceConflictException { MergeResult result = store() @@ -466,7 +467,8 @@ private void doMergeIntoEmpty( false, false); - checkAddedCommits(individualCommits, initialHash, result); + checkAddedCommits(individualCommits, initialHash, result, expectFastForward); + soft.assertThat( contentsWithoutId( store() @@ -485,9 +487,90 @@ private void doMergeIntoEmpty( } private void checkAddedCommits( - boolean individualCommits, Hash targetHead, MergeResult result) { + boolean individualCommits, + Hash targetHead, + MergeResult result, + boolean expectFastForward) { if (individualCommits) { - soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward + if (expectFastForward) { + // FIXME assertion is failing for new storage model since BatchingPersist introduction + soft.assertThat(result.getAddedCommits()).isEmpty(); + } else { + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .satisfiesExactly( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()).contains("First Commit"); + soft.assertThat(c.getOperations()) + .hasSize(3) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_1_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_2_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_3_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).contains("Second Commit"); + soft.assertThat(c.getOperations()) + .hasSize(4) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t1")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_1_2); + }, + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of("t2")), + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of("t3")), + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t4")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_4_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(1).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).contains("Third Commit"); + soft.assertThat(c.getOperations()) + .hasSize(1) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t2")); + soft.assertThat(contentWithoutId(((Put) o).getValue())) + .isEqualTo(V_2_2); + } + // Unchanged operation not retained + ); + }); + } } else { soft.assertThat(result.getAddedCommits()) .singleElement() @@ -698,7 +781,8 @@ protected void mergeIntoEmptyBranchModifying(boolean individualCommits) MetadataRewriter metadataRewriter = createMetadataRewriter(", merged"); - doMergeIntoEmpty(individualCommits, newBranch, metadataRewriter); + doMergeIntoEmpty( + individualCommits, newBranch, metadataRewriter, false /* because of metadata rewrite */); // modify the commit meta, will generate new commits and therefore new commit hashes soft.assertThat(store().hashOnReference(newBranch, Optional.empty())).isNotEqualTo(thirdCommit); diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index cf363808ebd..edf8bd9752e 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -178,16 +178,51 @@ private BranchName checkTransplantOnEmptyBranch( false, false); - checkAddedCommits(individualCommits, targetHead, result); - if (individualCommits) { - // Since we fast-forwarded the target branch, the transplanted commits and the new target - // commits are identical. + // FIXME assertion is failing for new storage model since BatchingPersist introduction + soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward + } else { soft.assertThat(result.getAddedCommits()) - .hasSize(3) - .extracting(Commit::getHash) - .containsExactly(firstCommit, secondCommit, thirdCommit); + .singleElement() + .satisfies( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()) + .contains("Initial Commit") + .contains("Second Commit") + .contains("Third Commit"); + soft.assertThat(c.getOperations()) + // old storage model keeps the Delete operation when a key is Put then Deleted, + // see https://github.com/projectnessie/nessie/pull/6472 + .hasSizeBetween(3, 4) + .anySatisfy( + o -> { + if (c.getOperations().size() == 4) { + soft.assertThat(o).isInstanceOf(Delete.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + } + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); + }); + }); } + soft.assertThat( contentsWithoutId( store() @@ -212,8 +247,28 @@ private BranchName checkTransplantOnEmptyBranch( return newBranch; } - private void checkAddedCommits( - boolean individualCommits, Hash targetHead, MergeResult result) { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + protected void checkTransplantWithPreviousCommit(boolean individualCommits) + throws VersionStoreException { + final BranchName newBranch = BranchName.of("bar_2"); + store().create(newBranch, Optional.empty()); + Hash targetHead = commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); + + MergeResult result = + store() + .transplant( + sourceBranch, + newBranch, + Optional.of(initialHash), + Arrays.asList(firstCommit, secondCommit, thirdCommit), + createMetadataRewriter(""), + individualCommits, + Collections.emptyMap(), + MergeBehavior.NORMAL, + false, + false); + if (individualCommits) { soft.assertThat(result.getAddedCommits()) .hasSize(3) @@ -324,31 +379,6 @@ private void checkAddedCommits( }); }); } - } - - @ParameterizedTest - @ValueSource(booleans = {false, true}) - protected void checkTransplantWithPreviousCommit(boolean individualCommits) - throws VersionStoreException { - final BranchName newBranch = BranchName.of("bar_2"); - store().create(newBranch, Optional.empty()); - Hash targetHead = commit("Unrelated commit").put(T_5, V_5_1).toBranch(newBranch); - - MergeResult result = - store() - .transplant( - sourceBranch, - newBranch, - Optional.of(initialHash), - Arrays.asList(firstCommit, secondCommit, thirdCommit), - createMetadataRewriter(""), - individualCommits, - Collections.emptyMap(), - MergeBehavior.NORMAL, - false, - false); - - checkAddedCommits(individualCommits, targetHead, result); assertThat( contentsWithoutId( store() From a4bb77d10b51ac841a3bd49f989f6a8e94e170de Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 3 May 2023 20:42:02 +0200 Subject: [PATCH 20/26] Minor javadoc revamp --- .../projectnessie/versioned/MergeResult.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java index b17e5c7162b..fdba7617806 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java @@ -76,17 +76,18 @@ default boolean wasSuccessful() { List getTargetCommits(); /** - * List of commits that where added to the target branch, that is, all the commits between - * {@linkplain #getEffectiveTargetHash() the previous HEAD} (exclusive) and {@linkplain - * #getResultantTargetHash() the current HEAD} (inclusive). + * List of new commits that where added to the target branch. * - *

    The returned list will always be empty if the merge or transplant operation failed. - * Otherwise, if commits were squashed, it will contain exactly one element; otherwise, it will - * generally contain as many commits as there were {@linkplain #getSourceCommits() source commits} - * to rebase (unless some source commits were filtered out). + *

    The returned list will always be empty if the merge or transplant operation failed. It will + * also always be empty in dry-run mode. Furthermore, it will also be empty if the operation + * resulted in a fast-forward merge or transplant, because no new commit is created in this case. + * Otherwise, if commits were squashed, the returned list will contain exactly one element: the + * squashed commit; conversely, if individual commits were preserved, the list will generally + * contain as many commits as there were {@linkplain #getSourceCommits() source commits} to rebase + * (unless some source commits were filtered out). * - *

    This list is currently not exposed via the REST API. It is intended to be used by the Nessie - * events notification system. + *

    The REST API does not expose this property currently; it is used by the Nessie events + * notification system. */ List getAddedCommits(); From cfd47ea77de88625739eec342e5eae30172a4e52 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 3 May 2023 20:44:13 +0200 Subject: [PATCH 21/26] remove FIXMEs --- .../java/org/projectnessie/versioned/tests/AbstractMerge.java | 1 - .../org/projectnessie/versioned/tests/AbstractTransplant.java | 1 - 2 files changed, 2 deletions(-) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index b8c4c2991c7..690e6a28523 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -493,7 +493,6 @@ private void checkAddedCommits( boolean expectFastForward) { if (individualCommits) { if (expectFastForward) { - // FIXME assertion is failing for new storage model since BatchingPersist introduction soft.assertThat(result.getAddedCommits()).isEmpty(); } else { soft.assertThat(result.getAddedCommits()) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index edf8bd9752e..d3993a4d643 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -179,7 +179,6 @@ private BranchName checkTransplantOnEmptyBranch( false); if (individualCommits) { - // FIXME assertion is failing for new storage model since BatchingPersist introduction soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward } else { soft.assertThat(result.getAddedCommits()) From 12300f13df0051030e4641677e309d242edd5f32 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Wed, 3 May 2023 20:53:12 +0200 Subject: [PATCH 22/26] minor refactoring --- .../versioned/tests/AbstractTransplant.java | 262 ++++++++---------- 1 file changed, 116 insertions(+), 146 deletions(-) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index d3993a4d643..ef4afe3fd5b 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -181,45 +181,7 @@ private BranchName checkTransplantOnEmptyBranch( if (individualCommits) { soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward } else { - soft.assertThat(result.getAddedCommits()) - .singleElement() - .satisfies( - c -> { - soft.assertThat(c.getParentHash()).isEqualTo(targetHead); - soft.assertThat(c.getCommitMeta().getMessage()) - .contains("Initial Commit") - .contains("Second Commit") - .contains("Third Commit"); - soft.assertThat(c.getOperations()) - // old storage model keeps the Delete operation when a key is Put then Deleted, - // see https://github.com/projectnessie/nessie/pull/6472 - .hasSizeBetween(3, 4) - .anySatisfy( - o -> { - if (c.getOperations().size() == 4) { - soft.assertThat(o).isInstanceOf(Delete.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); - } - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); - }); - }); + checkSquashedCommit(targetHead, result); } soft.assertThat( @@ -269,114 +231,9 @@ protected void checkTransplantWithPreviousCommit(boolean individualCommits) false); if (individualCommits) { - soft.assertThat(result.getAddedCommits()) - .hasSize(3) - .satisfiesExactly( - c -> { - soft.assertThat(c.getParentHash()).isEqualTo(targetHead); - soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Initial Commit"); - soft.assertThat(c.getOperations()) - .hasSize(3) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_1); - }, - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_1); - }, - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_3)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_3_1); - }); - }, - c -> { - soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); - soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); - soft.assertThat(c.getOperations()) - .hasSize(4) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); - }, - o -> - soft.assertThat(o) - .asInstanceOf(type(Delete.class)) - .extracting(Delete::getKey) - .isEqualTo(ContentKey.of(T_2)), - o -> - soft.assertThat(o) - .asInstanceOf(type(Delete.class)) - .extracting(Delete::getKey) - .isEqualTo(ContentKey.of(T_3)), - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); - }); - }, - c -> { - soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(1).getHash()); - soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Third Commit"); - soft.assertThat(c.getOperations()) - .hasSize(1) - .satisfiesExactlyInAnyOrder( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); - } - // Unchanged operation not retained - ); - }); + checkRebasedCommits(targetHead, result); // no fast-forward } else { - soft.assertThat(result.getAddedCommits()) - .singleElement() - .satisfies( - c -> { - soft.assertThat(c.getParentHash()).isEqualTo(targetHead); - soft.assertThat(c.getCommitMeta().getMessage()) - .contains("Initial Commit") - .contains("Second Commit") - .contains("Third Commit"); - soft.assertThat(c.getOperations()) - // old storage model keeps the Delete operation when a key is Put then Deleted, - // see https://github.com/projectnessie/nessie/pull/6472 - .hasSizeBetween(3, 4) - .anySatisfy( - o -> { - if (c.getOperations().size() == 4) { - soft.assertThat(o).isInstanceOf(Delete.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); - } - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); - }) - .anySatisfy( - o -> { - soft.assertThat(o).isInstanceOf(Put.class); - soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); - soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); - }); - }); + checkSquashedCommit(targetHead, result); } assertThat( contentsWithoutId( @@ -397,6 +254,119 @@ protected void checkTransplantWithPreviousCommit(boolean individualCommits) ContentKey.of(T_5), V_5_1)); } + private void checkSquashedCommit(Hash targetHead, MergeResult result) { + soft.assertThat(result.getAddedCommits()) + .singleElement() + .satisfies( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()) + .contains("Initial Commit") + .contains("Second Commit") + .contains("Third Commit"); + soft.assertThat(c.getOperations()) + // old storage model keeps the Delete operation when a key is Put then Deleted, + // see https://github.com/projectnessie/nessie/pull/6472 + .hasSizeBetween(3, 4) + .anySatisfy( + o -> { + if (c.getOperations() != null && c.getOperations().size() == 4) { + soft.assertThat(o).isInstanceOf(Delete.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of("t3")); + } + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); + }) + .anySatisfy( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); + }); + }); + } + + private void checkRebasedCommits(Hash targetHead, MergeResult result) { + soft.assertThat(result.getAddedCommits()) + .hasSize(3) + .satisfiesExactly( + c -> { + soft.assertThat(c.getParentHash()).isEqualTo(targetHead); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Initial Commit"); + soft.assertThat(c.getOperations()) + .hasSize(3) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_1); + }, + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_3)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_3_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(0).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); + soft.assertThat(c.getOperations()) + .hasSize(4) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_1)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_1_2); + }, + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of(T_2)), + o -> + soft.assertThat(o) + .asInstanceOf(type(Delete.class)) + .extracting(Delete::getKey) + .isEqualTo(ContentKey.of(T_3)), + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_4)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_4_1); + }); + }, + c -> { + soft.assertThat(c.getParentHash()) + .isEqualTo(result.getAddedCommits().get(1).getHash()); + soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Third Commit"); + soft.assertThat(c.getOperations()) + .hasSize(1) + .satisfiesExactlyInAnyOrder( + o -> { + soft.assertThat(o).isInstanceOf(Put.class); + soft.assertThat(o.getKey()).isEqualTo(ContentKey.of(T_2)); + soft.assertThat(contentWithoutId(((Put) o).getValue())).isEqualTo(V_2_2); + } + // Unchanged operation not retained + ); + }); + } + @ParameterizedTest @CsvSource({ "false,false", From 58641ddb883b39bd3cfd12454a9c0a570e5b5bf9 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 5 May 2023 13:42:33 +0200 Subject: [PATCH 23/26] review comments --- .../adapter/spi/AbstractDatabaseAdapter.java | 27 +++++++++---------- .../versioned/EventsVersionStore.java | 4 +-- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java index f48fa2f25e3..fa92d635230 100644 --- a/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java +++ b/versioned/persist/adapter/src/main/java/org/projectnessie/versioned/persist/adapter/spi/AbstractDatabaseAdapter.java @@ -593,9 +593,13 @@ protected Hash mergeTransplantCommon( result); } + if (params.isDryRun()) { + return toHead; + } + if (params.keepIndividualCommits()) { // re-apply commits in 'sequenceToTransplant' onto 'targetBranch' - Hash newHead = + toHead = copyCommits( ctx, timeInMicros, @@ -606,16 +610,13 @@ protected Hash mergeTransplantCommon( mergePredicate, addedCommits); - if (!params.isDryRun()) { - // Write commits - writeMultipleCommits(ctx, commitsToMergeChronological); - commitsToMergeChronological.stream() - .peek(writtenCommits) - .map(CommitLogEntry::getHash) - .forEach(branchCommits); - toHead = newHead; - } + // Write commits + writeMultipleCommits(ctx, commitsToMergeChronological); + commitsToMergeChronological.stream() + .peek(writtenCommits) + .map(CommitLogEntry::getHash) + .forEach(branchCommits); } else { CommitLogEntry squashed = squashCommits( @@ -630,10 +631,8 @@ protected Hash mergeTransplantCommon( addedCommits); if (squashed != null) { - if (!params.isDryRun()) { - writtenCommits.accept(squashed); - toHead = squashed.getHash(); - } + writtenCommits.accept(squashed); + toHead = squashed.getHash(); } } return toHead; diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java index b0e5c8ea3ee..16d579a1c06 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/EventsVersionStore.java @@ -91,7 +91,7 @@ public MergeResult transplant( defaultMergeBehavior, dryRun, fetchAdditionalInfo); - if (!dryRun) { + if (result.wasApplied()) { resultSink.accept(result); } return result; @@ -122,7 +122,7 @@ public MergeResult merge( defaultMergeBehavior, dryRun, fetchAdditionalInfo); - if (!dryRun) { + if (result.wasApplied()) { resultSink.accept(result); } return result; From bb9e0860ec4f35fa9711a1389e167f9c399cde2f Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 5 May 2023 13:49:46 +0200 Subject: [PATCH 24/26] rename method --- .../NonTransactionalDatabaseAdapter.java | 4 +- .../persist/store/PersistVersionStore.java | 4 +- .../tests/AbstractMergeTransplant.java | 8 ++-- .../persist/tx/TxDatabaseAdapter.java | 4 +- .../projectnessie/versioned/MergeResult.java | 4 +- .../BaseMergeTransplantIndividual.java | 2 +- .../BaseMergeTransplantSquash.java | 2 +- .../versioned/tests/AbstractMerge.java | 40 +++++++++---------- .../versioned/tests/AbstractTransplant.java | 16 ++++---- 9 files changed, 42 insertions(+), 42 deletions(-) diff --git a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java index 463afcc4933..ac2f4a0ad06 100644 --- a/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java +++ b/versioned/persist/nontx/src/main/java/org/projectnessie/versioned/persist/nontx/NonTransactionalDatabaseAdapter.java @@ -252,7 +252,7 @@ public MergeResult merge(MergeParams mergeParams) branchCommits, newKeyLists, writtenCommits::add, - mergeResult::addAddedCommits, + mergeResult::addCreatedCommits, mergeParams, mergeResult); @@ -309,7 +309,7 @@ public MergeResult transplant(TransplantParams transplantParams) branchCommits, newKeyLists, writtenCommits::add, - mergeResult::addAddedCommits, + mergeResult::addCreatedCommits, transplantParams, mergeResult); diff --git a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java index 55022d5ddf0..6f84005e05c 100644 --- a/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java +++ b/versioned/persist/store/src/main/java/org/projectnessie/versioned/persist/store/PersistVersionStore.java @@ -325,7 +325,7 @@ private MergeResult storeMergeResult( { BiConsumer enhancer = enhancerForCommitLog(true); - adapterMergeResult.getAddedCommits().stream() + adapterMergeResult.getCreatedCommits().stream() .map( logEntry -> { ImmutableCommit.Builder commit = @@ -336,7 +336,7 @@ private MergeResult storeMergeResult( enhancer.accept(commit, logEntry); return commit.build(); }) - .forEach(storeResult::addAddedCommits); + .forEach(storeResult::addCreatedCommits); } return storeResult.build(); } diff --git a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java index f26ab084ee3..13e613ade89 100644 --- a/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java +++ b/versioned/persist/tests/src/main/java/org/projectnessie/versioned/persist/tests/AbstractMergeTransplant.java @@ -351,7 +351,7 @@ Hash mergeTransplantSuccess( .sourceRef(source) .targetBranch(target) .resultantTargetHash(mainHead) - .addedCommits(mergeResult.getAddedCommits()) + .createdCommits(mergeResult.getCreatedCommits()) .build()); // Merge/transplant @@ -370,13 +370,13 @@ Hash mergeTransplantSuccess( .targetBranch(target) .resultantTargetHash(targetHead) .wasApplied(true) - .addedCommits(mergeResult.getAddedCommits()) + .createdCommits(mergeResult.getCreatedCommits()) .build()); if (individualCommits) { - assertThat(mergeResult.getAddedCommits()).hasSize(expectedSourceCommits.size()); + assertThat(mergeResult.getCreatedCommits()).hasSize(expectedSourceCommits.size()); } else { - assertThat(mergeResult.getAddedCommits()).hasSize(1); + assertThat(mergeResult.getCreatedCommits()).hasSize(1); } // Briefly check commit log diff --git a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java index 7d53f871a75..3d15ad66de2 100644 --- a/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java +++ b/versioned/persist/tx/src/main/java/org/projectnessie/versioned/persist/tx/TxDatabaseAdapter.java @@ -254,7 +254,7 @@ public MergeResult merge(MergeParams mergeParams) h -> {}, h -> {}, writtenCommits::add, - result::addAddedCommits, + result::addCreatedCommits, mergeParams, result); @@ -316,7 +316,7 @@ public MergeResult transplant(TransplantParams transplantParams) h -> {}, h -> {}, writtenCommits::add, - result::addAddedCommits, + result::addCreatedCommits, transplantParams, result); diff --git a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java index fdba7617806..16e67d95849 100644 --- a/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java +++ b/versioned/spi/src/main/java/org/projectnessie/versioned/MergeResult.java @@ -76,7 +76,7 @@ default boolean wasSuccessful() { List getTargetCommits(); /** - * List of new commits that where added to the target branch. + * List of new commits that where created and added to the target branch. * *

    The returned list will always be empty if the merge or transplant operation failed. It will * also always be empty in dry-run mode. Furthermore, it will also be empty if the operation @@ -89,7 +89,7 @@ default boolean wasSuccessful() { *

    The REST API does not expose this property currently; it is used by the Nessie events * notification system. */ - List getAddedCommits(); + List getCreatedCommits(); /** Details of all keys encountered during the merge or transplant operation. */ Map getDetails(); diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java index f825f7c0853..4cedb98bdf7 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantIndividual.java @@ -104,7 +104,7 @@ MergeResult individualCommits( newHead = newCommit.id(); boolean committed = commitLogic.storeCommit(newCommit, objsToStore); if (committed) { - mergeResult.addAddedCommits(commitObjToCommit(newCommit)); + mergeResult.addCreatedCommits(commitObjToCommit(newCommit)); } } diff --git a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java index 68fbf1ceccf..bc9e11cc3af 100644 --- a/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java +++ b/versioned/storage/store/src/main/java/org/projectnessie/versioned/storage/versionstore/BaseMergeTransplantSquash.java @@ -107,7 +107,7 @@ MergeResult squash( newHead = mergeCommit.id(); boolean committed = commitLogic.storeCommit(mergeCommit, objsToStore); if (committed) { - mergeResult.addAddedCommits(commitObjToCommit(mergeCommit)); + mergeResult.addCreatedCommits(commitObjToCommit(mergeCommit)); } } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java index 690e6a28523..ba52d838e93 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractMerge.java @@ -493,9 +493,9 @@ private void checkAddedCommits( boolean expectFastForward) { if (individualCommits) { if (expectFastForward) { - soft.assertThat(result.getAddedCommits()).isEmpty(); + soft.assertThat(result.getCreatedCommits()).isEmpty(); } else { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .hasSize(3) .satisfiesExactly( c -> { @@ -525,7 +525,7 @@ private void checkAddedCommits( }, c -> { soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); + .isEqualTo(result.getCreatedCommits().get(0).getHash()); soft.assertThat(c.getCommitMeta().getMessage()).contains("Second Commit"); soft.assertThat(c.getOperations()) .hasSize(4) @@ -555,7 +555,7 @@ private void checkAddedCommits( }, c -> { soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(1).getHash()); + .isEqualTo(result.getCreatedCommits().get(1).getHash()); soft.assertThat(c.getCommitMeta().getMessage()).contains("Third Commit"); soft.assertThat(c.getOperations()) .hasSize(1) @@ -571,7 +571,7 @@ private void checkAddedCommits( }); } } else { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .singleElement() .satisfies( c -> { @@ -689,7 +689,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio Put.of(ContentKey.of("t3"), V_3_1))))); soft.assertThat(mergeResult.getTargetCommits()).isNull(); // The branch was fast-forwarded to firstCommit, so no commits added - soft.assertThat(mergeResult.getAddedCommits()).isEmpty(); + soft.assertThat(mergeResult.getCreatedCommits()).isEmpty(); soft.assertThat(mergeResult.getDetails()) .containsKeys(ContentKey.of("t1"), ContentKey.of("t2"), ContentKey.of("t3")); soft.assertThat(mergeResult) @@ -706,7 +706,7 @@ void compareDryAndEffectiveMergeResults(boolean individualCommits) throws Versio .effectiveTargetHash(initialHash) .expectedHash(initialHash) .addAllSourceCommits(mergeResult.getSourceCommits()) - .addAllAddedCommits(mergeResult.getAddedCommits()) + .addAllCreatedCommits(mergeResult.getCreatedCommits()) .putAllDetails(mergeResult.getDetails()) .build()) // compare "effective" merge-result with dry-run merge-result @@ -758,7 +758,7 @@ protected void mergeIntoEmptyBranch1Commit(boolean individualCommits) // not modifying commit meta, will just "fast forward" soft.assertThat(store().hashOnReference(newBranch, Optional.empty())).isEqualTo(firstCommit); - soft.assertThat(result.getAddedCommits()).isEmpty(); // no new commits + soft.assertThat(result.getCreatedCommits()).isEmpty(); // no new commits List mergedCommit = commitsList(newBranch, false).subList(0, 1); assertCommitMeta(soft, mergedCommit, commits.subList(2, 3), metadataRewriter); @@ -900,7 +900,7 @@ protected void mergeIntoNonConflictingBranch(boolean individualCommits) c4 -> assertThat(c4).extracting(Commit::getHash).isEqualTo(initialHash)); } if (individualCommits) { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .hasSize(3) .satisfiesExactly( commit -> { @@ -909,16 +909,16 @@ protected void mergeIntoNonConflictingBranch(boolean individualCommits) }, commit -> { soft.assertThat(commit.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); + .isEqualTo(result.getCreatedCommits().get(0).getHash()); soft.assertThat(commit.getCommitMeta().getMessage()).isEqualTo("Second Commit"); }, commit -> { soft.assertThat(commit.getParentHash()) - .isEqualTo(result.getAddedCommits().get(1).getHash()); + .isEqualTo(result.getCreatedCommits().get(1).getHash()); soft.assertThat(commit.getCommitMeta().getMessage()).isEqualTo("Third Commit"); }); } else { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .singleElement() .extracting(Commit::getParentHash) .isEqualTo(newCommit); @@ -957,7 +957,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio false, false); soft.assertThat(mergeResult1.getResultantTargetHash()).isEqualTo(etl1.getCommitHash()); - soft.assertThat(mergeResult1.getAddedCommits()).isEmpty(); // fast-forward, so nothing added + soft.assertThat(mergeResult1.getCreatedCommits()).isEmpty(); // fast-forward, so nothing added CommitResult etl2 = store() @@ -980,7 +980,7 @@ protected void nonEmptyFastForwardMerge(boolean individualCommits) throws Versio false, false); soft.assertThat(mergeResult2.getResultantTargetHash()).isEqualTo(etl2.getCommitHash()); - soft.assertThat(mergeResult2.getAddedCommits()).isEmpty(); // fast-forward, so nothing added + soft.assertThat(mergeResult2.getCreatedCommits()).isEmpty(); // fast-forward, so nothing added soft.assertThat(contentWithoutId(store().getValue(review, key))).isEqualTo(VALUE_2); } @@ -1036,7 +1036,7 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version c -> assertThat(c.getHash()).isEqualTo(newCommit), c -> assertThat(c.getHash()).isEqualTo(firstCommit), c -> assertThat(c.getHash()).isEqualTo(initialHash)); - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .hasSize(2) .satisfiesExactly( c -> assertThat(c).isEqualTo(commits.get(1)), @@ -1053,7 +1053,7 @@ protected void mergeWithCommonAncestor(boolean individualCommits) throws Version c -> assertThat(c.getHash()).isEqualTo(firstCommit), c -> assertThat(c.getHash()).isEqualTo(initialHash)); - soft.assertThat(result.getAddedCommits()).singleElement().isEqualTo(commits.get(0)); + soft.assertThat(result.getCreatedCommits()).singleElement().isEqualTo(commits.get(0)); soft.assertThat(commits) .first() @@ -1252,7 +1252,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .containsEntry(key3, VALUE_5) .containsEntry(key4, VALUE_6); - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .singleElement() .satisfies( commit -> { @@ -1306,7 +1306,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu .containsEntry(key4, VALUE_6); if (individualCommits) { - soft.assertThat(result2.getAddedCommits()) + soft.assertThat(result2.getCreatedCommits()) .hasSize(2) .satisfiesExactly( commit -> { @@ -1330,7 +1330,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu soft.assertThat(commit.getCommitMeta().getMessage()) .isEqualTo("commit 4, merge-all-force"); soft.assertThat(commit.getParentHash()) - .isEqualTo(result2.getAddedCommits().get(0).getHash()); + .isEqualTo(result2.getCreatedCommits().get(0).getHash()); soft.assertThat(commit.getOperations()) .singleElement() .satisfies( @@ -1341,7 +1341,7 @@ protected void mergeWithConflictingKeys(boolean individualCommits, boolean dryRu }); }); } else { - soft.assertThat(result2.getAddedCommits()) + soft.assertThat(result2.getCreatedCommits()) .singleElement() .satisfies( commit -> { diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java index ef4afe3fd5b..057f760c34d 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractTransplant.java @@ -179,7 +179,7 @@ private BranchName checkTransplantOnEmptyBranch( false); if (individualCommits) { - soft.assertThat(result.getAddedCommits()).isEmpty(); // fast-forward + soft.assertThat(result.getCreatedCommits()).isEmpty(); // fast-forward } else { checkSquashedCommit(targetHead, result); } @@ -255,7 +255,7 @@ protected void checkTransplantWithPreviousCommit(boolean individualCommits) } private void checkSquashedCommit(Hash targetHead, MergeResult result) { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .singleElement() .satisfies( c -> { @@ -297,7 +297,7 @@ private void checkSquashedCommit(Hash targetHead, MergeResult result) { } private void checkRebasedCommits(Hash targetHead, MergeResult result) { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .hasSize(3) .satisfiesExactly( c -> { @@ -324,7 +324,7 @@ private void checkRebasedCommits(Hash targetHead, MergeResult result) { }, c -> { soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); + .isEqualTo(result.getCreatedCommits().get(0).getHash()); soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); soft.assertThat(c.getOperations()) .hasSize(4) @@ -352,7 +352,7 @@ private void checkRebasedCommits(Hash targetHead, MergeResult result) { }, c -> { soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(1).getHash()); + .isEqualTo(result.getCreatedCommits().get(1).getHash()); soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Third Commit"); soft.assertThat(c.getOperations()) .hasSize(1) @@ -628,7 +628,7 @@ protected void transplantBasic(boolean individualCommits) throws VersionStoreExc false); if (individualCommits) { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .hasSize(2) .satisfiesExactly( c -> { @@ -637,11 +637,11 @@ protected void transplantBasic(boolean individualCommits) throws VersionStoreExc }, c -> { soft.assertThat(c.getParentHash()) - .isEqualTo(result.getAddedCommits().get(0).getHash()); + .isEqualTo(result.getCreatedCommits().get(0).getHash()); soft.assertThat(c.getCommitMeta().getMessage()).isEqualTo("Second Commit"); }); } else { - soft.assertThat(result.getAddedCommits()) + soft.assertThat(result.getCreatedCommits()) .singleElement() .satisfies( c -> { From e78269fffa2ebbd83cf38a3406837c2a034c6984 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 5 May 2023 13:50:27 +0200 Subject: [PATCH 25/26] fix tests --- .../org/projectnessie/versioned/TestEventsVersionStore.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java index 5fe6f4e5402..d6ccd294caa 100644 --- a/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java +++ b/versioned/spi/src/test/java/org/projectnessie/versioned/TestEventsVersionStore.java @@ -193,6 +193,7 @@ void testTransplantSuccessful() throws Exception { .resultType(ResultType.TRANSPLANT) .effectiveTargetHash(hash1) .resultantTargetHash(hash2) + .wasApplied(true) .build(); when(delegate.transplant( branch1, @@ -347,6 +348,7 @@ void testMergeSuccessful() throws Exception { .resultType(ResultType.MERGE) .effectiveTargetHash(hash1) .resultantTargetHash(hash2) + .wasApplied(true) .build(); when(delegate.merge( branch1, From 5dbecdce51d632c35104e3c0be872c6f578e6bd9 Mon Sep 17 00:00:00 2001 From: Alexandre Dutra Date: Fri, 5 May 2023 14:08:03 +0200 Subject: [PATCH 26/26] more assertions --- .../versioned/tests/AbstractAssign.java | 26 +++++++++++--- .../versioned/tests/AbstractCommits.java | 29 +++++++++++----- .../versioned/tests/AbstractReferences.java | 34 ++++++++++++++----- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java index 8dcbaa6642f..5ca07cac83a 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractAssign.java @@ -29,6 +29,7 @@ import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceAssignedResult; import org.projectnessie.versioned.ReferenceConflictException; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; @@ -58,8 +59,16 @@ public void assign() throws VersionStoreException { store().create(TagName.of("tag3"), Optional.of(commit)); final Hash anotherCommit = commit("Another commit").toBranch(branch); - store().assign(TagName.of("tag2"), Optional.of(commit), anotherCommit); - store().assign(TagName.of("tag3"), Optional.empty(), anotherCommit); + ReferenceAssignedResult referenceAssignedResult = + store().assign(TagName.of("tag2"), Optional.of(commit), anotherCommit); + soft.assertThat(referenceAssignedResult.getPreviousHash()).isEqualTo(commit); + soft.assertThat(referenceAssignedResult.getCurrentHash()).isEqualTo(anotherCommit); + soft.assertThat(referenceAssignedResult.getNamedRef()).isEqualTo(TagName.of("tag2")); + + referenceAssignedResult = store().assign(TagName.of("tag3"), Optional.empty(), anotherCommit); + soft.assertThat(referenceAssignedResult.getPreviousHash()).isEqualTo(commit); + soft.assertThat(referenceAssignedResult.getCurrentHash()).isEqualTo(anotherCommit); + soft.assertThat(referenceAssignedResult.getNamedRef()).isEqualTo(TagName.of("tag3")); soft.assertThatThrownBy( () -> store().assign(BranchName.of("baz"), Optional.empty(), anotherCommit)) @@ -116,13 +125,22 @@ public void assignReferenceToFreshMain() BranchName testBranch = BranchName.of("testBranch"); Hash testBranchHash = store.create(testBranch, Optional.empty()).getHash(); - store.assign(testBranch, Optional.of(testBranchHash), main.getHash()); + ReferenceAssignedResult referenceAssignedResult = + store.assign(testBranch, Optional.of(testBranchHash), main.getHash()); + soft.assertThat(referenceAssignedResult.getPreviousHash()).isEqualTo(main.getHash()); + soft.assertThat(referenceAssignedResult.getCurrentHash()).isEqualTo(testBranchHash); + soft.assertThat(referenceAssignedResult.getNamedRef()).isEqualTo(testBranch); + soft.assertThat(store.getNamedRef(testBranch.getName(), GetNamedRefsParams.DEFAULT).getHash()) .isEqualTo(main.getHash()); TagName testTag = TagName.of("testTag"); Hash testTagHash = store.create(testTag, Optional.empty()).getHash(); - store.assign(testTag, Optional.of(testTagHash), main.getHash()); + referenceAssignedResult = store.assign(testTag, Optional.of(testTagHash), main.getHash()); + soft.assertThat(referenceAssignedResult.getPreviousHash()).isEqualTo(main.getHash()); + soft.assertThat(referenceAssignedResult.getCurrentHash()).isEqualTo(testTagHash); + soft.assertThat(referenceAssignedResult.getNamedRef()).isEqualTo(testTag); + soft.assertThat(store.getNamedRef(testTag.getName(), GetNamedRefsParams.DEFAULT).getHash()) .isEqualTo(main.getHash()); } diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java index faf8e10a2a6..f92265a5af8 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractCommits.java @@ -41,6 +41,8 @@ import org.projectnessie.model.Content; import org.projectnessie.model.ContentKey; import org.projectnessie.versioned.BranchName; +import org.projectnessie.versioned.Commit; +import org.projectnessie.versioned.CommitResult; import org.projectnessie.versioned.Delete; import org.projectnessie.versioned.GetNamedRefsParams; import org.projectnessie.versioned.Hash; @@ -89,24 +91,33 @@ public void commitToBranch() throws Exception { final Hash initialHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(createHash).isEqualTo(initialHash); - final Hash commitHash0 = + CommitResult result = store() .commit( branch, Optional.of(initialHash), CommitMeta.fromMessage("Some commit"), - Collections.emptyList()) - .getCommitHash(); + Collections.emptyList()); + soft.assertThat(result.getCommit().getParentHash()).isEqualTo(initialHash); + soft.assertThat(result.getCommit().getOperations()).isNullOrEmpty(); + soft.assertThat(result.getTargetBranch()).isEqualTo(branch); + + final Hash commitHash0 = result.getCommitHash(); final Hash commitHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(commitHash).isEqualTo(commitHash0); soft.assertThat(commitHash).isNotEqualTo(initialHash); - store() - .commit( - branch, - Optional.of(initialHash), - CommitMeta.fromMessage("Another commit"), - Collections.emptyList()); + result = + store() + .commit( + branch, + Optional.of(initialHash), + CommitMeta.fromMessage("Another commit"), + Collections.emptyList()); + soft.assertThat(result.getCommit().getParentHash()).isEqualTo(commitHash); + soft.assertThat(result.getCommit().getOperations()).isNullOrEmpty(); + soft.assertThat(result.getTargetBranch()).isEqualTo(branch); + final Hash anotherCommitHash = store().hashOnReference(branch, Optional.empty()); soft.assertThat(commitsList(branch, false)) diff --git a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java index 0b4d2fab41a..ff1c4921a1d 100644 --- a/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java +++ b/versioned/tests/src/main/java/org/projectnessie/versioned/tests/AbstractReferences.java @@ -37,6 +37,8 @@ import org.projectnessie.versioned.Hash; import org.projectnessie.versioned.NamedRef; import org.projectnessie.versioned.ReferenceAlreadyExistsException; +import org.projectnessie.versioned.ReferenceCreatedResult; +import org.projectnessie.versioned.ReferenceDeletedResult; import org.projectnessie.versioned.ReferenceInfo; import org.projectnessie.versioned.ReferenceNotFoundException; import org.projectnessie.versioned.TagName; @@ -69,14 +71,18 @@ public void createAndDeleteBranch() throws Exception { soft.assertThat(hash).isNotNull(); final BranchName anotherBranch = BranchName.of("bar"); - final Hash createHash = store().create(anotherBranch, Optional.of(hash)).getHash(); + ReferenceCreatedResult referenceCreatedResult = + store().create(anotherBranch, Optional.of(hash)); + soft.assertThat(referenceCreatedResult.getHash()).isEqualTo(hash); + soft.assertThat(referenceCreatedResult.getNamedRef()).isEqualTo(anotherBranch); + final Hash commitHash = commit("Some Commit").toBranch(anotherBranch); - soft.assertThat(commitHash).isNotEqualTo(createHash); + soft.assertThat(commitHash).isNotEqualTo(referenceCreatedResult.getHash()); final BranchName anotherAnotherBranch = BranchName.of("baz"); - final Hash otherCreateHash = - store().create(anotherAnotherBranch, Optional.of(commitHash)).getHash(); - soft.assertThat(otherCreateHash).isEqualTo(commitHash); + referenceCreatedResult = store().create(anotherAnotherBranch, Optional.of(commitHash)); + soft.assertThat(referenceCreatedResult.getHash()).isEqualTo(commitHash); + soft.assertThat(referenceCreatedResult.getNamedRef()).isEqualTo(anotherAnotherBranch); List> namedRefs; try (PaginationIterator> str = @@ -100,7 +106,10 @@ public void createAndDeleteBranch() throws Exception { soft.assertThatThrownBy(() -> store().create(branch, Optional.of(hash))) .isInstanceOf(ReferenceAlreadyExistsException.class); - store().delete(branch, Optional.of(hash)); + ReferenceDeletedResult referenceDeletedResult = store().delete(branch, Optional.of(hash)); + soft.assertThat(referenceDeletedResult.getHash()).isEqualTo(hash); + soft.assertThat(referenceDeletedResult.getNamedRef()).isEqualTo(branch); + soft.assertThatThrownBy(() -> store().hashOnReference(branch, Optional.empty())) .isInstanceOf(ReferenceNotFoundException.class); try (PaginationIterator> str = @@ -132,10 +141,14 @@ public void createAndDeleteTag() throws Exception { final Hash commitHash = commit("Some commit").toBranch(branch); final TagName tag = TagName.of("tag"); - store().create(tag, Optional.of(initialHash)); + ReferenceCreatedResult referenceCreatedResult = store().create(tag, Optional.of(initialHash)); + soft.assertThat(referenceCreatedResult.getHash()).isEqualTo(initialHash); + soft.assertThat(referenceCreatedResult.getNamedRef()).isEqualTo(tag); final TagName anotherTag = TagName.of("another-tag"); - store().create(anotherTag, Optional.of(commitHash)); + referenceCreatedResult = store().create(anotherTag, Optional.of(commitHash)); + soft.assertThat(referenceCreatedResult.getHash()).isEqualTo(commitHash); + soft.assertThat(referenceCreatedResult.getNamedRef()).isEqualTo(anotherTag); soft.assertThatThrownBy(() -> store().create(tag, Optional.of(initialHash))) .isInstanceOf(ReferenceAlreadyExistsException.class); @@ -160,7 +173,10 @@ public void createAndDeleteTag() throws Exception { soft.assertThat(commitsList(anotherTag, false)).hasSize(1); soft.assertThat(commitsList(commitHash, false)).hasSize(1); // empty commit should not be listed - store().delete(tag, Optional.of(initialHash)); + ReferenceDeletedResult referenceDeletedResult = store().delete(tag, Optional.of(initialHash)); + soft.assertThat(referenceDeletedResult.getHash()).isEqualTo(initialHash); + soft.assertThat(referenceDeletedResult.getNamedRef()).isEqualTo(tag); + soft.assertThatThrownBy(() -> store().hashOnReference(tag, Optional.empty())) .isInstanceOf(ReferenceNotFoundException.class); try (PaginationIterator> str =