Browse Source

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 <quic_achakila@quicinc.com>
tags/v5.12.0.202105051250-m2
Adithya Chakilam 3 years ago
parent
commit
41643dcb79

+ 38
- 4
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java View File

import org.eclipse.jgit.lib.AsyncObjectLoaderQueue; import org.eclipse.jgit.lib.AsyncObjectLoaderQueue;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdOwnerMap; import org.eclipse.jgit.lib.ObjectIdOwnerMap;
import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.filter.RevFilter; import org.eclipse.jgit.revwalk.filter.RevFilter;
*/ */
public List<Ref> getMergedInto(RevCommit commit, Collection<Ref> refs) public List<Ref> getMergedInto(RevCommit commit, Collection<Ref> refs)
throws IOException{ throws IOException{
return getMergedInto(commit, refs, GetMergedIntoStrategy.EVALUATE_ALL);
return getMergedInto(commit, refs, NullProgressMonitor.INSTANCE);
}

/**
* Determine the Refs into which a commit is merged.
* <p>
* A commit is merged into a ref if we can find a path of commits that leads
* from that specific ref and ends at <code>commit</code>.
* <p>
*
* @param commit
* commit the caller thinks is reachable from <code>refs</code>.
* @param refs
* refs to start iteration from, and which is most likely a
* descendant (child) of <code>commit</code>.
* @param monitor
* the callback for progress and cancellation
* @return list of refs that are reachable from <code>commit</code>.
* @throws java.io.IOException
* a pack file or loose object could not be read.
* @since 5.12
*/
public List<Ref> getMergedInto(RevCommit commit, Collection<Ref> refs,
ProgressMonitor monitor) throws IOException{
return getMergedInto(commit, refs,
GetMergedIntoStrategy.EVALUATE_ALL,
monitor);
} }


/** /**
public boolean isMergedIntoAny(RevCommit commit, Collection<Ref> refs) public boolean isMergedIntoAny(RevCommit commit, Collection<Ref> refs)
throws IOException { throws IOException {
return getMergedInto(commit, refs, return getMergedInto(commit, refs,
GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND).size() > 0;
GetMergedIntoStrategy.RETURN_ON_FIRST_FOUND,
NullProgressMonitor.INSTANCE).size() > 0;
} }


/** /**
public boolean isMergedIntoAll(RevCommit commit, Collection<Ref> refs) public boolean isMergedIntoAll(RevCommit commit, Collection<Ref> refs)
throws IOException { throws IOException {
return getMergedInto(commit, refs, return getMergedInto(commit, refs,
GetMergedIntoStrategy.RETURN_ON_FIRST_NOT_FOUND).size()
GetMergedIntoStrategy.RETURN_ON_FIRST_NOT_FOUND,
NullProgressMonitor.INSTANCE).size()
== refs.size(); == refs.size();
} }


private List<Ref> getMergedInto(RevCommit needle, Collection<Ref> haystacks, private List<Ref> getMergedInto(RevCommit needle, Collection<Ref> haystacks,
Enum returnStrategy) throws IOException {
Enum returnStrategy, ProgressMonitor monitor) throws IOException {
List<Ref> result = new ArrayList<>(); List<Ref> result = new ArrayList<>();
RevFilter oldRF = filter; RevFilter oldRF = filter;
TreeFilter oldTF = treeFilter; TreeFilter oldTF = treeFilter;
filter = RevFilter.ALL; filter = RevFilter.ALL;
treeFilter = TreeFilter.ALL; treeFilter = TreeFilter.ALL;
for (Ref r: haystacks) { for (Ref r: haystacks) {
if (monitor.isCancelled()) {
return result;
}
monitor.update(1);
RevObject o = parseAny(r.getObjectId()); RevObject o = parseAny(r.getObjectId());
if (!(o instanceof RevCommit)) { if (!(o instanceof RevCommit)) {
continue; continue;

+ 3
- 6
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalkUtils.java View File

// Make sure commit is from the same RevWalk // Make sure commit is from the same RevWalk
commit = revWalk.parseCommit(commit.getId()); commit = revWalk.parseCommit(commit.getId());
revWalk.reset(); revWalk.reset();
List<Ref> result = new ArrayList<>();
List<Ref> filteredRefs = new ArrayList<>();
monitor.beginTask(JGitText.get().searchForReachableBranches, monitor.beginTask(JGitText.get().searchForReachableBranches,
refs.size()); refs.size());
final int SKEW = 24*3600; // one day clock skew final int SKEW = 24*3600; // one day clock skew


for (Ref ref : refs) { for (Ref ref : refs) {
if (monitor.isCancelled())
return result;
monitor.update(1);
RevObject maybehead = revWalk.parseAny(ref.getObjectId()); RevObject maybehead = revWalk.parseAny(ref.getObjectId());
if (!(maybehead instanceof RevCommit)) if (!(maybehead instanceof RevCommit))
continue; continue;
if (headCommit.getCommitTime() + SKEW < commit.getCommitTime()) if (headCommit.getCommitTime() + SKEW < commit.getCommitTime())
continue; continue;


if (revWalk.isMergedInto(commit, headCommit))
result.add(ref);
filteredRefs.add(ref);
} }
List<Ref> result = revWalk.getMergedInto(commit, filteredRefs, monitor);
monitor.endTask(); monitor.endTask();
return result; return result;
} }

Loading…
Cancel
Save