Allow opening new changes on existing commits

The %base argument can be used with refs/for/ to identify a specific
revision the server should start to look for new commits at. Any
commits in the range $base..$tip will be opened as a new change,
even if the commit already has another change on a different branch.

Change-Id: Ic2ea9b7c53df3b99d29043cd6a6fd68214f3398f
This commit is contained in:
Shawn Pearce 2013-04-22 11:50:23 -07:00
parent c36a0e01d2
commit 5d8a290d06
2 changed files with 45 additions and 5 deletions

View File

@ -353,6 +353,20 @@ If the merge fails the change stays open, but when pushing a new patch
set the merge can be reattempted by using `%submit` again. set the merge can be reattempted by using `%submit` again.
[[base]]
Selecting Merge Base
~~~~~~~~~~~~~~~~~~~~
By default new changes are opened only for new unique commits
that have never before been seen by the Gerrit server. Clients
may override that behavior and force new changes to be created
by setting the merge base SHA-1 using the '%base' argument:
====
git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/master%base=$(git rev-parse origin/master)
====
repo upload repo upload
----------- -----------

View File

@ -1003,6 +1003,10 @@ public class ReceiveCommits {
RefControl ctl; RefControl ctl;
Set<Account.Id> reviewer = Sets.newLinkedHashSet(); Set<Account.Id> reviewer = Sets.newLinkedHashSet();
Set<Account.Id> cc = Sets.newLinkedHashSet(); Set<Account.Id> cc = Sets.newLinkedHashSet();
RevCommit baseCommit;
@Option(name = "--base", metaVar = "BASE", usage = "merge base of changes")
ObjectId base;
@Option(name = "--topic", metaVar = "NAME", usage = "attach topic to changes") @Option(name = "--topic", metaVar = "NAME", usage = "attach topic to changes")
String topic; String topic;
@ -1147,13 +1151,31 @@ public class ReceiveCommits {
reject(cmd, "submit not allowed"); reject(cmd, "submit not allowed");
} }
RevWalk walk = rp.getRevWalk();
if (magicBranch.base != null) {
try {
magicBranch.baseCommit = walk.parseCommit(magicBranch.base);
} catch (IncorrectObjectTypeException notCommit) {
reject(cmd, "base must be a commit");
return;
} catch (MissingObjectException e) {
reject(cmd, "base not found");
return;
} catch (IOException e) {
log.warn(String.format(
"Project %s cannot read %s",
project.getName(), magicBranch.base.name()), e);
reject(cmd, "internal server error");
return;
}
}
// Validate that the new commits are connected with the target // Validate that the new commits are connected with the target
// branch. If they aren't, we want to abort. We do this check by // branch. If they aren't, we want to abort. We do this check by
// looking to see if we can compute a merge base between the new // looking to see if we can compute a merge base between the new
// commits and the target branch head. // commits and the target branch head.
// //
try { try {
final RevWalk walk = rp.getRevWalk();
final RevCommit tip = walk.parseCommit(magicBranch.cmd.getNewId()); final RevCommit tip = walk.parseCommit(magicBranch.cmd.getNewId());
Ref targetRef = rp.getAdvertisedRefs().get(magicBranch.ctl.getRefName()); Ref targetRef = rp.getAdvertisedRefs().get(magicBranch.ctl.getRefName());
if (targetRef == null || targetRef.getObjectId() == null) { if (targetRef == null || targetRef.getObjectId() == null) {
@ -1283,10 +1305,14 @@ public class ReceiveCommits {
try { try {
Set<ObjectId> existing = Sets.newHashSet(); Set<ObjectId> existing = Sets.newHashSet();
walk.markStart(walk.parseCommit(magicBranch.cmd.getNewId())); walk.markStart(walk.parseCommit(magicBranch.cmd.getNewId()));
markHeadsAsUninteresting( if (magicBranch.baseCommit != null) {
walk, walk.markUninteresting(magicBranch.baseCommit);
existing, } else {
magicBranch.ctl != null ? magicBranch.ctl.getRefName() : null); markHeadsAsUninteresting(
walk,
existing,
magicBranch.ctl != null ? magicBranch.ctl.getRefName() : null);
}
List<ChangeLookup> pending = Lists.newArrayList(); List<ChangeLookup> pending = Lists.newArrayList();
final Set<Change.Key> newChangeIds = new HashSet<Change.Key>(); final Set<Change.Key> newChangeIds = new HashSet<Change.Key>();