Merge "Only handle last value change event for attached change screens"
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index ec64e0b..a3bfe27 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -1134,6 +1134,13 @@
 Below you find a list of capabilities available:
 
 
+[[capability_accessDatabase]]
+Access Database
+~~~~~~~~~~~~~~~
+
+Allow users to access the database using the `gsql` command.
+
+
 [[capability_administrateServer]]
 Administrate Server
 ~~~~~~~~~~~~~~~~~~~
@@ -1196,6 +1203,14 @@
 you need the <<capability_viewCaches,view caches capability>>.
 
 
+[[capability_generateHttpPassword]]
+Generate HTTP Password
+~~~~~~~~~~~~~~~~~~~~~~
+
+Allow the user to generate HTTP passwords for other users.  Typically this would
+be assigned to a non-interactive users group.
+
+
 [[capability_kill]]
 Kill Task
 ~~~~~~~~~
@@ -1251,13 +1266,6 @@
 command, but also to the web UI results pagination size.
 
 
-[[capability_accessDatabase]]
-Access Database
-~~~~~~~~~~~~~~~
-
-Allow users to access the database using the `gsql` command.
-
-
 [[capability_runGC]]
 Run Garbage Collection
 ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/config-reverseproxy.txt b/Documentation/config-reverseproxy.txt
index 0857442..064fe2e 100644
--- a/Documentation/config-reverseproxy.txt
+++ b/Documentation/config-reverseproxy.txt
@@ -28,37 +28,40 @@
 Apache 2 Configuration
 ----------------------
 
-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
+To run Gerrit behind an Apache server using 'mod_proxy', enable the
 necessary Apache2 modules:
 
 ----
-  a2enmod rewrite
+  a2enmod proxy_http
   a2enmod ssl          ; # optional, needed for HTTPS / SSL
 ----
 
-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.
+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.
 
 ----
 	<VirtualHost *>
 	  ServerName review.example.com
 
-	  AllowEncodedSlashes NoDecode
-	  RewriteEngine On
-	  RewriteRule ^/r/(.*) http://localhost:8081/r/$1 [NE,P]
+	  ProxyRequests Off
+	  ProxyVia Off
+	  ProxyPreserveHost On
+
+	  <Proxy *>
+	    Order deny,allow
+	    Allow from all
+	  </Proxy>
+
+	  AllowEncodedSlashes On
+	  ProxyPass /r/ http://127.0.0.1:8081/r/ nocanon
 	</VirtualHost>
 ----
 
+The two options 'AllowEncodedSlashes On' and 'ProxyPass .. nocanon' are required
+since Gerrit 2.6.
+
 SSL
 ~~~
 
@@ -80,6 +83,15 @@
 configure SSL within the server, like controlling how strong of an
 encryption algorithm is required.
 
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+If you are encountering 'Page Not Found' errors when opening the change
+screen, your Apache proxy is very likely decoding the passed URL.
+Make sure to either use 'AllowEncodedSlashes On' together with
+'ProxyPass .. nodecode' or alternatively a 'mod_rewrite' configuration with
+'AllowEncodedSlashes NoDecode' set.
+
 
 Nginx Configuration
 -------------------
@@ -124,6 +136,14 @@
 how to configure SSL within the server, like controlling how strong
 of an encryption algorithm is required.
 
+Troubleshooting
+~~~~~~~~~~~~~~~
+
+If you are encountering 'Page Not Found' errors when opening the change
+screen, your Nginx proxy is very likely decoding the passed URL.
+Make sure to use a 'proxy_pass' URL without any path (esp. no trailing
+'/' after the 'host:port').
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 0169bff..0594d93 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -2531,13 +2531,13 @@
 The `DiffIntralineInfo` entity contains information about intraline edits in a
 file.
 
-The information consists of a list of `<skip length, mark length>` pairs.  Where
-the skip length is the number of characters between between the end of the
-previous edit and the start of this edit. The mark length is the number of
-edited characters following the skip. The start of the edits is from the
-beginning of the related diff content lines.
+The information consists of a list of `<skip length, mark length>` pairs, where
+the skip length is the number of characters between the end of the previous edit
+and the start of this edit, and the mark length is the number of edited characters
+following the skip. The start of the edits is from the beginning of the related
+diff content lines.
 
-Note that the implied newline character at the end of each line is include in
+Note that the implied newline character at the end of each line is included in
 the length calculation, and thus it is possible for the edits to span newlines.
 
 [[fetch-info]]
diff --git a/ReleaseNotes/ReleaseNotes-2.6.txt b/ReleaseNotes/ReleaseNotes-2.6.txt
index ef481c5..12986f6 100644
--- a/ReleaseNotes/ReleaseNotes-2.6.txt
+++ b/ReleaseNotes/ReleaseNotes-2.6.txt
@@ -23,6 +23,17 @@
 a later 2.1.x version), and then to 2.6.x.  If you are upgrading from 2.2.x.x or
 newer, you may ignore this warning and upgrade directly to 2.6.x.
 
+Reverse Proxy Configuration Changes
+-----------------------------------
+
+If you are running a reverse proxy in front of Gerrit (e.g. Apache or Nginx),
+make sure to check your configuration, especially if you are encountering
+'Page Not Found' errors when opening the change screen.
+See the link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.6/config-reverseproxy.html[
+Reverse Proxy Configuration] for details.
+
+Gerrit now requires passed URLs to be unchanged by the proxy.
+
 Release Highlights
 ------------------
 * 42x improvement on `git clone` and `git fetch`
@@ -437,13 +448,6 @@
 HTML thanks to Gson encoding HTML control characters using Unicode
 character escapes within JSON strings.
 
-* Apache reverse proxies must switch to mod_rewrite
-+
-When Apache is used as a reverse proxy the server must be reconfigured
-to use mod_rewrite and AllowEncodedSlashes.  For updated information
-link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.6/config-reverseproxy.html#_apache_2_configuration[
-review the Apache 2 Configuration documentation].
-
 Project Dashboards
 ~~~~~~~~~~~~~~~~~~
 * link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.6/user-dashboards.html#project-dashboards[
@@ -1222,6 +1226,13 @@
 * Prevent account's full name from being set to empty string.  Set it to
   null instead.
 
+* link:https://code.google.com/p/gerrit/issues/detail?id=1682[Issue 1682]:
+Correctly handle paths with URL-escaped characters
++
+URL-unescape the path portion of a change history token to correctly
+handle paths with URL-escapable characters, i.e. '+', ' ', etc.
+
+
 REST API
 ~~~~~~~~
 * Fix returning of 'Email Reviewers' capability via REST
diff --git a/ReleaseNotes/ReleaseNotes-2.7.txt b/ReleaseNotes/ReleaseNotes-2.7.txt
new file mode 100644
index 0000000..844701f
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.7.txt
@@ -0,0 +1,249 @@
+Release notes for Gerrit 2.7
+============================
+
+
+Gerrit 2.7 is now available:
+
+link:http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.7.war[
+http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.7.war]
+
+
+Schema Change
+-------------
+
+
+*WARNING:* This release contains schema changes.  To upgrade:
+----
+  java -jar gerrit.war init -d site_path
+----
+
+*WARNING:* Upgrading to 2.7.x requires the server be first upgraded to 2.1.7 (or
+a later 2.1.x version), and then to 2.7.x.  If you are upgrading from 2.2.x.x or
+newer, you may ignore this warning and upgrade directly to 2.7.x.
+
+
+
+Release Highlights
+------------------
+
+
+* New `copyMaxScore` setting for labels.
+* Comment links configurable per project.
+* Themes configurable per project.
+* Better support for binary files and images in diff screens.
+* User avatars.
+* Several new REST APIs.
+
+
+New Features
+------------
+
+
+General
+~~~~~~~
+
+* New `copyMaxScore` setting for labels.
++
+Labels can be link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-labels.html#label_copyMaxScore[
+configured] to copy approvals forward to the next patch set.
+
+* Comment links can be link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-gerrit.html#commentlink[
+defined per project in the project configuration].
+
+* Gerrit administrators can define project-specific themes.
++
+Themes can be link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-themes.html[
+configured site-wide or per project].
+
+* New '/a/tools' URL.
++
+This allows users to download the `commit-msg` hook via the command line if the
+Gerrit server requires authentication globally.
+
+* New 'Stream Events' global capability.
++
+The link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/access-control.txt#capability_streamEvents[
+Stream Events capability] controls access to the `stream-events` ssh command.
++
+Only administrators and users having this capability are allowed to use `stream-events`.
+
+* 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.
+
+* New setting `gitweb.linkDrafts` to control if gitweb links are shown on drafts.
++
+By default, Gerrit will show links to gitweb on all patch sets.  If the
+link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-gerrit.html#gitweb.linkDrafts[
+gitweb.linkDrafts setting] is set to 'false', links will not be shown on
+draft patch sets.
+
+* Allow changes to be automatically submitted on push.
++
+Teams that want to use Gerrit's submit strategies to handle contention on busy
+branches can use %submit to create a change and have it
+link:link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/user-upload.html#auto_merge[
+immediately submitted], if the caller has Submit permission on refs/for/<ref>.
+
+
+Web UI
+~~~~~~
+
+
+Global
+^^^^^^
+
+* The search box no longer automatically resizes.  Its width is fixed at 70 pixels.
+
+* User avatars are displayed in several places in the Web UI.  "Diffy" is used as
+avatar for the Gerrit server itself.
+
+
+Change Screens
+^^^^^^^^^^^^^^
+
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=667[Issue 667]:
+Highlight patch sets that have drafts.
++
+Patch sets having unpublished draft comments are higlighted with an icon.
+
+* Option to show relative times in change tables.
++
+A new preference setting allows the user to decide if absolute or relative dates
+should be shown in change tables.
+
+* Option to set default visibility of change comments.
++
+A new preference setting allows the user to set the default visibility of
+change comments.
+
+
+Diff Screens
+^^^^^^^^^^^^
+
+* Show images in side-by-side and unified diffs
+
+* Show diffed images above/below each other in unified diffs.
+
+* Harmonize unified diff's styling of images with that of text
+
+
+REST API
+~~~~~~~~
+
+
+Several new link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api.html[
+REST API endpoints] are added.
+
+Accounts
+^^^^^^^^
+
+
+* link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-accounts.html#get-diff-preferences[
+Get account diff preferences]
+
+* link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-accounts.html#set-diff-preferences[
+Set account diff preferences]
+
+
+Changes
+^^^^^^^
+
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=1820[Issue 1820]:
+link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-changes.html#list-comments[
+List comments]
+
+* link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-changes.html#get-comment[
+Get comment]
+
+
+
+Projects
+^^^^^^^^
+
+
+* link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-projects.html#get-config[
+Get project configuration]
+
+
+ssh
+~~~
+
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=1088[Issue 1088]:
+Support link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-gerrit.html#sshd.kerberosKeytab[
+Kerberos authentication for ssh interaction].
+
+
+Bug Fixes
+---------
+
+General
+~~~~~~~
+
+* Postpone check for first account until adding an account.
+
+
+Web UI
+~~~~~~
+
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=1848[Issue 1848]:
+Don't discard inline comments when escape key is pressed.
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=1863[Issue 1863]:
+Drop Arial Unicode MS font and request only sans-serif.
++
+Arial Unicode MS does not have a bold version. Selecting this font prevents
+correct display of bold text on Mac OS X. Simplify the selector to sans-serif
+and allow the browser to use the user's preferred font in this family.
+
+
+REST API
+~~~~~~~~
+
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=1819[Issue 1819]:
+Include change-level messages to the payload returned from
+the link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/rest-api-changes#get-change-detail[
+Get Change Detail REST API endpoint].
+
+
+Email
+~~~~~
+
+* Log failure to access reviewer list for notification emails
+
+* Log when appropriate if email delivery is skipped.
+
+
+Tools
+~~~~~
+
+
+* The release build now builds for all browser configurations.
+
+
+Upgrades
+--------
+
+* `gwtexpui` is now built in the gerrit tree rather than linking a separate module.
+
+
+
+Documentation
+-------------
+
+
+* Update the access control documentation to clarify how to set
+link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/access-control.html#global_capabilities[
+global capabilities].
+
+* Clarify the
+link:http://gerrit-documentation.googlecode.com/svn/Documentation/2.7/config-gerrit.html#cache_names[
+change cache configuration]
+
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index 98cc3ac..6165768 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -1,6 +1,16 @@
 Gerrit Code Review - Release Notes
 ==================================
 
+[[2_8]]
+Version 2.8.x
+-------------
+* link:ReleaseNotes-2.8.html[2.8]
+
+[[2_7]]
+Version 2.7.x
+-------------
+* link:ReleaseNotes-2.7.html[2.7]
+
 [[2_6]]
 Version 2.6.x
 -------------
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
index 8c08feb..b8de9ae 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -58,6 +58,9 @@
   /** Can flush any cache except the active web_sessions cache. */
   public static final String FLUSH_CACHES = "flushCaches";
 
+  /** Can generate HTTP passwords for user other than self. */
+  public static final String GENERATE_HTTP_PASSWORD = "generateHttpPassword";
+
   /** Can terminate any task using the kill command. */
   public static final String KILL_TASK = "killTask";
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
index f55c545..8215e9b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
@@ -5,7 +5,7 @@
 changesMergedInProject = Merged Changes In {0}
 changesAbandonedInProject = Abandoned Changes In {0}
 
-revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}
+revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}.
 cherryPickedChangeDefaultMessage = {0}\n(cherry picked from commit {1})
 
 changeScreenTitleId = Change {0}
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 0bc3369..a05e1ea 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,6 +49,15 @@
 &lt;VirtualHost <span class='ServerName'>review.example.com</span><span class='ServerPort'>:80</span>&gt;
     ServerName <span class='ServerName'>review.example.com</span>
 
+    ProxyRequests Off
+    ProxyVia Off
+    ProxyPreserveHost On
+
+    &lt;Proxy *&gt;
+          Order deny,allow
+          Allow from all
+    &lt;/Proxy&gt;
+
 <div class='apache_auth'>    &lt;Location <span class='ContextPath'>/r</span>/login/&gt;
       AuthType Basic
       AuthName "Gerrit Code Review"
@@ -56,9 +65,8 @@
       ...
     &lt;/Location&gt;</div>
 
-    AllowEncodedSlashes NoDecode
-    RewriteEngine On
-    RewriteRule ^<span class='ContextPath'>/r</span>/(.*) http://...<span class='ContextPath'>/r</span>/$1 [NE,P]
+    AllowEncodedSlashes On
+    ProxyPass <span class='ContextPath'>/r</span>/ http://...<span class='ContextPath'>/r</span>/ nodecode
 &lt;/VirtualHost&gt;
     </pre>
   </body>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index 62d29dd..df218c4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -43,6 +43,7 @@
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.RefControl;
 import com.google.gerrit.server.util.IdGenerator;
+import com.google.gerrit.server.util.MagicBranch;
 import com.google.gwtorm.server.OrmConcurrencyException;
 import com.google.gwtorm.server.OrmException;
 
@@ -252,11 +253,14 @@
           changeInserterFactory.create(refControl, change, revertCommit);
       PatchSet ps = ins.getPatchSet();
 
+      String ref = refControl.getRefName();
+      final String cmdRef =
+          MagicBranch.NEW_PUBLISH_CHANGE
+              + ref.substring(ref.lastIndexOf('/') + 1);
       CommitReceivedEvent commitReceivedEvent =
           new CommitReceivedEvent(new ReceiveCommand(ObjectId.zeroId(),
-              revertCommit.getId(), ps.getRefName()), refControl
-              .getProjectControl().getProject(), refControl.getRefName(),
-              revertCommit, user);
+              revertCommit.getId(), cmdRef), refControl.getProjectControl()
+              .getProject(), refControl.getRefName(), revertCommit, user);
 
       try {
         commitValidators.validateForGerritCommits(commitReceivedEvent);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
index d2014ec..fad9465 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityControl.java
@@ -154,6 +154,12 @@
         || canAdministrateServer();
   }
 
+  /** @return true if the user can generate HTTP passwords for users other than self. */
+  public boolean canGenerateHttpPassword() {
+    return canPerform(GlobalCapability.GENERATE_HTTP_PASSWORD)
+        || canAdministrateServer();
+  }
+
   /** @return which priority queue the user's tasks should be submitted to. */
   public QueueProvider.QueueType getQueueType() {
     // If a non-generic group (that is not Anonymous Users or Registered Users)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
index fa6e4d6..e796cbb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
@@ -68,13 +68,17 @@
   @Override
   public Response<String> apply(AccountResource rsrc, Input input) throws AuthException,
       ResourceNotFoundException, ResourceConflictException, OrmException {
-    if (self.get() != rsrc.getUser()
-        && !self.get().getCapabilities().canAdministrateServer()) {
-      throw new AuthException("not allowed to set HTTP password");
-    }
     if (input == null) {
       input = new Input();
     }
+    if (self.get() != rsrc.getUser()
+        && !self.get().getCapabilities().canAdministrateServer()) {
+      if (input.generate && !self.get().getCapabilities().canGenerateHttpPassword()) {
+        throw new AuthException("not allowed to generate HTTP password");
+      } else {
+        throw new AuthException("not allowed to set HTTP password");
+      }
+    }
     if (rsrc.getUser().getUserName() == null) {
       throw new ResourceConflictException("username must be set");
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
index ebee110..f0458a6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -240,9 +240,12 @@
   private void validate() throws InvalidChangeOperationException {
     CommitValidators cv = commitValidatorsFactory.create(refControl, sshInfo, git);
 
+    String refName = patchSet.getRefName();
     CommitReceivedEvent event = new CommitReceivedEvent(
-        new ReceiveCommand(ObjectId.zeroId(), commit.getId(),
-            patchSet.getRefName()),
+        new ReceiveCommand(
+            ObjectId.zeroId(),
+            commit.getId(),
+            refName.substring(0, refName.lastIndexOf('/') + 1) + "new"),
         refControl.getProjectControl().getProject(), refControl.getRefName(),
         commit, user);
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java
index 0db8019..abba89f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RebaseChange.java
@@ -321,6 +321,9 @@
       OrmException, IOException, InvalidChangeOperationException,
       PathConflictException {
     Change change = chg;
+    if (!chg.currentPatchSetId().equals(patchSetId)) {
+      throw new InvalidChangeOperationException("patch set is not current");
+    }
     final PatchSet originalPatchSet = db.patchSets().get(patchSetId);
 
     final RevCommit rebasedCommit;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 6775566..152cbf4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -32,10 +32,12 @@
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.LinkedListMultimap;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
+import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
@@ -149,7 +151,7 @@
   private static final Logger log =
       LoggerFactory.getLogger(ReceiveCommits.class);
 
-  private static final Pattern NEW_PATCHSET =
+  public static final Pattern NEW_PATCHSET =
       Pattern.compile("^refs/changes/(?:[0-9][0-9]/)?([1-9][0-9]*)(?:/new)?$");
 
   private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
@@ -285,7 +287,7 @@
   private final Set<RevCommit> validCommits = new HashSet<RevCommit>();
 
   private ListMultimap<Change.Id, Ref> refsByChange;
-  private Map<ObjectId, Ref> refsById;
+  private SetMultimap<ObjectId, Ref> refsById;
   private Map<String, Ref> allRefs;
 
   private final SubmoduleOp.Factory subOpFactory;
@@ -1886,6 +1888,14 @@
                   }
                   change.setLastSha1MergeTested(null);
                   change.setCurrentPatchSet(info);
+
+                  final List<String> idList = newCommit.getFooterLines(CHANGE_ID);
+                  if (idList.isEmpty()) {
+                    change.setKey(new Change.Key("I" + newCommit.name()));
+                  } else {
+                    change.setKey(new Change.Key(idList.get(idList.size() - 1).trim()));
+                  }
+
                   ChangeUtil.updated(change);
                   return change;
                 }
@@ -2100,20 +2110,22 @@
         rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
       }
 
-      final Map<ObjectId, Ref> byCommit = changeRefsById();
+      final SetMultimap<ObjectId, Ref> byCommit = changeRefsById();
       final Map<Change.Key, Change.Id> byKey = openChangesByKey(
           new Branch.NameKey(project.getNameKey(), cmd.getRefName()));
       final List<ReplaceRequest> toClose = new ArrayList<ReplaceRequest>();
       RevCommit c;
       while ((c = rw.next()) != null) {
-        final Ref ref = byCommit.get(c.copy());
-        if (ref != null) {
-          rw.parseBody(c);
-          Change.Key closedChange =
-              closeChange(cmd, PatchSet.Id.fromRef(ref.getName()), c);
-          closeProgress.update(1);
-          if (closedChange != null) {
-            byKey.remove(closedChange);
+        final Set<Ref> refs = byCommit.get(c.copy());
+        for (Ref ref : refs) {
+          if (ref != null) {
+            rw.parseBody(c);
+            Change.Key closedChange =
+                closeChange(cmd, PatchSet.Id.fromRef(ref.getName()), c);
+            closeProgress.update(1);
+            if (closedChange != null) {
+              byKey.remove(closedChange);
+            }
           }
         }
 
@@ -2193,9 +2205,9 @@
     return change.getKey();
   }
 
-  private Map<ObjectId, Ref> changeRefsById() throws IOException {
+  private SetMultimap<ObjectId, Ref> changeRefsById() throws IOException {
     if (refsById == null) {
-      refsById = new HashMap<ObjectId, Ref>();
+      refsById =  HashMultimap.create();
       for (Ref r : repo.getRefDatabase().getRefs("refs/changes/").values()) {
         if (PatchSet.isRef(r.getName())) {
           refsById.put(r.getObjectId(), r);
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 c6fc709..e7b9d31 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
@@ -24,6 +24,7 @@
 import com.google.gerrit.server.events.CommitReceivedEvent;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.git.ReceiveCommits;
 import com.google.gerrit.server.git.ValidationError;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.RefControl;
@@ -50,7 +51,6 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.regex.Pattern;
 
 import javax.annotation.Nullable;
 
@@ -60,9 +60,6 @@
 
   private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
 
-  private static final Pattern NEW_PATCHSET = Pattern
-      .compile("^refs/changes/(?:[0-9][0-9])?(/[1-9][0-9]*){1,2}(?:/new)?$");
-
   private static final String GIT_HOOKS_COMMIT_MSG =
       "`git rev-parse --git-dir`/hooks/commit-msg";
 
@@ -109,7 +106,8 @@
     validators.add(new CommitterUploaderValidator(refControl, canonicalWebUrl));
     validators.add(new SignedOffByValidator(refControl, canonicalWebUrl));
     if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
-        || NEW_PATCHSET.matcher(receiveEvent.command.getRefName()).matches()) {
+        || ReceiveCommits.NEW_PATCHSET.matcher(
+            receiveEvent.command.getRefName()).matches()) {
       validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
           installCommitMsgHookCommand, sshInfo));
     }
@@ -143,7 +141,8 @@
     validators.add(new AuthorUploaderValidator(refControl, canonicalWebUrl));
     validators.add(new SignedOffByValidator(refControl, canonicalWebUrl));
     if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
-        || NEW_PATCHSET.matcher(receiveEvent.command.getRefName()).matches()) {
+        || ReceiveCommits.NEW_PATCHSET.matcher(
+            receiveEvent.command.getRefName()).matches()) {
       validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
           installCommitMsgHookCommand, sshInfo));
     }
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/change/ChangeMessages.properties b/gerrit-server/src/main/resources/com/google/gerrit/server/change/ChangeMessages.properties
index 11384a1..f05f23b 100644
--- a/gerrit-server/src/main/resources/com/google/gerrit/server/change/ChangeMessages.properties
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/change/ChangeMessages.properties
@@ -1,6 +1,6 @@
 # Changes to this file should also be made in
 # gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties
-revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}
+revertChangeDefaultMessage = Revert \"{0}\"\n\nThis reverts commit {1}.
 reviewerNotFound = {0} does not identify a registered user or group
 
 groupIsNotAllowed =  The group {0} cannot be added as reviewer.
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshScope.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshScope.java
index 64a1a42..0ae40a5 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshScope.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshScope.java
@@ -82,7 +82,9 @@
     public CurrentUser getCurrentUser() {
       final CurrentUser user = session.getCurrentUser();
       if (user instanceof IdentifiedUser) {
-        return userFactory.create(((IdentifiedUser) user).getAccountId());
+        IdentifiedUser identifiedUser = userFactory.create(((IdentifiedUser) user).getAccountId());
+        identifiedUser.setAccessPath(user.getAccessPath());
+        return identifiedUser;
       }
       return user;
     }