private static Collection findRefsToFetch()

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;
    }
  }