Use changeRefsById to track existing revisions

Most processing paths build up the same sets of ObjectIds, by scanning
through all refs/changes/ and copying them into a temporary set.

Reuse an existing map that is cached after first use and also supports
the autoCloseChanges code path.

It is unlikely that both refs/for/* and refs/heads/* are pushed at the
same time and need to use the map, so there may not be very much reuse
of the data structure within a single execution of ReceiveCommits.

This commit mostly shrinks the code a bit smaller by removing a very
simple redundant processing path.

Change-Id: If2ffd544c821d184593d729fe4ebef77de1860ee
This commit is contained in:
Shawn Pearce
2014-10-17 14:59:00 -07:00
parent e154dbd9f6
commit 2ffd2cb83f

View File

@@ -1467,7 +1467,6 @@ public class ReceiveCommits {
walk.sort(RevSort.TOPO); walk.sort(RevSort.TOPO);
walk.sort(RevSort.REVERSE, true); walk.sort(RevSort.REVERSE, true);
try { try {
Set<ObjectId> existing = Sets.newHashSet();
walk.markStart(walk.parseCommit(magicBranch.cmd.getNewId())); walk.markStart(walk.parseCommit(magicBranch.cmd.getNewId()));
if (magicBranch.baseCommit != null) { if (magicBranch.baseCommit != null) {
for (RevCommit c : magicBranch.baseCommit) { for (RevCommit c : magicBranch.baseCommit) {
@@ -1480,10 +1479,10 @@ public class ReceiveCommits {
} else { } else {
markHeadsAsUninteresting( markHeadsAsUninteresting(
walk, walk,
existing,
magicBranch.ctl != null ? magicBranch.ctl.getRefName() : null); magicBranch.ctl != null ? magicBranch.ctl.getRefName() : null);
} }
Set<ObjectId> existing = changeRefsById().keySet();
List<ChangeLookup> pending = Lists.newArrayList(); List<ChangeLookup> pending = Lists.newArrayList();
final Set<Change.Key> newChangeIds = new HashSet<>(); final Set<Change.Key> newChangeIds = new HashSet<>();
final int maxBatchChanges = final int maxBatchChanges =
@@ -1602,23 +1601,15 @@ public class ReceiveCommits {
} }
} }
private void markHeadsAsUninteresting( private void markHeadsAsUninteresting(RevWalk rw, @Nullable String forRef) {
final RevWalk walk,
Set<ObjectId> existing,
@Nullable String forRef) {
for (Ref ref : allRefs.values()) { for (Ref ref : allRefs.values()) {
if (ref.getObjectId() == null) { if ((ref.getName().startsWith(R_HEADS) || ref.getName().equals(forRef))
continue; && ref.getObjectId() != null) {
} else if (ref.getName().startsWith(REFS_CHANGES)) {
existing.add(ref.getObjectId());
} else if (ref.getName().startsWith(R_HEADS)
|| (forRef != null && forRef.equals(ref.getName()))) {
try { try {
walk.markUninteresting(walk.parseCommit(ref.getObjectId())); rw.markUninteresting(rw.parseCommit(ref.getObjectId()));
} catch (IOException e) { } catch (IOException e) {
log.warn(String.format("Invalid ref %s in %s", log.warn(String.format("Invalid ref %s in %s",
ref.getName(), project.getName()), e); ref.getName(), project.getName()), e);
continue;
} }
} }
} }
@@ -2287,12 +2278,11 @@ public class ReceiveCommits {
walk.reset(); walk.reset();
walk.sort(RevSort.NONE); walk.sort(RevSort.NONE);
try { try {
Set<ObjectId> existing = Sets.newHashSet();
walk.markStart(walk.parseCommit(cmd.getNewId())); walk.markStart(walk.parseCommit(cmd.getNewId()));
markHeadsAsUninteresting(walk, existing, cmd.getRefName()); markHeadsAsUninteresting(walk, cmd.getRefName());
RevCommit c; Set<ObjectId> existing = changeRefsById().keySet();
while ((c = walk.next()) != null) { for (RevCommit c; (c = walk.next()) != null;) {
if (existing.contains(c)) { if (existing.contains(c)) {
continue; continue;
} else if (!validCommit(ctl, cmd, c)) { } else if (!validCommit(ctl, cmd, c)) {