private Set findVcsRootEntriesWithPaths()

in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/GitVcsSupport.java [480:536]


  private Set<VcsRootEntry> findVcsRootEntriesWithPaths(@NotNull Collection<GitMapFullPath.FullPath> paths, @NotNull Collection<VcsRootEntry> rootEntries) {
    Set<VcsRootEntry> res = new HashSet<>();

    Set<String> mappedPaths = new HashSet<>();
    paths.forEach(p -> mappedPaths.addAll(p.getMappedPaths()));

    Map<Pair<File, CheckoutRules>, Boolean> cache = new HashMap<>();
    for (VcsRootEntry re: rootEntries) {
      VcsRoot root = re.getVcsRoot();
      CheckoutRules checkoutRules = re.getCheckoutRules();
      if (checkoutRules.map(mappedPaths).isEmpty()) continue;

      OperationContext context = createContext(root, "repositoryContainsPath");
      try {
        final GitVcsRoot gitRoot = context.getGitRoot();
        final File cloneDir = gitRoot.getRepositoryDir();

        // group paths with the same revisions because most likely for all of them the operation can be performed only once
        Map<Pair<String, String>, List<GitMapFullPath.FullPath>> pathsGroupedByRevisions = new HashMap<>();
        for (GitMapFullPath.FullPath path: paths) {
          pathsGroupedByRevisions.computeIfAbsent(Pair.create(path.getRevision(), path.getHintRevision()), k -> new ArrayList<>()).add(path);
        }

        boolean pathsApplicable = cache.computeIfAbsent(Pair.create(cloneDir, checkoutRules), key -> {
          try {
            for (Map.Entry<Pair<String, String>, List<GitMapFullPath.FullPath>> e: pathsGroupedByRevisions.entrySet()) {
              for (GitMapFullPath.FullPath path: e.getValue()) {
                if (checkoutRules.map(path.getMappedPaths()).isEmpty()) continue;
                final GitMapFullPath.RevisionCheckResult result = myMapFullPath.repositoryContainsPath(context, gitRoot, path);
                if (result == GitMapFullPath.RevisionCheckResult.CONTAINS_PATH) return true;

                if (result == GitMapFullPath.RevisionCheckResult.DOES_NOT_CONTAIN_REVISION) {
                  // seems the path has revisions and revisions check returned false
                  // as we grouped all the paths with the same revisions together there is no need to check other paths in the same group
                  break;
                }
              }
            }
          } catch (VcsException e) {
            LOG.warnAndDebugDetails("Error while checking suitability for root " + LogUtil.describe(root) + ", assume root is not suitable", e);
          }

          return false;
        });

        if (pathsApplicable) {
          res.add(re);
        }
      } catch (VcsException e) {
        LOG.warnAndDebugDetails("Error while checking suitability for root " + LogUtil.describe(root) + ", assume root is not suitable", e);
      } finally {
        context.close();
      }
    }

    return res;
  }