Merge "Fix group suggestions when adding a group to groups"
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 0123724..771e323 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -204,8 +204,8 @@
Permissions can be set on a single reference name to match one
branch (e.g. `refs/heads/master`), or on a reference namespace
(e.g. `+refs/heads/*+`) to match any branch starting with that
-prefix. So a permission with `+refs/heads/*+` will match
-`refs/heads/master` and `refs/heads/experimental`, etc.
+prefix. So a permission with `+refs/heads/*+` will match all of
+`refs/heads/master`, `refs/heads/experimental`, `refs/heads/release/1.0` etc.
Reference names can also be described with a regular expression
by prefixing the reference name with `^`. For example
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/RestSession.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/RestSession.java
index 4c8ba42..9c59e10 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/RestSession.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/RestSession.java
@@ -54,6 +54,10 @@
return execute(get);
}
+ public RestResponse head(String endPoint) throws IOException {
+ return execute(Request.Head(url + "/a" + endPoint));
+ }
+
public RestResponse put(String endPoint) throws IOException {
return put(endPoint, null);
}
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
index 20f9b82..1864c56 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
@@ -280,6 +280,9 @@
/** ID number of the first patch set in a change. */
public static final int INITIAL_PATCH_SET_ID = 1;
+ /** Change-Id pattern. */
+ public static final String CHANGE_ID_PATTERN = "^[iI][0-9a-f]{4,}.*$";
+
/**
* Current state within the basic workflow of the change.
*
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
index 5e84fd3..74411ad 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.git.validators;
+import static com.google.gerrit.reviewdb.client.Change.CHANGE_ID_PATTERN;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CHANGES;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
@@ -61,6 +62,7 @@
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
+import java.util.regex.Pattern;
public class CommitValidators {
private static final Logger log = LoggerFactory
@@ -182,6 +184,27 @@
}
public static class ChangeIdValidator implements CommitValidationListener {
+ private static final int SHA1_LENGTH = 7;
+ private static final String CHANGE_ID_PREFIX =
+ FooterConstants.CHANGE_ID.getName() + ":";
+ private static final String MISSING_CHANGE_ID_MSG =
+ "[%s] missing "
+ + FooterConstants.CHANGE_ID.getName()
+ + " in commit message footer";
+ private static final String MISSING_SUBJECT_MSG =
+ "[%s] missing subject; "
+ + FooterConstants.CHANGE_ID.getName()
+ + " must be in commit message footer";
+ private static final String MULTIPLE_CHANGE_ID_MSG =
+ "[%s] multiple "
+ + FooterConstants.CHANGE_ID.getName()
+ + " lines in commit message footer";
+ private static final String INVALID_CHANGE_ID_MSG =
+ "[%s] invalid "
+ + FooterConstants.CHANGE_ID.getName() +
+ " line format in commit message footer";
+ private static final Pattern CHANGE_ID = Pattern.compile(CHANGE_ID_PATTERN);
+
private final ProjectControl projectControl;
private final String canonicalWebUrl;
private final String installCommitMsgHookCommand;
@@ -200,63 +223,62 @@
@Override
public List<CommitValidationMessage> onCommitReceived(
CommitReceivedEvent receiveEvent) throws CommitValidationException {
- final List<String> idList = receiveEvent.commit.getFooterLines(
- FooterConstants.CHANGE_ID);
-
+ RevCommit commit = receiveEvent.commit;
List<CommitValidationMessage> messages = new LinkedList<>();
+ List<String> idList = commit.getFooterLines(FooterConstants.CHANGE_ID);
+ String sha1 = commit.abbreviate(SHA1_LENGTH).name();
if (idList.isEmpty()) {
if (projectControl.getProjectState().isRequireChangeID()) {
- String shortMsg = receiveEvent.commit.getShortMessage();
- String changeIdPrefix = FooterConstants.CHANGE_ID.getName() + ":";
- if (shortMsg.startsWith(changeIdPrefix)
- && shortMsg.substring(changeIdPrefix.length()).trim()
- .matches("^I[0-9a-f]{8,}.*$")) {
- throw new CommitValidationException(
- "missing subject; Change-Id must be in commit message footer");
- } else {
- String errMsg = "missing Change-Id in commit message footer";
- messages.add(getMissingChangeIdErrorMsg(
- errMsg, receiveEvent.commit));
- throw new CommitValidationException(errMsg, messages);
+ String shortMsg = commit.getShortMessage();
+ if (shortMsg.startsWith(CHANGE_ID_PREFIX)
+ && CHANGE_ID.matcher(shortMsg.substring(
+ CHANGE_ID_PREFIX.length()).trim()).matches()) {
+ String errMsg = String.format(MISSING_SUBJECT_MSG, sha1);
+ throw new CommitValidationException(errMsg);
}
- }
- } else if (idList.size() > 1) {
- throw new CommitValidationException(
- "multiple Change-Id lines in commit message footer", messages);
- } else {
- final String v = idList.get(idList.size() - 1).trim();
- if (!v.matches("^I[0-9a-f]{8,}.*$")) {
- final String errMsg =
- "missing or invalid Change-Id line format in commit message footer";
- messages.add(
- getMissingChangeIdErrorMsg(errMsg, receiveEvent.commit));
+ String errMsg = String.format(MISSING_CHANGE_ID_MSG, sha1);
+ messages.add(getMissingChangeIdErrorMsg(errMsg, commit));
throw new CommitValidationException(errMsg, messages);
}
+ } else if (idList.size() > 1) {
+ String errMsg = String.format(
+ MULTIPLE_CHANGE_ID_MSG, sha1);
+ throw new CommitValidationException(errMsg, messages);
+ }
+ String v = idList.get(idList.size() - 1).trim();
+ if (!CHANGE_ID.matcher(v).matches()) {
+ String errMsg = String.format(INVALID_CHANGE_ID_MSG, sha1);
+ messages.add(
+ getMissingChangeIdErrorMsg(errMsg, receiveEvent.commit));
+ throw new CommitValidationException(errMsg, messages);
}
return Collections.emptyList();
}
private CommitValidationMessage getMissingChangeIdErrorMsg(
final String errMsg, final RevCommit c) {
- final String changeId = "Change-Id:";
StringBuilder sb = new StringBuilder();
sb.append("ERROR: ").append(errMsg);
- if (c.getFullMessage().indexOf(changeId) >= 0) {
+ if (c.getFullMessage().indexOf(CHANGE_ID_PREFIX) >= 0) {
String[] lines = c.getFullMessage().trim().split("\n");
String lastLine = lines.length > 0 ? lines[lines.length - 1] : "";
- if (lastLine.indexOf(changeId) == -1) {
+ if (lastLine.indexOf(CHANGE_ID_PREFIX) == -1) {
sb.append('\n');
sb.append('\n');
- sb.append("Hint: A potential Change-Id was found, but it was not in the ");
+ sb.append("Hint: A potential ");
+ sb.append(FooterConstants.CHANGE_ID.getName());
+ sb.append("Change-Id was found, but it was not in the ");
sb.append("footer (last paragraph) of the commit message.");
}
}
sb.append('\n');
sb.append('\n');
- sb.append("Hint: To automatically insert Change-Id, install the hook:\n");
+ sb.append("Hint: To automatically insert ");
+ sb.append(FooterConstants.CHANGE_ID.getName());
+ sb.append(", install the hook:\n");
sb.append(getCommitMessageHookInstallationHint());
sb.append('\n');
sb.append("And then amend the commit:\n");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index d92c2b2..590be32 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.change;
+import static com.google.gerrit.reviewdb.client.Change.CHANGE_ID_PATTERN;
import static com.google.gerrit.server.query.change.ChangeData.asChanges;
import com.google.common.annotations.VisibleForTesting;
@@ -94,8 +95,7 @@
}
private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");
- private static final Pattern PAT_CHANGE_ID =
- Pattern.compile("^[iI][0-9a-f]{4,}.*$");
+ private static final Pattern PAT_CHANGE_ID = Pattern.compile(CHANGE_ID_PATTERN);
private static final Pattern DEF_CHANGE = Pattern.compile(
"^(?:[1-9][0-9]*|(?:[^~]+~[^~]+~)?[iI][0-9a-f]{4,}.*)$");