in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/gitProxy/GitProxyChangesCollector.java [270:324]
private List<ModificationData> doCollectChanges(@NotNull GitVcsRoot gitRoot,
@NotNull VcsRoot root,
GitApiClient<GitRepoApi> client,
@NotNull RepositoryStateData fromState,
@NotNull RepositoryStateData toState,
@NotNull String operationId,
@Nullable Map<String, List<String>> commitIdToSubmodulePrefixes,
boolean exceptionOnSubmoduleChanges) throws VcsException {
LinkedHashSet<String> commitPatterns = new LinkedHashSet<>();
for (Map.Entry<String, String> entry: fromState.getBranchRevisions().entrySet()) {
commitPatterns.add("^" + entry.getValue());
}
for (Map.Entry<String, String> entry: toState.getBranchRevisions().entrySet()) {
String branch = entry.getKey();
String branchRevision = entry.getValue();
String fromStateRev = fromState.getBranchRevisions().get(branch);
if (fromStateRev == null || !branchRevision.equals(fromStateRev)) {
commitPatterns.add(branchRevision);
}
}
Map<String, CommitInfo> commitInfoMap = new HashMap<>();
List<CommitChange> changes = retrieveChanges(client, commitPatterns, commitInfoMap);
List<ModificationData> result = new ArrayList<>();
int i = changes.size() - 1;
// traverse the list of changes from the end and remove elements from the end of 'changes' list after processing to make it possible for gc to collect those objects later
while (i >= 0) {
CommitInfo info = commitInfoMap.get(changes.get(i).revision);
List<CommitChange> mergeEdgeChanges = null;
// find diff for other edges of merge commit, when inferMergeCommitChanges was set to false separate commit changes are returned for each edge of the merge commit
while (i - 1 >= 0 && changes.get(i - 1).revision.equals(info.id)) {
if (mergeEdgeChanges == null) {
mergeEdgeChanges = new ArrayList<>();
}
mergeEdgeChanges.add(changes.get(i));
changes.remove(i); // remove last object for gc
i--;
}
if (mergeEdgeChanges != null) {
Collections.reverse(mergeEdgeChanges);
}
CommitChange change = changes.get(i);
changes.remove(i); //remove last object for gc
i--;
if (info == null) {
LOG.error("There is no commit info for returned revision " + change.revision + "Operation id " + operationId);
continue;
}
commitInfoMap.remove(change.revision); // remove for gc
result.add(createModificationDataGitProxy(info, change, gitRoot, root, mergeEdgeChanges, commitIdToSubmodulePrefixes, exceptionOnSubmoduleChanges));
}
Collections.reverse(result);
return result;
}