use of org.projectnessie.versioned.Hash in project nessie by projectnessie.
the class AbstractDatabaseAdapter method checkForModifiedKeysBetweenExpectedAndCurrentCommit.
/**
* If the current HEAD of the target branch for a commit/transplant/merge is not equal to the
* expected/reference HEAD, verify that there is no conflict, like keys in the operations of the
* commit(s) contained in keys of the commits 'expectedHead (excluding) .. currentHead
* (including)'.
*/
protected void checkForModifiedKeysBetweenExpectedAndCurrentCommit(OP_CONTEXT ctx, CommitAttempt commitAttempt, Hash branchHead, List<String> mismatches) throws ReferenceNotFoundException {
if (commitAttempt.getExpectedHead().isPresent()) {
Hash expectedHead = commitAttempt.getExpectedHead().get();
if (!expectedHead.equals(branchHead)) {
Set<Key> operationKeys = new HashSet<>();
operationKeys.addAll(commitAttempt.getDeletes());
operationKeys.addAll(commitAttempt.getUnchanged());
commitAttempt.getPuts().stream().map(KeyWithBytes::getKey).forEach(operationKeys::add);
boolean sinceSeen = checkConflictingKeysForCommit(ctx, branchHead, expectedHead, operationKeys, mismatches::add);
// branch.
if (!sinceSeen && !expectedHead.equals(NO_ANCESTOR)) {
throw hashNotFound(commitAttempt.getCommitToBranch(), expectedHead);
}
}
}
}
use of org.projectnessie.versioned.Hash in project nessie by projectnessie.
the class AbstractDatabaseAdapter method findCommonAncestor.
protected <R> R findCommonAncestor(OP_CONTEXT ctx, Hash from, CommonAncestorState state, BiFunction<Integer, Hash, R> result) {
Iterator<Hash> fromLog = Spliterators.iterator(readCommitLogHashes(ctx, from));
List<Hash> fromCommitHashes = new ArrayList<>();
while (true) {
boolean anyFetched = false;
for (int i = 0; i < config.getParentsPerCommit(); i++) {
if (state.fetchNext()) {
anyFetched = true;
}
if (fromLog.hasNext()) {
fromCommitHashes.add(fromLog.next());
anyFetched = true;
}
}
if (!anyFetched) {
return null;
}
for (int diffOnFrom = 0; diffOnFrom < fromCommitHashes.size(); diffOnFrom++) {
Hash f = fromCommitHashes.get(diffOnFrom);
if (state.contains(f)) {
return result.apply(diffOnFrom, f);
}
}
}
}
use of org.projectnessie.versioned.Hash in project nessie by projectnessie.
the class AbstractDatabaseAdapter method buildIndividualCommit.
/**
* Builds a {@link CommitLogEntry} using the given values. This function also includes a {@link
* KeyList}, if triggered by the values of {@code currentKeyListDistance} and {@link
* DatabaseAdapterConfig#getKeyListDistance()}, so read operations may happen.
*/
protected CommitLogEntry buildIndividualCommit(OP_CONTEXT ctx, long timeInMicros, List<Hash> parentHashes, long commitSeq, ByteString commitMeta, List<KeyWithBytes> puts, List<Key> deletes, int currentKeyListDistance, Consumer<Hash> newKeyLists, @Nonnull Function<Hash, CommitLogEntry> inMemoryCommits) throws ReferenceNotFoundException {
Hash commitHash = individualCommitHash(parentHashes, commitMeta, puts, deletes);
int keyListDistance = currentKeyListDistance + 1;
CommitLogEntry entry = CommitLogEntry.of(timeInMicros, commitHash, commitSeq, parentHashes, commitMeta, puts, deletes, keyListDistance, null, Collections.emptyList());
if (keyListDistance >= config.getKeyListDistance()) {
entry = buildKeyList(ctx, entry, newKeyLists, inMemoryCommits);
}
return entry;
}
use of org.projectnessie.versioned.Hash in project nessie by projectnessie.
the class AbstractDatabaseAdapter method findCommonAncestor.
/**
* Finds the common-ancestor of two commit-log-entries. If no common-ancestor is found, throws a
* {@link ReferenceConflictException} or. Otherwise this method returns the hash of the
* common-ancestor.
*/
protected Hash findCommonAncestor(OP_CONTEXT ctx, Hash from, NamedRef toBranch, Hash toHead) throws ReferenceConflictException {
// TODO this implementation requires guardrails:
// max number of "to"-commits to fetch, max number of "from"-commits to fetch,
// both impact the cost (CPU, memory, I/O) of a merge operation.
CommonAncestorState commonAncestorState = new CommonAncestorState(ctx, toHead, false);
Hash commonAncestorHash = findCommonAncestor(ctx, from, commonAncestorState, (dist, hash) -> hash);
if (commonAncestorHash == null) {
throw new ReferenceConflictException(String.format("No common ancestor found for merge of '%s' into branch '%s'", from, toBranch.getName()));
}
return commonAncestorHash;
}
use of org.projectnessie.versioned.Hash in project nessie by projectnessie.
the class AbstractDatabaseAdapter method namedRefsWithDefaultBranchRelatedInfo.
/**
* If necessary based on the given {@link GetNamedRefsParams}, updates the returned {@link
* ReferenceInfo}s with the common-ancestor of the named reference and the default branch and the
* number of commits behind/ahead compared to the default branch.
*
* <p>The common ancestor and/or information of commits behind/ahead is meaningless ({@code null})
* for the default branch. Both fields are also {@code null} if the named reference points to the
* {@link #noAncestorHash()} (beginning of time).
*/
protected Stream<ReferenceInfo<ByteString>> namedRefsWithDefaultBranchRelatedInfo(OP_CONTEXT ctx, GetNamedRefsParams params, Stream<ReferenceInfo<ByteString>> refs, Hash defaultBranchHead) {
if (defaultBranchHead == null) {
// No enhancement of common ancestor and/or commits behind/ahead.
return refs;
}
CommonAncestorState commonAncestorState = new CommonAncestorState(ctx, defaultBranchHead, params.getBranchRetrieveOptions().isComputeAheadBehind() || params.getTagRetrieveOptions().isComputeAheadBehind());
return refs.map(ref -> {
if (ref.getNamedRef().equals(params.getBaseReference())) {
return ref;
}
RetrieveOptions retrieveOptions = namedRefsRetrieveOptionsForReference(params, ref);
ReferenceInfo<ByteString> updated = namedRefsRequiresBaseReference(retrieveOptions) ? findCommonAncestor(ctx, ref.getHash(), commonAncestorState, (diffOnFrom, hash) -> {
ReferenceInfo<ByteString> newRef = ref;
if (retrieveOptions.isComputeCommonAncestor()) {
newRef = newRef.withCommonAncestor(hash);
}
if (retrieveOptions.isComputeAheadBehind()) {
int behind = commonAncestorState.indexOf(hash);
CommitsAheadBehind aheadBehind = CommitsAheadBehind.of(diffOnFrom, behind);
newRef = newRef.withAheadBehind(aheadBehind);
}
return newRef;
}) : null;
return updated != null ? updated : ref;
});
}
Aggregations