in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/CommitLoaderImpl.java [142:210]
private static Collection<RefCommit> findRefsToFetch(@NotNull OperationContext context,
@NotNull Repository db,
@NotNull Collection<RefCommit> revisions,
boolean checkTipRefs,
boolean throwErrors) throws VcsException {
final Set<RefCommit> refsToFetch = new HashSet<>();
Map<String, Ref> currentRefTips = Collections.emptyMap();
if (checkTipRefs) {
currentRefTips = loadCurrentRefTips(db, revisions);
}
try (RevWalk walk = new RevWalk(db)) {
for (RefCommit r : revisions) {
final String ref = GitUtils.expandRef(r.getRef());
final String revNumber = GitUtils.versionRevision(r.getCommit());
try {
if (checkTipRefs && r.isRefTip() && !GitServerUtil.isTag(ref)) {
// For the refs from the new ("to") state we check if these refs in the local clone point to the same revisions
// this is only done prior to determining if we need to fetch these refs selectively (hence checkTipRefs argument)
String localRev = null;
Ref localRef = currentRefTips.get(ref);
if (localRef != null) {
ObjectId localRevId = localRef.getObjectId();
if (localRevId != null) {
localRev = localRevId.getName();
}
}
if (localRev == null || !localRev.equals(revNumber))
refsToFetch.add(r);
} else {
// In all other cases we just check if revisions exist in the local clone
// This is done for all refs from the old ("from") state and also for all refs from the "to" state
// after selective fetch was done - as a last resort we will attempt to fetch all refs (not selectively)
// to obtain revisions that are still missing
walk.parseCommit(ObjectId.fromString(revNumber));
}
} catch (IncorrectObjectTypeException e) {
LOG.warn("Ref " + ref + " points to a non-commit " + revNumber + " for " + context.getGitRoot().debugInfo());
} catch (MissingObjectException e) {
refsToFetch.add(r);
} catch (Exception e) {
LOG.warnAndDebugDetails("Unexpected exception while trying to parse commit " + revNumber, e);
refsToFetch.add(r);
}
}
if (refsToFetch.isEmpty()) {
return refsToFetch;
}
LOG.debug("Revisions missing in the local repository: " +
refsToFetch.stream().map(e -> e.getRef() + ": " + e.getCommit()).collect(Collectors.joining(", ")) + " for " +
context.getGitRoot().debugInfo());
if (throwErrors) {
final Set<String> missingTips =
refsToFetch.stream().filter(RefCommit::isRefTip).map(e -> e.getRef() + ": " + e.getCommit()).collect(Collectors.toSet());
if (missingTips.size() > 0) {
final VcsException error = new VcsException("Revisions missing in the local repository: " + StringUtil.join(missingTips, ", "));
error.setRecoverable(context.getPluginConfig().treatMissingBranchTipAsRecoverableError());
throw error;
}
}
return refsToFetch;
}
}