for (;;) {
RevObject obj;
try {
obj = q.next();
} 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;
}
if (obj == null)
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;
haveCnt++;
if (obj instanceof RevCommit) {
RevCommit c = (RevCommit) obj;
if (oldestTime == 0 || c.getCommitTime() < oldestTime)
oldestTime = c.getCommitTime();
}
if (obj.has(PEER_HAS))
continue;
obj.add(PEER_HAS);
if (obj instanceof RevCommit)
((RevCommit) obj).carry(PEER_HAS);
addCommonBase(obj);
// If both sides have the same object; let the client know.
//
switch (multiAck) {
case OFF:
if (commonBase.size() == 1)
pckOut.writeString("ACK " + obj.name() + "\n");
break;
case CONTINUE:
pckOut.writeString("ACK " + obj.name() + " continue\n");
break;
case DETAILED:
pckOut.writeString("ACK " + obj.name() + " common\n");
break;
}
}
} finally {
q.release();
}
// 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;
// If we don't have one of the objects but we're also willing to
// create a pack at this point, let the client know so it stops
// telling us about its history.
//
boolean didOkToGiveUp = false;
if (0 < missCnt) {
for (int i = peerHas.size() - 1; i >= 0; i--) {
ObjectId id = peerHas.get(i);
if (walk.lookupOrNull(id) == null) {
didOkToGiveUp = true;
if (okToGiveUp()) {
switch (multiAck) {
case OFF:
break;
case CONTINUE:
pckOut.writeString("ACK " + id.name() + " continue\n");
break;
case DETAILED:
pckOut.writeString("ACK " + id.name() + " ready\n");
sentReady = true;
break;
}
}
break;
}
}
}
if (multiAck == MultiAck.DETAILED && !didOkToGiveUp && okToGiveUp()) {
ObjectId id = peerHas.get(peerHas.size() - 1);
sentReady = true;
pckOut.writeString("ACK " + id.name() + " ready\n");
sentReady = true;
}
preUploadHook.onEndNegotiateRound(this, wantAll, haveCnt, missCnt, sentReady);
peerHas.clear();