|
|
|
@ -45,10 +45,16 @@ package org.eclipse.jgit.revwalk;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException; |
|
|
|
|
import org.eclipse.jgit.errors.MissingObjectException; |
|
|
|
|
import org.eclipse.jgit.lib.AnyObjectId; |
|
|
|
|
import org.eclipse.jgit.lib.ObjectId; |
|
|
|
|
import org.eclipse.jgit.lib.ObjectIdSubclassMap; |
|
|
|
|
import org.eclipse.jgit.lib.Ref; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Utility methods for {@link RevWalk}. |
|
|
|
@ -124,4 +130,71 @@ public final class RevWalkUtils {
|
|
|
|
|
commits.add(c); |
|
|
|
|
return commits; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Find the list of branches a given commit is reachable from when following |
|
|
|
|
* parent.s |
|
|
|
|
* <p> |
|
|
|
|
* Note that this method calls {@link RevWalk#reset()} at the beginning. |
|
|
|
|
* <p> |
|
|
|
|
* In order to improve performance this method assumes clock skew among |
|
|
|
|
* committers is never larger than 24 hours. |
|
|
|
|
* |
|
|
|
|
* @param commit |
|
|
|
|
* the commit we are looking at |
|
|
|
|
* @param revWalk |
|
|
|
|
* The RevWalk to be used. |
|
|
|
|
* @param refs |
|
|
|
|
* the set of branches we want to see reachability from |
|
|
|
|
* @return the list of branches a given commit is reachable from |
|
|
|
|
* @throws MissingObjectException |
|
|
|
|
* @throws IncorrectObjectTypeException |
|
|
|
|
* @throws IOException |
|
|
|
|
*/ |
|
|
|
|
public static List<Ref> findBranchesReachableFrom(RevCommit commit, |
|
|
|
|
RevWalk revWalk, Collection<Ref> refs) |
|
|
|
|
throws MissingObjectException, IncorrectObjectTypeException, |
|
|
|
|
IOException { |
|
|
|
|
|
|
|
|
|
List<Ref> result = new ArrayList<Ref>(); |
|
|
|
|
// searches from branches can be cut off early if any parent of the
|
|
|
|
|
// search-for commit is found. This is quite likely, so optimize for this.
|
|
|
|
|
revWalk.markStart(Arrays.asList(commit.getParents())); |
|
|
|
|
ObjectIdSubclassMap<ObjectId> cutOff = new ObjectIdSubclassMap<ObjectId>(); |
|
|
|
|
|
|
|
|
|
final int SKEW = 24*3600; // one day clock skew
|
|
|
|
|
|
|
|
|
|
for (Ref ref : refs) { |
|
|
|
|
RevCommit headCommit = revWalk.parseCommit(ref.getObjectId()); |
|
|
|
|
|
|
|
|
|
// if commit is in the ref branch, then the tip of ref should be
|
|
|
|
|
// newer than the commit we are looking for. Allow for a large
|
|
|
|
|
// clock skew.
|
|
|
|
|
if (headCommit.getCommitTime() + SKEW < commit.getCommitTime()) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
List<ObjectId> maybeCutOff = new ArrayList<ObjectId>(cutOff.size()); // guess rough size
|
|
|
|
|
revWalk.resetRetain(); |
|
|
|
|
revWalk.markStart(headCommit); |
|
|
|
|
RevCommit current; |
|
|
|
|
Ref found = null; |
|
|
|
|
while ((current = revWalk.next()) != null) { |
|
|
|
|
if (AnyObjectId.equals(current, commit)) { |
|
|
|
|
found = ref; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
if (cutOff.contains(current)) |
|
|
|
|
break; |
|
|
|
|
maybeCutOff.add(current.toObjectId()); |
|
|
|
|
} |
|
|
|
|
if (found != null) |
|
|
|
|
result.add(ref); |
|
|
|
|
else |
|
|
|
|
for (ObjectId id : maybeCutOff) |
|
|
|
|
cutOff.addIfAbsent(id); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|