Add options to refs/for/ magic branch syntax

Git doesn't want to modify the network protocol to support passing
data from the git push client to the server. Work around this by
embedding option data into a new style of reference specification:

  refs/for/master%r=alice,cc=bob,cc=charlie,topic=options

is now parsed by the server as:

  - set topic to "options"
  - CC charlie and bob
  - add reviewer alice
  - for branch refs/heads/master

If % is used the "extra information" after the branch name is
parsed as options with args4j. Each option is delimited by ",".

Selecting publish vs. draft should be done with options draft or
publish, appearing anywhere in the refspec after the % marker:

  refs/for/master%draft
  refs/for/master%draft,r=alice
  refs/for/master%r=alice,draft
  refs/for/master%r=alice,publish

Change-Id: I895bd1218c2099b5b45cac943039bbd12565370c
This commit is contained in:
Shawn Pearce
2013-02-24 18:01:27 -08:00
parent 7882a0da1a
commit 69928a6d06
7 changed files with 157 additions and 100 deletions

View File

@@ -36,6 +36,7 @@ package com.google.gerrit.util.cli;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.inject.Inject;
import com.google.inject.Injector;
@@ -77,6 +78,9 @@ public class CmdLineParser {
private final Injector injector;
private final MyParser parser;
@SuppressWarnings("rawtypes")
private Map<String, OptionHandler> options;
/**
* Creates a new command line owner that parses arguments/options and set them
* into the given object.
@@ -225,16 +229,9 @@ public class CmdLineParser {
throws CmdLineException {
List<String> tmp = Lists.newArrayListWithCapacity(2 * params.size());
for (final String key : params.keySet()) {
String name = key;
if (!name.startsWith("-")) {
if (name.length() == 1) {
name = "-" + name;
} else {
name = "--" + name;
}
}
String name = makeOption(key);
if (findHandler(name) instanceof BooleanOptionHandler) {
if (isBoolean(name)) {
boolean on = false;
for (String value : params.get(key)) {
on = toBoolean(key, value);
@@ -252,22 +249,44 @@ public class CmdLineParser {
parser.parseArgument(tmp.toArray(new String[tmp.size()]));
}
public boolean isBoolean(String name) {
return findHandler(makeOption(name)) instanceof BooleanOptionHandler;
}
private String makeOption(String name) {
if (!name.startsWith("-")) {
if (name.length() == 1) {
name = "-" + name;
} else {
name = "--" + name;
}
}
return name;
}
@SuppressWarnings("rawtypes")
private OptionHandler findHandler(String name) {
for (OptionHandler handler : parser.options) {
if (options == null) {
options = index(parser.options);
}
return options.get(name);
}
@SuppressWarnings("rawtypes")
private static Map<String, OptionHandler> index(List<OptionHandler> in) {
Map<String, OptionHandler> m = Maps.newHashMap();
for (OptionHandler handler : in) {
if (handler.option instanceof NamedOptionDef) {
NamedOptionDef def = (NamedOptionDef) handler.option;
if (name.equals(def.name())) {
return handler;
}
for (String alias : def.aliases()) {
if (name.equals(alias)) {
return handler;
if (!def.isArgument()) {
m.put(def.name(), handler);
for (String alias : def.aliases()) {
m.put(alias, handler);
}
}
}
}
return null;
return m;
}
private boolean toBoolean(String name, String value) throws CmdLineException {