Automatically close changes when pushing into a branch with Change-Id

If new commits are being directly pushed into the branch and their
messages contain Change-Id tags which correspond to an open change
on our server in this project, we should tag that change as closed
by marking the final commit as a replacement commit and updating
the change.

Change-Id: Ieb914afddedca8f21c39a8ba5711bbef6d6dd43c
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-08-21 17:58:09 -07:00
parent 222834a0dd
commit ea9121f6c0
2 changed files with 42 additions and 7 deletions

View File

@@ -57,6 +57,9 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
@Query("WHERE open = true AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
ResultSet<Change> allOpenNext(String sortKey, int limit) throws OrmException;
@Query("WHERE open = true AND dest.projectName = ?")
ResultSet<Change> byProjectOpenAll(Project.NameKey p) throws OrmException;
@Query("WHERE open = true AND dest.projectName = ? AND sortKey > ?"
+ " ORDER BY sortKey LIMIT ?")
ResultSet<Change> byProjectOpenPrev(Project.NameKey p, String sortKey,

View File

@@ -863,12 +863,12 @@ final class Receive extends AbstractGitCommand {
}
}
private void doReplace(final ReplaceRequest request) throws IOException,
OrmException {
private PatchSet.Id doReplace(final ReplaceRequest request)
throws IOException, OrmException {
final RevCommit c = request.newCommit;
rp.getRevWalk().parseBody(c);
if (!validCommitter(request.cmd, c)) {
return;
return null;
}
final Account.Id me = currentUser.getAccountId();
@@ -1080,6 +1080,7 @@ final class Receive extends AbstractGitCommand {
}
}
sendMergedEmail(result);
return result != null ? result.info.getKey() : null;
}
private void insertDummyApproval(final ReplaceResult result,
@@ -1245,12 +1246,35 @@ final class Receive extends AbstractGitCommand {
rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
}
final Map<ObjectId, Ref> changes = changeRefsById();
final Map<ObjectId, Ref> byCommit = changeRefsById();
final Map<Change.Key, Change.Id> byKey = openChangesByKey();
final List<ReplaceRequest> toClose = new ArrayList<ReplaceRequest>();
RevCommit c;
while ((c = rw.next()) != null) {
Ref r = changes.get(c.copy());
if (r != null) {
closeChange(cmd, PatchSet.Id.fromRef(r.getName()));
final Ref ref = byCommit.get(c.copy());
if (ref != null) {
closeChange(cmd, PatchSet.Id.fromRef(ref.getName()));
continue;
}
rw.parseBody(c);
for (final String changeId : c.getFooterLines(CHANGE_ID)) {
final Change.Id onto = byKey.get(new Change.Key(changeId));
if (onto != null) {
toClose.add(new ReplaceRequest(onto, c, cmd));
break;
}
}
}
for (final ReplaceRequest req : toClose) {
final PatchSet.Id psi = doReplace(req);
if (psi != null) {
closeChange(req.cmd, psi);
} else {
log.warn("Replacement of Change-Id " + req.ontoChange
+ " with commit " + req.newCommit.name()
+ " did not import the new patch set.");
}
}
} catch (IOException e) {
@@ -1307,6 +1331,14 @@ final class Receive extends AbstractGitCommand {
return refsById;
}
private Map<Change.Key, Change.Id> openChangesByKey() throws OrmException {
final Map<Change.Key, Change.Id> r = new HashMap<Change.Key, Change.Id>();
for (Change c : db.changes().byProjectOpenAll(proj.getNameKey())) {
r.put(c.getKey(), c.getId());
}
return r;
}
private void markChangeMergedByPush(final ReviewDb db, final Transaction txn,
final ReplaceResult result) throws OrmException {
final Change change = result.change;