Reuse cached list of existing objects during receive

ReceiveCommits may need to walk through all of the already existing
commits more than once during a push, if the user pushes multiple
branches in a single transaction.  Cache the list (and build it on
demand) to avoid walking through the ref map again.

Instead of walking through the advertised references, walk
through all of the references on the repository.  This considers
other references that may have been hidden from the user by the
VisibleRefFilter, but this isn't really harmful here because that
was already validated inside of ReceivePack.  Using the full set
is however more accurate, and is necessary if the advertised set
is reduced to a subset of refs.

Change-Id: I9eb3a681266cdf46eddbf6e1abb2abb9c7a05556
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2010-12-10 14:42:05 -08:00
parent fba6da8cb2
commit 27b9924173

View File

@@ -161,6 +161,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
private final Map<RevCommit, ReplaceRequest> replaceByCommit =
new HashMap<RevCommit, ReplaceRequest>();
private Collection<ObjectId> existingObjects;
private Map<ObjectId, Ref> refsById;
private String destTopicName;
@@ -808,9 +809,9 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
walk.sort(RevSort.REVERSE, true);
try {
walk.markStart(walk.parseCommit(newChange.getNewId()));
for (final Ref r : rp.getAdvertisedRefs().values()) {
for (ObjectId id : existingObjects()) {
try {
walk.markUninteresting(walk.parseCommit(r.getObjectId()));
walk.markUninteresting(walk.parseCommit(id));
} catch (IOException e) {
continue;
}
@@ -1412,9 +1413,9 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
walk.sort(RevSort.NONE);
try {
walk.markStart(walk.parseCommit(cmd.getNewId()));
for (final Ref r : rp.getAdvertisedRefs().values()) {
for (ObjectId id : existingObjects()) {
try {
walk.markUninteresting(walk.parseCommit(r.getObjectId()));
walk.markUninteresting(walk.parseCommit(id));
} catch (IOException e) {
continue;
}
@@ -1432,6 +1433,17 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
}
}
private Collection<ObjectId> existingObjects() {
if (existingObjects == null) {
Map<String, Ref> refs = repo.getAllRefs();
existingObjects = new ArrayList<ObjectId>(refs.size());
for (Ref r : refs.values()) {
existingObjects.add(r.getObjectId());
}
}
return existingObjects;
}
private boolean validCommit(final RefControl ctl, final ReceiveCommand cmd,
final RevCommit c) throws MissingObjectException, IOException {
rp.getRevWalk().parseBody(c);