From 41643dcb79a52e9fac03b77d40d6b33df13f034b Mon Sep 17 00:00:00 2001 From: Adithya Chakilam Date: Tue, 23 Feb 2021 13:58:03 -0600 Subject: [PATCH] Optimize RevWalkUtils.findBranchesReachableFrom() In [1], improved RevWalk.getMergedInto() is introduced to avoid repeated work while performing RevWalk.isMergedInto() on many refs. Modify findBranchesReachableFrom() to use it. [1] I65de9873dce67af9c415d1d236bf52d31b67e8fe Change-Id: I81d615241638d4093df64b449637af601843a5ed Signed-off-by: Adithya Chakilam --- .../src/org/eclipse/jgit/revwalk/RevWalk.java | 42 +++++++++++++++++-- .../eclipse/jgit/revwalk/RevWalkUtils.java | 9 ++-- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index 3ca2ff603..5d5ba12ba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -32,10 +32,12 @@ import org.eclipse.jgit.lib.AsyncObjectLoaderQueue; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.MutableObjectId; +import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdOwnerMap; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.filter.RevFilter; @@ -450,7 +452,33 @@ public boolean isMergedInto(RevCommit base, RevCommit tip) */ public List getMergedInto(RevCommit commit, Collection refs) throws IOException{ - return getMergedInto(commit, refs, GetMergedIntoStrategy.EVALUATE_ALL); + return getMergedInto(commit, refs, NullProgressMonitor.INSTANCE); + } + + /** + * Determine the Refs into which a commit is merged. + *

+ * A commit is merged into a ref if we can find a path of commits that leads + * from that specific ref and ends at commit. + *

+ * + * @param commit + * commit the caller thinks is reachable from refs. + * @param refs + * refs to start iteration from, and which is most likely a + * descendant (child) of commit. + * @param monitor + * the callback for progress and cancellation + * @return list of refs that are reachable from commit. + * @throws java.io.IOException + * a pack file or loose object could not be read. + * @since 5.12 + */ + public List getMergedInto(RevCommit commit, Collection refs, + ProgressMonitor monitor) throws IOException{ + return getMergedInto(commit, refs, + GetMergedIntoStrategy.EVALUATE_ALL, + monitor); } /** @@ -470,7 +498,8 @@ public List getMergedInto(RevCommit commit, Collection refs) public boolean isMergedIntoAny(RevCommit commit, Collection refs) throws IOException { return getMergedInto(commit, refs, - GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND).size() > 0; + GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND, + NullProgressMonitor.INSTANCE).size() > 0; } /** @@ -490,12 +519,13 @@ public boolean isMergedIntoAny(RevCommit commit, Collection refs) public boolean isMergedIntoAll(RevCommit commit, Collection refs) throws IOException { return getMergedInto(commit, refs, - GetMergedIntoStrategy.RETURN_ON_FIRST_NOT_FOUND).size() + GetMergedIntoStrategy.RETURN_ON_FIRST_NOT_FOUND, + NullProgressMonitor.INSTANCE).size() == refs.size(); } private List getMergedInto(RevCommit needle, Collection haystacks, - Enum returnStrategy) throws IOException { + Enum returnStrategy, ProgressMonitor monitor) throws IOException { List result = new ArrayList<>(); RevFilter oldRF = filter; TreeFilter oldTF = treeFilter; @@ -504,6 +534,10 @@ private List getMergedInto(RevCommit needle, Collection haystacks, filter = RevFilter.ALL; treeFilter = TreeFilter.ALL; for (Ref r: haystacks) { + if (monitor.isCancelled()) { + return result; + } + monitor.update(1); RevObject o = parseAny(r.getObjectId()); if (!(o instanceof RevCommit)) { continue; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java index 3feb9c5a4..e52e91631 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java @@ -159,15 +159,12 @@ public static List findBranchesReachableFrom(RevCommit commit, // Make sure commit is from the same RevWalk commit = revWalk.parseCommit(commit.getId()); revWalk.reset(); - List result = new ArrayList<>(); + List filteredRefs = new ArrayList<>(); monitor.beginTask(JGitText.get().searchForReachableBranches, refs.size()); final int SKEW = 24*3600; // one day clock skew for (Ref ref : refs) { - if (monitor.isCancelled()) - return result; - monitor.update(1); RevObject maybehead = revWalk.parseAny(ref.getObjectId()); if (!(maybehead instanceof RevCommit)) continue; @@ -179,9 +176,9 @@ public static List findBranchesReachableFrom(RevCommit commit, if (headCommit.getCommitTime() + SKEW < commit.getCommitTime()) continue; - if (revWalk.isMergedInto(commit, headCommit)) - result.add(ref); + filteredRefs.add(ref); } + List result = revWalk.getMergedInto(commit, filteredRefs, monitor); monitor.endTask(); return result; }