Add 'CherryPickOf' field for a change

After a change is created or updated using the 'cherry-pick'
functionality, this field will contain the source change number
and the patchset. Having this field helps us identify changes
where actual dev time was spent on by filtering out propagated
changes. This is especially useful for organizations wanting to
generate cost metrics.

Change-Id: I782a56aa52c52670ec74fabb713fe47ecba24de1
This commit is contained in:
Kaushik Lingarkar
2019-11-12 13:53:29 -08:00
committed by Kaushik Lingarkar
parent 8b457aeb17
commit 4a711eda84
33 changed files with 413 additions and 12 deletions

View File

@@ -42,6 +42,7 @@ import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.NotifyResolver;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.change.SetCherryPickOp;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -102,6 +103,7 @@ public class CherryPickChange {
private final Provider<IdentifiedUser> user;
private final ChangeInserter.Factory changeInserterFactory;
private final PatchSetInserter.Factory patchSetInserterFactory;
private final SetCherryPickOp.Factory setCherryPickOfFactory;
private final MergeUtil.Factory mergeUtilFactory;
private final ChangeNotes.Factory changeNotesFactory;
private final ProjectCache projectCache;
@@ -117,6 +119,7 @@ public class CherryPickChange {
Provider<IdentifiedUser> user,
ChangeInserter.Factory changeInserterFactory,
PatchSetInserter.Factory patchSetInserterFactory,
SetCherryPickOp.Factory setCherryPickOfFactory,
MergeUtil.Factory mergeUtilFactory,
ChangeNotes.Factory changeNotesFactory,
ProjectCache projectCache,
@@ -129,6 +132,7 @@ public class CherryPickChange {
this.user = user;
this.changeInserterFactory = changeInserterFactory;
this.patchSetInserterFactory = patchSetInserterFactory;
this.setCherryPickOfFactory = setCherryPickOfFactory;
this.mergeUtilFactory = mergeUtilFactory;
this.changeNotesFactory = changeNotesFactory;
this.projectCache = projectCache;
@@ -374,7 +378,13 @@ public class CherryPickChange {
dest.project(),
destChanges.get(0).getId().get()));
}
changeId = insertPatchSet(bu, git, destChanges.get(0).notes(), cherryPickCommit);
changeId =
insertPatchSet(
bu,
git,
destChanges.get(0).notes(),
cherryPickCommit,
sourceChange.currentPatchSetId());
} else {
// Change key not found on destination branch. We can create a new
// change.
@@ -457,13 +467,22 @@ public class CherryPickChange {
}
private Change.Id insertPatchSet(
BatchUpdate bu, Repository git, ChangeNotes destNotes, CodeReviewCommit cherryPickCommit)
BatchUpdate bu,
Repository git,
ChangeNotes destNotes,
CodeReviewCommit cherryPickCommit,
PatchSet.Id sourcePatchSetId)
throws IOException {
Change destChange = destNotes.getChange();
PatchSet.Id psId = ChangeUtil.nextPatchSetId(git, destChange.currentPatchSetId());
PatchSetInserter inserter = patchSetInserterFactory.create(destNotes, psId, cherryPickCommit);
inserter.setMessage("Uploaded patch set " + inserter.getPatchSetId().get() + ".");
bu.addOp(destChange.getId(), inserter);
if (destChange.getCherryPickOf() == null
|| !destChange.getCherryPickOf().equals(sourcePatchSetId)) {
SetCherryPickOp cherryPickOfUpdater = setCherryPickOfFactory.create(sourcePatchSetId);
bu.addOp(destChange.getId(), cherryPickOfUpdater);
}
return destChange.getId();
}
@@ -483,6 +502,7 @@ public class CherryPickChange {
ChangeInserter ins = changeInserterFactory.create(changeId, cherryPickCommit, refName);
ins.setRevertOf(revertOf);
BranchNameKey sourceBranch = sourceChange == null ? null : sourceChange.getDest();
PatchSet.Id sourcePatchSetId = sourceChange == null ? null : sourceChange.currentPatchSetId();
ins.setMessage(
revertOf == null
? messageForDestinationChange(
@@ -490,6 +510,7 @@ public class CherryPickChange {
: "Uploaded patch set 1.") // For revert commits, the message should not include
// cherry-pick information.
.setTopic(topic)
.setCherryPickOf(sourcePatchSetId)
.setWorkInProgress(
(sourceChange != null && sourceChange.isWorkInProgress())
|| !cherryPickCommit.getFilesWithGitConflicts().isEmpty());

View File

@@ -40,6 +40,7 @@ import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.change.RebaseChangeOp;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.SetAssigneeOp;
import com.google.gerrit.server.change.SetCherryPickOp;
import com.google.gerrit.server.change.SetHashtagsOp;
import com.google.gerrit.server.change.SetPrivateOp;
import com.google.gerrit.server.change.WorkInProgressOp;
@@ -201,6 +202,7 @@ public class Module extends RestApiModule {
factory(RebaseChangeOp.Factory.class);
factory(ReviewerResource.Factory.class);
factory(SetAssigneeOp.Factory.class);
factory(SetCherryPickOp.Factory.class);
factory(SetHashtagsOp.Factory.class);
factory(SetPrivateOp.Factory.class);
factory(WorkInProgressOp.Factory.class);