|
|
@ -787,74 +787,24 @@ public class UploadPack { |
|
|
|
preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size()); |
|
|
|
preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size()); |
|
|
|
if (peerHas.isEmpty()) |
|
|
|
if (peerHas.isEmpty()) |
|
|
|
return last; |
|
|
|
return last; |
|
|
|
|
|
|
|
if (wantAll.isEmpty() && !wantIds.isEmpty()) |
|
|
|
|
|
|
|
parseWants(); |
|
|
|
|
|
|
|
|
|
|
|
List<ObjectId> toParse = peerHas; |
|
|
|
|
|
|
|
HashSet<ObjectId> peerHasSet = null; |
|
|
|
|
|
|
|
boolean needMissing = false; |
|
|
|
|
|
|
|
sentReady = false; |
|
|
|
sentReady = false; |
|
|
|
|
|
|
|
|
|
|
|
if (wantAll.isEmpty() && !wantIds.isEmpty()) { |
|
|
|
|
|
|
|
// We have not yet parsed the want list. Parse it now.
|
|
|
|
|
|
|
|
peerHasSet = new HashSet<ObjectId>(peerHas); |
|
|
|
|
|
|
|
int cnt = wantIds.size() + peerHasSet.size(); |
|
|
|
|
|
|
|
toParse = new ArrayList<ObjectId>(cnt); |
|
|
|
|
|
|
|
toParse.addAll(wantIds); |
|
|
|
|
|
|
|
toParse.addAll(peerHasSet); |
|
|
|
|
|
|
|
needMissing = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Set<RevObject> notAdvertisedWants = null; |
|
|
|
|
|
|
|
int haveCnt = 0; |
|
|
|
int haveCnt = 0; |
|
|
|
AsyncRevObjectQueue q = walk.parseAny(toParse, needMissing); |
|
|
|
walk.getObjectReader().setAvoidUnreachableObjects(true); |
|
|
|
|
|
|
|
AsyncRevObjectQueue q = walk.parseAny(peerHas, false); |
|
|
|
try { |
|
|
|
try { |
|
|
|
for (;;) { |
|
|
|
for (;;) { |
|
|
|
RevObject obj; |
|
|
|
RevObject obj; |
|
|
|
try { |
|
|
|
try { |
|
|
|
obj = q.next(); |
|
|
|
obj = q.next(); |
|
|
|
} catch (MissingObjectException notFound) { |
|
|
|
} catch (MissingObjectException notFound) { |
|
|
|
ObjectId id = notFound.getObjectId(); |
|
|
|
|
|
|
|
if (wantIds.contains(id)) { |
|
|
|
|
|
|
|
String msg = MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, id.name()); |
|
|
|
|
|
|
|
throw new PackProtocolException(msg, notFound); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
if (obj == null) |
|
|
|
if (obj == null) |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
// If the object is still found in wantIds, the want
|
|
|
|
|
|
|
|
// list wasn't parsed earlier, and was done in this batch.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
if (wantIds.remove(obj)) { |
|
|
|
|
|
|
|
if (!advertised.contains(obj) && requestPolicy != RequestPolicy.ANY) { |
|
|
|
|
|
|
|
if (notAdvertisedWants == null) |
|
|
|
|
|
|
|
notAdvertisedWants = new HashSet<RevObject>(); |
|
|
|
|
|
|
|
notAdvertisedWants.add(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!obj.has(WANT)) { |
|
|
|
|
|
|
|
obj.add(WANT); |
|
|
|
|
|
|
|
wantAll.add(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!(obj instanceof RevCommit)) |
|
|
|
|
|
|
|
obj.add(SATISFIED); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (obj instanceof RevTag) { |
|
|
|
|
|
|
|
RevObject target = walk.peel(obj); |
|
|
|
|
|
|
|
if (target instanceof RevCommit) { |
|
|
|
|
|
|
|
if (!target.has(WANT)) { |
|
|
|
|
|
|
|
target.add(WANT); |
|
|
|
|
|
|
|
wantAll.add(target); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!peerHasSet.contains(obj)) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
last = obj; |
|
|
|
last = obj; |
|
|
|
haveCnt++; |
|
|
|
haveCnt++; |
|
|
|
|
|
|
|
|
|
|
@ -889,25 +839,7 @@ public class UploadPack { |
|
|
|
} |
|
|
|
} |
|
|
|
} finally { |
|
|
|
} finally { |
|
|
|
q.release(); |
|
|
|
q.release(); |
|
|
|
} |
|
|
|
walk.getObjectReader().setAvoidUnreachableObjects(false); |
|
|
|
|
|
|
|
|
|
|
|
// If the client asked for non advertised object, check our policy.
|
|
|
|
|
|
|
|
if (notAdvertisedWants != null && !notAdvertisedWants.isEmpty()) { |
|
|
|
|
|
|
|
switch (requestPolicy) { |
|
|
|
|
|
|
|
case ADVERTISED: |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new PackProtocolException(MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, |
|
|
|
|
|
|
|
notAdvertisedWants.iterator().next().name())); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case REACHABLE_COMMIT: |
|
|
|
|
|
|
|
checkNotAdvertisedWants(notAdvertisedWants); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case ANY: |
|
|
|
|
|
|
|
// Allow whatever was asked for.
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int missCnt = peerHas.size() - haveCnt; |
|
|
|
int missCnt = peerHas.size() - haveCnt; |
|
|
@ -952,7 +884,61 @@ public class UploadPack { |
|
|
|
return last; |
|
|
|
return last; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void checkNotAdvertisedWants(Set<RevObject> notAdvertisedWants) |
|
|
|
private void parseWants() throws IOException { |
|
|
|
|
|
|
|
AsyncRevObjectQueue q = walk.parseAny(wantIds, true); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
List<RevCommit> checkReachable = null; |
|
|
|
|
|
|
|
RevObject obj; |
|
|
|
|
|
|
|
while ((obj = q.next()) != null) { |
|
|
|
|
|
|
|
if (!advertised.contains(obj)) { |
|
|
|
|
|
|
|
switch (requestPolicy) { |
|
|
|
|
|
|
|
case ADVERTISED: |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new PackProtocolException(MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, obj)); |
|
|
|
|
|
|
|
case REACHABLE_COMMIT: |
|
|
|
|
|
|
|
if (!(obj instanceof RevCommit)) { |
|
|
|
|
|
|
|
throw new PackProtocolException(MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, obj)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (checkReachable == null) |
|
|
|
|
|
|
|
checkReachable = new ArrayList<RevCommit>(); |
|
|
|
|
|
|
|
checkReachable.add((RevCommit) obj); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case ANY: |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
want(obj); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!(obj instanceof RevCommit)) |
|
|
|
|
|
|
|
obj.add(SATISFIED); |
|
|
|
|
|
|
|
if (obj instanceof RevTag) { |
|
|
|
|
|
|
|
obj = walk.peel(obj); |
|
|
|
|
|
|
|
if (obj instanceof RevCommit) |
|
|
|
|
|
|
|
want(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (checkReachable != null) |
|
|
|
|
|
|
|
checkNotAdvertisedWants(checkReachable); |
|
|
|
|
|
|
|
wantIds.clear(); |
|
|
|
|
|
|
|
} catch (MissingObjectException notFound) { |
|
|
|
|
|
|
|
ObjectId id = notFound.getObjectId(); |
|
|
|
|
|
|
|
throw new PackProtocolException(MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, id.name()), notFound); |
|
|
|
|
|
|
|
} finally { |
|
|
|
|
|
|
|
q.release(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void want(RevObject obj) { |
|
|
|
|
|
|
|
if (!obj.has(WANT)) { |
|
|
|
|
|
|
|
obj.add(WANT); |
|
|
|
|
|
|
|
wantAll.add(obj); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void checkNotAdvertisedWants(List<RevCommit> notAdvertisedWants) |
|
|
|
throws MissingObjectException, IncorrectObjectTypeException, IOException { |
|
|
|
throws MissingObjectException, IncorrectObjectTypeException, IOException { |
|
|
|
// Walk the requested commits back to the advertised commits.
|
|
|
|
// Walk the requested commits back to the advertised commits.
|
|
|
|
// If any commit exists, a branch was deleted or rewound and
|
|
|
|
// If any commit exists, a branch was deleted or rewound and
|
|
|
@ -960,15 +946,8 @@ public class UploadPack { |
|
|
|
// If the requested commit is merged into an advertised branch
|
|
|
|
// If the requested commit is merged into an advertised branch
|
|
|
|
// it will be marked UNINTERESTING and no commits return.
|
|
|
|
// it will be marked UNINTERESTING and no commits return.
|
|
|
|
|
|
|
|
|
|
|
|
for (RevObject o : notAdvertisedWants) { |
|
|
|
for (RevCommit c : notAdvertisedWants) |
|
|
|
if (!(o instanceof RevCommit)) { |
|
|
|
walk.markStart(c); |
|
|
|
throw new PackProtocolException(MessageFormat.format( |
|
|
|
|
|
|
|
JGitText.get().wantNotValid, |
|
|
|
|
|
|
|
notAdvertisedWants.iterator().next().name())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
walk.markStart((RevCommit) o); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (ObjectId id : advertised) { |
|
|
|
for (ObjectId id : advertised) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
walk.markUninteresting(walk.parseCommit(id)); |
|
|
|
walk.markUninteresting(walk.parseCommit(id)); |
|
|
|