Accept refs/for/ options via git push -o
Push options are a capability in the Git protocol to transport arbitrary strings (example usage: topic strings) to the server through command line flags rather than by the existing Gerrit-specific magic branch "refs/for/master%..." convention. For example with Git >= 2.10: git push -o r=email -o topic=fix-bug42 origin HEAD:refs/for/master can now be used instead of: git push origin HEAD:refs/for/master%r=email,topic=fix-bug42 Change-Id: I44e7214b9342d461b07c4b6dd638970cf5fb622f Signed-off-by: Dan Wang <dwwang@google.com>
This commit is contained in:
committed by
Jonathan Nieder
parent
8f23c50d6f
commit
22f5360b59
@@ -42,6 +42,7 @@ import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.LinkedListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
@@ -315,6 +316,8 @@ public class ReceiveCommits {
|
||||
private final RequestId receiveId;
|
||||
private MagicBranchInput magicBranch;
|
||||
private boolean newChangeForAllNotInTarget;
|
||||
private final ListMultimap<String, String> pushOptions =
|
||||
LinkedListMultimap.create();
|
||||
|
||||
private List<CreateRequest> newChanges = Collections.emptyList();
|
||||
private final Map<Change.Id, ReplaceRequest> replaceByChange =
|
||||
@@ -490,6 +493,7 @@ public class ReceiveCommits {
|
||||
advHooks.add(new HackPushNegotiateHook());
|
||||
rp.setAdvertiseRefsHook(AdvertiseRefsHookChain.newChain(advHooks));
|
||||
rp.setPostReceiveHook(lazyPostReceive.get());
|
||||
rp.setAllowPushOptions(true);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
@@ -915,6 +919,18 @@ public class ReceiveCommits {
|
||||
}
|
||||
|
||||
private void parseCommands(Collection<ReceiveCommand> commands) {
|
||||
List<String> optionList = rp.getPushOptions();
|
||||
if (optionList != null) {
|
||||
for (String option : optionList) {
|
||||
int e = option.indexOf('=');
|
||||
if (e > 0) {
|
||||
pushOptions.put(option.substring(0, e), option.substring(e + 1));
|
||||
} else {
|
||||
pushOptions.put(option, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logDebug("Parsing {} commands", commands.size());
|
||||
for (ReceiveCommand cmd : commands) {
|
||||
if (cmd.getResult() != NOT_ATTEMPTED) {
|
||||
@@ -1305,14 +1321,14 @@ public class ReceiveCommits {
|
||||
return new MailRecipients(reviewer, cc);
|
||||
}
|
||||
|
||||
String parse(CmdLineParser clp, Repository repo, Set<String> refs)
|
||||
throws CmdLineException {
|
||||
String parse(CmdLineParser clp, Repository repo, Set<String> refs,
|
||||
ListMultimap<String, String> pushOptions) throws CmdLineException {
|
||||
String ref = RefNames.fullName(
|
||||
MagicBranch.getDestBranchName(cmd.getRefName()));
|
||||
|
||||
ListMultimap<String, String> options = LinkedListMultimap.create(pushOptions);
|
||||
int optionStart = ref.indexOf('%');
|
||||
if (0 < optionStart) {
|
||||
ListMultimap<String, String> options = LinkedListMultimap.create();
|
||||
for (String s : COMMAS.split(ref.substring(optionStart + 1))) {
|
||||
int e = s.indexOf('=');
|
||||
if (0 < e) {
|
||||
@@ -1321,10 +1337,13 @@ public class ReceiveCommits {
|
||||
options.put(s, "");
|
||||
}
|
||||
}
|
||||
clp.parseOptionMap(options);
|
||||
ref = ref.substring(0, optionStart);
|
||||
}
|
||||
|
||||
if (!options.isEmpty()) {
|
||||
clp.parseOptionMap(options);
|
||||
}
|
||||
|
||||
// Split the destination branch by branch and topic. The topic
|
||||
// suffix is entirely optional, so it might not even exist.
|
||||
String head = readHEAD(repo);
|
||||
@@ -1347,6 +1366,19 @@ public class ReceiveCommits {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unmodifiable view of the pushOptions.
|
||||
* <p>
|
||||
* The collection is empty if the client does not support push options, or if
|
||||
* the client did not send any options.
|
||||
*
|
||||
* @return an unmodifiable view of pushOptions.
|
||||
*/
|
||||
@Nullable
|
||||
public ListMultimap<String, String> getPushOptions() {
|
||||
return ImmutableListMultimap.copyOf(pushOptions);
|
||||
}
|
||||
|
||||
private void parseMagicBranch(ReceiveCommand cmd) {
|
||||
// Permit exactly one new change request per push.
|
||||
if (magicBranch != null) {
|
||||
@@ -1362,8 +1394,10 @@ public class ReceiveCommits {
|
||||
String ref;
|
||||
CmdLineParser clp = optionParserFactory.create(magicBranch);
|
||||
magicBranch.clp = clp;
|
||||
|
||||
try {
|
||||
ref = magicBranch.parse(clp, repo, rp.getAdvertisedRefs().keySet());
|
||||
ref = magicBranch.parse(
|
||||
clp, repo, rp.getAdvertisedRefs().keySet(), pushOptions);
|
||||
} catch (CmdLineException e) {
|
||||
if (!clp.wasHelpRequestedByOption()) {
|
||||
logDebug("Invalid branch syntax");
|
||||
|
||||
Reference in New Issue
Block a user