Merge "TrivialRebase: Aggregate approvals" into stable-2.6
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 9ef6e13..5e70460 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -134,6 +134,17 @@
members of `Foo` have submit rights on a project, and the members of
`Foo-admin` typically do not need to have such rights.
+[[ldap_groups]]
+LDAP Groups
+-----------
+
+LDAP groups are Account Groups that are maintained inside of your
+LDAP instance. If you are using LDAP to manage your groups they will
+not appear in the Groups list. However you can use them just like
+regular Account Groups by prefixing your group with "ldap/" in the
+Access Control for a project. For example "ldap/foo-project" will
+add the LDAP "foo-project" group to the access list.
+
Project Access Control Lists
----------------------------
diff --git a/Documentation/config-reverseproxy.txt b/Documentation/config-reverseproxy.txt
index 7161c4a..c932c0c 100644
--- a/Documentation/config-reverseproxy.txt
+++ b/Documentation/config-reverseproxy.txt
@@ -28,33 +28,34 @@
Apache 2 Configuration
----------------------
-To run Gerrit behind an Apache server using 'mod_proxy', enable the
+To run Gerrit behind an Apache server we cannot use 'mod_proxy'
+directly, as Gerrit relies on getting unmodified escaped forward
+slashes. Depending on the setting of 'AllowEncodedSlashes',
+'mod_proxy' would either decode encoded slashes, or encode them once
+again. Hence, we resort to using 'mod_rewrite'. To enable the
necessary Apache2 modules:
----
- a2enmod proxy_http
+ a2enmod rewrite
a2enmod ssl ; # optional, needed for HTTPS / SSL
----
-Configure an Apache VirtualHost to proxy to the Gerrit daemon,
-setting the 'ProxyPass' line to use the 'http://' URL configured
-above. Ensure the path of ProxyPass and httpd.listenUrl match,
-or links will redirect to incorrect locations.
+Configure an Apache VirtualHost to proxy to the Gerrit daemon, setting
+the 'RewriteRule' line to use the 'http://' URL configured above.
+Ensure the path of 'RewriteRule' (the part before '$1') and
+httpd.listenUrl match, or links will redirect to incorrect locations.
+
+Note that this configuration allows to pass encoded characters to the
+virtual host, which is potentially dangerous. Be sure to read up on
+this topic and that you understand the risks.
----
<VirtualHost *>
ServerName review.example.com
- ProxyRequests Off
- ProxyVia Off
- ProxyPreserveHost On
-
- <Proxy *>
- Order deny,allow
- Allow from all
- </Proxy>
-
- ProxyPass /r/ http://127.0.0.1:8081/r/
+ AllowEncodedSlashes NoDecode
+ RewriteEngine On
+ RewriteRule ^/r/(.*) http://localhost:8081/r/$1
</VirtualHost>
----
diff --git a/Documentation/user-changeid.txt b/Documentation/user-changeid.txt
index 0b67205..a4224bd 100644
--- a/Documentation/user-changeid.txt
+++ b/Documentation/user-changeid.txt
@@ -10,10 +10,10 @@
Gerrit can automatically associate a new version of a change back
to its original review, even across cherry-picks and rebases.
-To be picked up by Gerrit, a Change-Id line must be in the bottom
-portion (last paragraph) of a commit message, and may be mixed
-together with the Signed-off-by, Acked-by, or other such footers.
-For example:
+To be picked up by Gerrit, a Change-Id line must be in the footer
+(last paragraph) of a commit message, and may be mixed
+together with link:user-signedoffby.html[Signed-off-by], Acked-by,
+or other such lines. For example:
----
$ git log -1
diff --git a/ReleaseNotes/ReleaseNotes-2.6.txt b/ReleaseNotes/ReleaseNotes-2.6.txt
index 4612aaa..15dc7be 100644
--- a/ReleaseNotes/ReleaseNotes-2.6.txt
+++ b/ReleaseNotes/ReleaseNotes-2.6.txt
@@ -430,6 +430,12 @@
HTML thanks to Gson encoding HTML control characters using Unicode
character escapes within JSON strings.
+* Apache reverse proxies need `AllowEncodedSlashes NoDecode`
++
+When Apache is used as a reverse proxy the NoDecode option
+must be set for AllowEncodedSlashes to prevent Apache from
+mangling Gerrit REST API URLs.
+
Project Dashboards
~~~~~~~~~~~~~~~~~~
* link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.6/user-dashboards.html#project-dashboards[
diff --git a/contrib/trivial_rebase.py b/contrib/trivial_rebase.py
index 0a0e510..6254c69 100755
--- a/contrib/trivial_rebase.py
+++ b/contrib/trivial_rebase.py
@@ -159,7 +159,8 @@
git_show_process = subprocess.Popen(git_show_cmd, stdout=subprocess.PIPE)
patch_id_process = subprocess.Popen(patch_id_cmd, stdout=subprocess.PIPE,
stdin=git_show_process.stdout)
- return patch_id_process.communicate()[0]
+ res = patch_id_process.communicate()[0] or '0'
+ return res.split()[0]
def SuExec(self, as_user, cmd):
suexec_cmd = [self.ssh, '-l', "Gerrit Code Review", self.ssh_port_flag, self.port, self.server]
@@ -187,14 +188,10 @@
assert prev_revision, "Previous revision not found"
prev_patch_id = self.GetPatchId(prev_revision)
cur_patch_id = self.GetPatchId(self.commit)
- if not (prev_patch_id and cur_patch_id):
- # Merge commit
- if not prev_patch_id:
- print "GetPatchId failed for commit %s" % (prev_revision)
- if not cur_patch_id:
- print "GetPatchId failed for commit %s" % (self.commit)
+ if prev_patch_id == '0' and cur_patch_id == '0':
+ print "commits %s and %s are both empty or merge commits" % (prev_revision, self.commit)
return
- if cur_patch_id.split()[0] != prev_patch_id.split()[0]:
+ if cur_patch_id != prev_patch_id:
# patch-ids don't match
return
# Patch ids match. This is a trivial rebase.
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
index bc40097..4f4e8a7 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
@@ -125,7 +125,7 @@
}
/**
- * Formats an account as an name and an email address.
+ * Formats an account as a name and an email address.
* <p>
* Example output:
* <ul>
@@ -137,7 +137,7 @@
*/
public static String nameEmail(AccountInfo info) {
String name = info.name();
- if (name == null) {
+ if (name == null || name.trim().isEmpty()) {
name = Gerrit.getConfig().getAnonymousCowardName();
}
@@ -172,7 +172,7 @@
* returns a longer form that includes the email address.
*/
public static String name(AccountInfo ai) {
- if (ai.name() != null) {
+ if (ai.name() != null && !ai.name().trim().isEmpty()) {
return ai.name();
}
String email = ai.email();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
index cba2f0b..f35bd4b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
@@ -348,7 +348,7 @@
void doSave(final AsyncCallback<Account> onSave) {
String newName = canEditFullName() ? nameTxt.getText() : null;
- if ("".equals(newName)) {
+ if (newName != null && newName.trim().isEmpty()) {
newName = null;
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
index 07f25f4..dac0b6a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
@@ -18,7 +18,7 @@
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.groups.GroupMap;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
+import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountScreen;
import com.google.gerrit.client.ui.FilteredUserInterface;
import com.google.gerrit.client.ui.IgnoreOutdatedFilterResultsCallbackWrapper;
@@ -54,6 +54,7 @@
@Override
protected void onLoad() {
super.onLoad();
+ display();
refresh();
}
@@ -62,9 +63,9 @@
: ADMIN_GROUPS + "?filter=" + URL.encodeQueryString(subname));
GroupMap.match(subname,
new IgnoreOutdatedFilterResultsCallbackWrapper<GroupMap>(this,
- new ScreenLoadCallback<GroupMap>(this) {
+ new GerritCallback<GroupMap>() {
@Override
- protected void preDisplay(final GroupMap result) {
+ public void onSuccess(GroupMap result) {
groups.display(result, subname);
groups.finishDisplay();
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
index 6af437c..ee58420 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
@@ -21,7 +21,7 @@
import com.google.gerrit.client.GitwebLink;
import com.google.gerrit.client.projects.ProjectInfo;
import com.google.gerrit.client.projects.ProjectMap;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
+import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.FilteredUserInterface;
import com.google.gerrit.client.ui.HighlightingInlineHyperlink;
import com.google.gerrit.client.ui.IgnoreOutdatedFilterResultsCallbackWrapper;
@@ -63,6 +63,7 @@
@Override
protected void onLoad() {
super.onLoad();
+ display();
refresh();
}
@@ -71,9 +72,9 @@
: ADMIN_PROJECTS + "?filter=" + URL.encodeQueryString(subname));
ProjectMap.match(subname,
new IgnoreOutdatedFilterResultsCallbackWrapper<ProjectMap>(this,
- new ScreenLoadCallback<ProjectMap>(this) {
+ new GerritCallback<ProjectMap>() {
@Override
- protected void preDisplay(final ProjectMap result) {
+ public void onSuccess(ProjectMap result) {
projects.display(result);
}
}));
diff --git a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/container/ConfigurationError.html b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/container/ConfigurationError.html
index 7294012..a7cd489 100644
--- a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/container/ConfigurationError.html
+++ b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/container/ConfigurationError.html
@@ -49,22 +49,16 @@
<VirtualHost <span class='ServerName'>review.example.com</span><span class='ServerPort'>:80</span>>
ServerName <span class='ServerName'>review.example.com</span>
- ProxyRequests Off
- ProxyVia Off
- ProxyPreserveHost On
-
- <Proxy *>
- Order deny,allow
- Allow from all
- </Proxy>
-
<div class='apache_auth'> <Location <span class='ContextPath'>/r</span>/login/>
AuthType Basic
AuthName "Gerrit Code Review"
Require valid-user
...
</Location></div>
- ProxyPass <span class='ContextPath'>/r</span>/ http://...<span class='ContextPath'>/r</span>/
+
+ AllowEncodedSlashes NoDecode
+ RewriteEngine On
+ RewriteRule ^<span class='ContextPath'>/r</span>/(.*) http://...<span class='ContextPath'>/r</span>/$1
</VirtualHost>
</pre>
</body>
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 97af5ac..8abe501 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
@@ -486,7 +486,8 @@
sb.append('\n');
sb.append(changeId).append(" I").append(c.name());
sb.append('\n');
- sb.append("Hint: A potential Change-Id was found, but it was not in the footer of the commit message.");
+ sb.append("Hint: A potential Change-Id was found, but it was not in the ");
+ sb.append("footer (last paragraph) of the commit message.");
}
}
sb.append('\n');
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java
index 244028c..ab70395 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java
@@ -21,6 +21,8 @@
import org.apache.sshd.server.Environment;
+import java.util.List;
+
@CommandMetaData(name = "ls-projects", descr = "List projects visible to the caller")
final class ListProjectsCommand extends BaseCommand {
@Inject
@@ -33,7 +35,8 @@
public void run() throws Exception {
parseCommandLine(impl);
if (!impl.getFormat().isJson()) {
- if (impl.isShowTree() && (impl.getShowBranch() != null)) {
+ List<String> showBranch = impl.getShowBranch();
+ if (impl.isShowTree() && (showBranch != null) && !showBranch.isEmpty()) {
throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible.");
}
if (impl.isShowTree() && impl.isShowDescription()) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ScpCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ScpCommand.java
index 09c25ff..987380f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ScpCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ScpCommand.java
@@ -92,6 +92,7 @@
private void runImp() {
try {
+ readAck();
if (error != null) {
throw error;
}