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 ?") @Query("WHERE open = true AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
ResultSet<Change> allOpenNext(String sortKey, int limit) throws OrmException; 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 > ?" @Query("WHERE open = true AND dest.projectName = ? AND sortKey > ?"
+ " ORDER BY sortKey LIMIT ?") + " ORDER BY sortKey LIMIT ?")
ResultSet<Change> byProjectOpenPrev(Project.NameKey p, String sortKey, 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, private PatchSet.Id doReplace(final ReplaceRequest request)
OrmException { throws IOException, OrmException {
final RevCommit c = request.newCommit; final RevCommit c = request.newCommit;
rp.getRevWalk().parseBody(c); rp.getRevWalk().parseBody(c);
if (!validCommitter(request.cmd, c)) { if (!validCommitter(request.cmd, c)) {
return; return null;
} }
final Account.Id me = currentUser.getAccountId(); final Account.Id me = currentUser.getAccountId();
@@ -1080,6 +1080,7 @@ final class Receive extends AbstractGitCommand {
} }
} }
sendMergedEmail(result); sendMergedEmail(result);
return result != null ? result.info.getKey() : null;
} }
private void insertDummyApproval(final ReplaceResult result, private void insertDummyApproval(final ReplaceResult result,
@@ -1245,12 +1246,35 @@ final class Receive extends AbstractGitCommand {
rw.markUninteresting(rw.parseCommit(cmd.getOldId())); 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; RevCommit c;
while ((c = rw.next()) != null) { while ((c = rw.next()) != null) {
Ref r = changes.get(c.copy()); final Ref ref = byCommit.get(c.copy());
if (r != null) { if (ref != null) {
closeChange(cmd, PatchSet.Id.fromRef(r.getName())); 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) { } catch (IOException e) {
@@ -1307,6 +1331,14 @@ final class Receive extends AbstractGitCommand {
return refsById; 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, private void markChangeMergedByPush(final ReviewDb db, final Transaction txn,
final ReplaceResult result) throws OrmException { final ReplaceResult result) throws OrmException {
final Change change = result.change; final Change change = result.change;