Browse Source

UploadPack: Refactor to generalize the object reachability checks

ObjectWalk#createObjectReachabilityChecker() returns the best
implementation for the repo. UploadPack can use the interface and fold
the with/without commits cases in one code path.

Change-Id: I857c11735d1d8e36c3ed8185ff11de8a62e86540
Signed-off-by: Ivan Frade <ifrade@google.com>
stable-5.8
Ivan Frade 5 years ago
parent
commit
a661e2e9eb
  1. 2
      org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java
  2. 23
      org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java
  3. 4
      org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianObjectReachabilityChecker.java
  4. 38
      org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

2
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmappedReachabilityChecker.java

@ -42,7 +42,7 @@ class BitmappedReachabilityChecker implements ReachabilityChecker {
* @throws IOException * @throws IOException
* if the index or the object reader cannot be opened. * if the index or the object reader cannot be opened.
*/ */
public BitmappedReachabilityChecker(RevWalk walk) BitmappedReachabilityChecker(RevWalk walk)
throws IOException { throws IOException {
this.walk = walk; this.walk = walk;
if (walk.getObjectReader().getBitmapIndex() == null) { if (walk.getObjectReader().getBitmapIndex() == null) {

23
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java

@ -159,6 +159,29 @@ public class ObjectWalk extends RevWalk {
pathBuf = new byte[256]; pathBuf = new byte[256];
} }
/**
* Create an object reachability checker that will use bitmaps if possible.
*
* This reachability checker accepts any object as target. For checks
* exclusively between commits, see
* {@link RevWalk#createReachabilityChecker()}.
*
* @return an object reachability checker, using bitmaps if possible.
*
* @throws IOException
* when the index fails to load.
*
* @since 5.8
*/
public ObjectReachabilityChecker createObjectReachabilityChecker()
throws IOException {
if (reader.getBitmapIndex() != null) {
return new BitmappedObjectReachabilityChecker(this);
}
return new PedestrianObjectReachabilityChecker(this);
}
/** /**
* Mark an object or commit to start graph traversal from. * Mark an object or commit to start graph traversal from.
* <p> * <p>

4
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PedestrianObjectReachabilityChecker.java

@ -22,7 +22,7 @@ import org.eclipse.jgit.errors.MissingObjectException;
* Checks if all objects are reachable from certain starting points doing a * Checks if all objects are reachable from certain starting points doing a
* walk. * walk.
*/ */
public class PedestrianObjectReachabilityChecker implements ObjectReachabilityChecker { class PedestrianObjectReachabilityChecker implements ObjectReachabilityChecker {
private ObjectWalk walk; private ObjectWalk walk;
/** /**
@ -31,7 +31,7 @@ public class PedestrianObjectReachabilityChecker implements ObjectReachabilityCh
* @param walk * @param walk
* ObjectWalk instance to reuse. Caller retains ownership. * ObjectWalk instance to reuse. Caller retains ownership.
*/ */
public PedestrianObjectReachabilityChecker(ObjectWalk walk) { PedestrianObjectReachabilityChecker(ObjectWalk walk) {
this.walk = walk; this.walk = walk;
} }

38
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

@ -75,11 +75,9 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.AsyncRevObjectQueue; import org.eclipse.jgit.revwalk.AsyncRevObjectQueue;
import org.eclipse.jgit.revwalk.BitmappedObjectReachabilityChecker;
import org.eclipse.jgit.revwalk.DepthWalk; import org.eclipse.jgit.revwalk.DepthWalk;
import org.eclipse.jgit.revwalk.ObjectReachabilityChecker; import org.eclipse.jgit.revwalk.ObjectReachabilityChecker;
import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.PedestrianObjectReachabilityChecker;
import org.eclipse.jgit.revwalk.ReachabilityChecker; import org.eclipse.jgit.revwalk.ReachabilityChecker;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.jgit.revwalk.RevFlag;
@ -1918,44 +1916,24 @@ public class UploadPack {
boolean repoHasBitmaps = reader.getBitmapIndex() != null; boolean repoHasBitmaps = reader.getBitmapIndex() != null;
if (!allWantsAreCommits) { if (!allWantsAreCommits) {
if (!repoHasBitmaps) { if (!repoHasBitmaps && !up.transferConfig.isAllowFilter()) {
if (up.transferConfig.isAllowFilter()) { // Checking unadvertised non-commits without bitmaps
// Use allowFilter as an indication that the server // requires an expensive manual walk. Use allowFilter as an
// operator is willing to pay the cost of these // indication that the server operator is willing to pay
// reachability checks. // this cost. Reject the request otherwise.
try (ObjectWalk objWalk = walk.toObjectWalkWithSameObjects()) {
List<RevObject> havesAsObjs = objectIdsToRevObjects(
objWalk, reachableFrom);
ObjectReachabilityChecker reachabilityChecker = new PedestrianObjectReachabilityChecker(
objWalk);
Optional<RevObject> unreachable = reachabilityChecker
.areAllReachable(wantsAsObjs,
havesAsObjs.stream());
if (unreachable.isPresent()) {
throw new WantNotValidException(
unreachable.get());
}
}
return;
}
// If unadvertized non-commits are requested, use
// bitmaps. If there are no bitmaps, instead of
// incurring the expense of a manual walk, reject
// the request.
RevObject nonCommit = wantsAsObjs RevObject nonCommit = wantsAsObjs
.stream() .stream()
.filter(obj -> !(obj instanceof RevCommit)) .filter(obj -> !(obj instanceof RevCommit))
.limit(1) .limit(1)
.collect(Collectors.toList()).get(0); .collect(Collectors.toList()).get(0);
throw new WantNotValidException(nonCommit); throw new WantNotValidException(nonCommit);
} }
try (ObjectWalk objWalk = walk.toObjectWalkWithSameObjects()) { try (ObjectWalk objWalk = walk.toObjectWalkWithSameObjects()) {
List<RevObject> havesAsObjs = objectIdsToRevObjects(objWalk, List<RevObject> havesAsObjs = objectIdsToRevObjects(objWalk,
reachableFrom); reachableFrom);
ObjectReachabilityChecker reachabilityChecker = new BitmappedObjectReachabilityChecker( ObjectReachabilityChecker reachabilityChecker = objWalk
objWalk); .createObjectReachabilityChecker();
Optional<RevObject> unreachable = reachabilityChecker Optional<RevObject> unreachable = reachabilityChecker
.areAllReachable(wantsAsObjs, havesAsObjs.stream()); .areAllReachable(wantsAsObjs, havesAsObjs.stream());
if (unreachable.isPresent()) { if (unreachable.isPresent()) {

Loading…
Cancel
Save