Merge branch 'stable-2.3' into stable-2.4

* stable-2.3: (27 commits)
  Fix merging of access sections
  Fix: Inconsistent behaviour when replicating refs/meta/config
  Fix case check for project name so that symlinks work again
  Move note about changing approval categories to the correct section
  Fix spelling mistake in access control documentation
  Gerrit 2.3 ReleaseNotes
  Fix link in show caches documentation
  Access control documentation: Administrator example role
  Access control documentation: Project owner example role
  Access control documentation: Integrator example role
  Access control documentation: CI system example role
  Access control documentation: Capability view conn. & queue
  Access control documentation: Developer example role
  Access control documentation: Capability replication and view caches
  Access control documentation: Kill and priority capabilities
  Access control documentation: Flush caches capability
  Access control documentation: Example roles introduced
  Add missing header for suggest.accounts documentation
  Add visible-to-all flag in the documentation for cmd-create-group
  Access control documentation: Create group and project
  ...

Conflicts:
	Documentation/config-gerrit.txt
	ReleaseNotes/index.txt
	gerrit-server/src/main/java/com/google/gerrit/server/git/RepositoryCaseMismatchException.java

Change-Id: I23398003827ee9c010445e65e6d16b55f2754f3d
Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
diff --git a/Documentation/cmd-ls-projects.txt b/Documentation/cmd-ls-projects.txt
index b6e67c4..7782aa8 100644
--- a/Documentation/cmd-ls-projects.txt
+++ b/Documentation/cmd-ls-projects.txt
@@ -57,6 +57,12 @@
 --type::
 	Display only projects of the specified type.  If not
 	specified, defaults to `code`. Supported types:
++
+--
+`code`:: Any project likely to contain user files.
+`permissions`:: Projects created with the `--permissions-only` flag.
+`all`:: Any type of project.
+--
 
 --all::
 	Display all projects that are accessible by the calling user
@@ -65,12 +71,6 @@
 	are owned by the calling user account (even if for these projects
 	the 'READ' access right is not assigned to the calling user
 	account).
-+
---
-`code`:: Any project likely to contain user files.
-`permissions`:: Projects created with the `--permissions-only` flag.
-`all`:: Any type of project.
---
 
 EXAMPLES
 --------
diff --git a/Documentation/cmd-query.txt b/Documentation/cmd-query.txt
index 1bd4862..253bed1 100644
--- a/Documentation/cmd-query.txt
+++ b/Documentation/cmd-query.txt
@@ -15,6 +15,7 @@
   [--files]
   [--comments]
   [--commit-message]
+  [--dependencies]
   [--]
   <query>
   [limit:<n>]
@@ -75,6 +76,10 @@
 --commit-message::
 	Include the full commit message in the change description.
 
+--dependencies::
+	Show information about patch sets which depend on, or are needed by,
+	each patch set.
+
 limit:<n>::
 	Maximum number of results to return.  This is actually a
 	query operator, and not a command line option.	If more
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 9fa7ee1..54f7752 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -24,6 +24,27 @@
   diskbuffer = 10 m
 ----
 
+[[accounts]]Section accounts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[[accounts.visibility]]accounts.visibility::
++
+Controls visibility of other users' dashboard pages and
+completion suggestions to web users.
++
+If `ALL`, all users are visible to all other users, even
+anonymous users.
++
+If `SAME_GROUP`, only users who are also members of a group the
+current user is a member of are visible.
++
+If `VISIBLE_GROUP`, only users who are members of at least one group
+that is visible to the current user are visible.
++
+If `NONE`, no users other than the current user are visible.
++
+Default is `ALL`.
+
 [[addreviewer]]Section addreviewer
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1086,7 +1107,7 @@
 +
 Valid values are `gitweb`, `cgit`, `disabled` or `custom`.
 
-[[gitweb.type]]gitweb.revision::
+[[gitweb.revision]]gitweb.revision::
 +
 Optional pattern to use for constructing the gitweb URL when pointing
 at a specific commit when `custom` is used above.
@@ -1094,14 +1115,14 @@
 Valid replacements are `${project}` for the project name in Gerrit
 and `${commit}` for the SHA1 hash for the commit.
 
-[[gitweb.type]]gitweb.project::
+[[gitweb.project]]gitweb.project::
 +
 Optional pattern to use for constructing the gitweb URL when pointing
 at a specific project when `custom` is used above.
 +
 Valid replacements are `${project}` for the project name in Gerrit.
 
-[[gitweb.type]]gitweb.branch::
+[[gitweb.branch]]gitweb.branch::
 +
 Optional pattern to use for constructing the gitweb URL when pointing
 at a specific branch when `custom` is used above.
@@ -1109,6 +1130,16 @@
 Valid replacements are `${project}` for the project name in Gerrit
 and `${branch}` for the name of the branch.
 
+[[gitweb.filehistory]]gitweb.filehistory::
++
+Optional pattern to use for constructing the gitweb URL when pointing
+at the history of a file in a specific branch when `custom` is used
+above.
++
+Valid replacements are `${project}` for the project name in Gerrit,
+`${file}` for the file name and `${branch}` for the name of the
+branch.
+
 [[gitweb.linkname]]gitweb.linkname::
 +
 Optional setting for modifying the link name presented to the user
@@ -1654,7 +1685,8 @@
 This section is used to set who can execute the 'receive-pack' and
 to limit the maximum Git object size that 'receive-pack' will accept.
 'receive-pack' is what runs on the server during a user's push or
-repo upload command.
+repo upload command. It also contains some advanced options for tuning the
+behavior of Gerrit's 'receive-pack' mechanism.
 
 ----
 [receive]
@@ -1685,6 +1717,24 @@
 +
 Common unit suffixes of 'k', 'm', or 'g' are supported.
 
+[[receive.threadPoolSize]]receive.threadPoolSize::
++
+Maximum size of the thread pool in which the change data in received packs is
+processed.
++
+Defaults to the number of available CPUs according to the Java runtime.
+
+[[receive.timeout]]receive.timeout::
++
+Overall timeout on the time taken to process the change data in
+received packs. Only includes the time processing Gerrit changes
+and updating references, not the time to index the pack. Values can
+be specified using standard time unit abbreviations ('ms', 'sec',
+'min', etc.).
++
+Default is 2 minutes. If no unit is specified, millisconds
+is assumed.
+
 
 [[repository]]Section repository
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2013,19 +2063,20 @@
 
 [[suggest.accounts]]suggest.accounts::
 +
-If `ALL`, all matching user accounts will be offered as
-completion suggestions when adding a reviewer to a change,
-or a user to a group.
+If `true`, visible user accounts (according to the value of
+`accounts.visibility`) will be offered as completion suggestions
+when adding a reviewer to a change, or a user to a group.
 +
-If `SAME_GROUP`, only users who are also members of a group the
-current user is a member of will be offered.
+If `false`, account suggestion is disabled.
 +
-If `VISIBLE_GROUP`, only users who are members of at least one group
-that is visible to the current user will be offered.
+Older configurations may also have one of the `accounts.visibility`
+values for this field, including `OFF` as a synonym for `NONE`. If
+`accounts.visibility` is also set, that value overrides this one;
+otherwise, this value applies to both `suggest.accounts` and
+`accounts.visibility`.
 +
-If `OFF`, no account suggestions are given.
-+
-Default is `ALL`.
+New configurations should prefer the boolean value for this field
+and an enum value for `accounts.visibility`.
 
 [[theme]] Section theme
 ~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/dev-eclipse.txt b/Documentation/dev-eclipse.txt
index b37223c..e239a63 100644
--- a/Documentation/dev-eclipse.txt
+++ b/Documentation/dev-eclipse.txt
@@ -13,7 +13,7 @@
 
 Install the Maven Integration plugins:
 
-http://m2eclipse.codehaus.org/[m2eclipse]
+http://www.eclipse.org/m2e/download/[m2eclipse]
 
 
 [[Formatting]]
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 6a6ce16..3aafe8c 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -109,12 +109,9 @@
 [[branch]]
 branch:'BRANCH'::
 +
-Changes for 'BRANCH'.  The branch name is the short name shown
-in the web interface, without the traditional 'refs/heads/'
-prefix.  This operator is a shorthand for 'refs:'.  Searching for
-'branch:master' really means 'ref:refs/heads/master', and searching
-for 'branch:refs/heads/master' is the same as searching for
-'ref:refs/heads/refs/heads/master'.
+Changes for 'BRANCH'.  The branch name is either the short name shown
+in the web interface or the full name of the destination branch with
+the traditional 'refs/heads/' prefix.
 +
 If 'BRANCH' starts with `^` it matches branch names by regular
 expression patterns.  The
diff --git a/Documentation/user-upload.txt b/Documentation/user-upload.txt
index 2cd959b..8e05e72 100644
--- a/Documentation/user-upload.txt
+++ b/Documentation/user-upload.txt
@@ -342,17 +342,17 @@
 ~~~~~~~~~~~~~~~
 
 To replace changes, ensure Change-Id lines were created in the
-commit messages, and just use `repo upload` without the `--replace`
-command line flag.  Gerrit Code Review will automatically match
-the commits back to their original changes by taking advantage of
-their Change-Id lines.
+commit messages, and just use `repo upload`.
+Gerrit Code Review will automatically match the commits back to
+their original changes by taking advantage of their Change-Id lines.
 
 If Change-Id lines are not present in the commit messages, consider
 amending the message and copying the line from the change's page
 on the web.
 
 If Change-Id lines are not available, then the user must use the much
-more manual mapping technique offered by `repo upload --replace`.
+more <<manual_replacement_mapping,manual mapping technique>> offered
+by using `git push` to a specific `refs/changes/change#` reference.
 
 For more about Change-Ids, see link:user-changeid.html[Change-Id Lines].
 
diff --git a/ReleaseNotes/ReleaseNotes-2.4.txt b/ReleaseNotes/ReleaseNotes-2.4.txt
new file mode 100644
index 0000000..ee7fd54
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.4.txt
@@ -0,0 +1,249 @@
+Release notes for Gerrit 2.4
+============================
+
+Gerrit 2.4 is now available:
+
+link:http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.4.war[http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.4.war]
+
+Schema Change
+-------------
+*WARNING:* This release contains schema changes.  To upgrade:
+----
+  java -jar gerrit.war init -d site_path
+----
+
+*WARNING:* Upgrading to 2.4.x requires the server be first upgraded to 2.1.7 (or
+a later 2.1.x version), and then to 2.4.x.  If you are upgrading from 2.2.x.x or
+newer, you may ignore this warning and upgrade directly to 2.4.x.
+
+New Features
+------------
+
+Security
+~~~~~~~~
+
+* Restrict visibility to arbitrary user dashboards
++
+Administrators have some expectation when using the 'suggest.accounts'
+visibility restriction feature that users cannot get the names or
+email addresses for arbitrary accounts. In fact, because account IDs
+are sequential, it would be easy for an adversary to get personal
+information of all users on the server by requesting every user's
+dashboard.
++
+This includes changing the meaning of the 'suggest.accounts' config
+option to be a boolean indicating whether account suggestion should
+happen at all, which is now orthogonal to the account visibility
+restriction policy. We still recognize the old values for
+'suggest.accounts', with the slight behavior change that
+'suggest.accounts=OFF' now means that users cannot access the dashboards
+of any other users. Administrators who do not want this behavior can
+update their configuration.
+
+* Indicate that 'not found' may actually be a permission issue
+
+Web
+~~~
+
+* Add user preference to mark files reviewed automatically or manually
++
+Add a checkbox to the preferences header on the diff
+screen which allows a user to specify whether they
+want manual-reviewing enabled or disabled.  Previously,
+every file was auto marked reviewed when a user first
+displayed it.  The new manual mode prevents this auto
+marking and only marks a file reviewed when the user
+explicitly clicks on the reviewed checkbox.
+
+* Use 'Auto Merge' for merge commit's base comparison
++
+When reviewing a merge commit, the old wording in the version history dropdown
+of 'Base' doesn't really match Gerrit's behavior.  Updating this to use
+'Auto Merge' as suggested by Shawn Pearce on IRC.
+
+* issue 1035 Add rebase button to the change screen
++
+This change adds a rebase button along with the rest of
+the action buttons in the change page. When pressing the
+button, the most recent patch set will be rebased onto
+the tip of the destination branch or the latest patchset
+of the change we depend upon. A new patch set containing
+the rebased commit will be produced and added to the
+change.
+
+* Make a user's dashboard visible if any of the changes are visible to the
+current user.
+
+* Change 'Loading ...' to say 'Working ...' as, often, there is more going on
+than just loading a response.
+
+Performance
+~~~~~~~~~~~
+
+* Asynchronously send email so it does not block the UI
+* Optimize queries for open/merged changes by project + branch
+
+Git
+~~~
+
+* Implement a multi-sub-task progress monitor for ReceiveCommits
+
+* Close corresponding change when pushing to 'refs/heads/*'
++
+Gerrit would not close the open changes with matching change-ids,
+when the user pushes commits directly to 'refs/heads/*'.
++
+This issue could be triggered for two reasons:
+
+. It is triggered when Gerrit detects no changes between the
+pushed commits and the current patchset on the open changes. This
+patch make sure that the matching open change is always closed when
+pushing to 'refs/heads/*', even if no visible changes is detected.
+
+. The same commit exists on another branch than the destination
+branch. This could trick gerrit into just "re-closing" the wrong
+change.
+
+* Run ReceiveCommits in a shared thread pool
++
+Since the work to ReceiveCommits may take a long, potentially unbounded
+amount of time, we would like to have it run in the background so it
+can be monitored for timeouts and cancelled, and have stalls reported
+to the user from the main thread.
+
+Search
+~~~~~~
+
+* Add the '--dependencies' option to the 'query' command.
++
+This option includes information about patch sets which depend on, or are
+needed by, each patch set.
+
+* Branch Operator: Support full branch names
++
+The search operator for branches required the provided value to be the
+short branch name that is shown in the web interface (without the
+'refs/heads/' prefix). Change the branch operator so that it also
+supports full branch names as value.
++
+It is intuive that searching with 'branch:master' and searching with
+'branch:refs/for/master' deliver the same result. So far
+'branch:refs/for/master' was the same as searching with
+'refs:refs/heads/refs/heads/master' which is unexpected for most users.
+
+* Add comment inclusion via '&comments=true' over HTTP
++
+With this change, we can fetch the comments on a patchset by sending a
+request to 'https://site/query?comments=true'
+
+Access Rights
+~~~~~~~~~~~~~
+
+* Added the 'emailReviewers' as a global capability.
++
+This replaces the 'emailOnlyAuthors' flag of account groups.
+
+Dev
+~~~
+
+* issue 1272 Add scripts to create release notes from git log
++
+These script generates a list of commits from git log between two given commits
+and outputs the asciidoc format containting list of commits subject and body.
+
+* Update URL for m2eclipse
++
+The project is now under the Eclipse Foundation umbrella.
+
+* Add missing ignore for m2e prefs in gerrit-ehcache
+
+* Add '--issues' and '--issue_numbers' options to the 'gitlog2asciidoc.py'
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+* Remove perl from 'commit-msg' hook
++
+Removing perl from the commit-msg hook reduces the dependencies
+gerrit imposes on its users.
+
+* updating contrib 'trivial_rebase.py' for 2.2.2.1
+
+Upgrades
+--------
+
+* Updated to Guice 3.0.
+* Updated to gwtorm 1.4.
+* Update JGit to 1.3.0.201202151440-r.75-gff13648
+* Update to gwtjsonrpc 1.3
++
+The change also shrinks the built WAR from 38M to 23M
+by excluding the now unnecessary GWT server code.
+
+Bug Fixes
+---------
+
+* issue 904 Users who starred a change should receive all the emails about a change.
+
+* Fix: 'Diff All Side-by-Side' and 'Diff All Unified' buttons
++
+When pressing the 'Diff All Side-by-Side' or
+'Diff All Unified' button on the change screen, the
+opened browser windows/tabs shows diffs using "Base"
+as old version and the latest one as active patch set,
+regardless what has been set using the
+"Old Version History:" drop down menu and what is
+currently active patch set.
++
+Gerrit doesn't remember the base patch set in the URL,
+making it impossible to copy-and-paste the URL to
+co-workers to show them the same diff a user is
+looking at.
++
+This change fixes this behavior to make sure that
+the opened new browser windows shows diffs using the
+correct old patch set and active patch set.
+
+* Fix NPEs looking up groups by UUID in GroupCache
+
+* Fix default 'receive.timeout'
++
+This should be in milliseconds, not seconds. Set the default to be
+2 minutes in milliseconds and update the documentation to reflect
+that milliseconds are the default unit of time used here.
+
+* Fix 'development_become_any_account' redirects
+* issue 1299 Allow configuration of optional pattern for gitweb file history link
+* Use servlet context path during logout
+
+* issue 1353 Fix case check for project name so that symlinks work again
+
+Documentation
+-------------
+
+Access Rights
+~~~~~~~~~~~~~
+* Capabilities introduced
+* Kill and priority capabilities
+* Administrate server capability
+* Create account capability
+* Create group and project capability
+* Flush caches capability
+* Capability replication and view caches
+* Capability view conn. & queue
+* Example roles introduced
+* Developer example role
+* CI system example role
+* Integrator example role
+* Project owner example role
+* Administrator example role
+
+Miscellaneous
+~~~~~~~~~~~~~
+* User upload documentation: Replace changes
+* Add visible-to-all flag in the documentation for cmd-create-group
+* Add a contributing guideline for annotations
+* Add missing header for suggest.accounts documentation
+* Fix anchors for description of gitweb config parameters
+* Add missing section name to config-gerrit documentation
+* Fix documentation of ls-projects
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index 13da60a..30a85e8 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -1,6 +1,11 @@
 Gerrit Code Review - Release Notes
 ==================================
 
+[[2_4]]
+Version 2.4.x
+-------------
+* link:ReleaseNotes-2.4.html[2.4]
+
 [[2_3]]
 Version 2.3.x
 -------------
diff --git a/contrib/trivial_rebase.py b/contrib/trivial_rebase.py
index a5123a3..a514b4c 100755
--- a/contrib/trivial_rebase.py
+++ b/contrib/trivial_rebase.py
@@ -93,8 +93,8 @@
 
   Returns a list of approval dicts"""
   sql_query = ("\"SELECT value,account_id,category_id FROM patch_set_approvals "
-               "WHERE change_id = (SELECT change_id FROM changes WHERE "
-               "patch_set_id = %s AND change_key = \'%s\') AND value <> 0\""
+               "WHERE patch_set_id = %s AND change_id = (SELECT change_id FROM "
+               "changes WHERE change_key = \'%s\') AND value <> 0\""
                % ((patchset - 1), changeId))
   gsql_out = GsqlQuery(sql_query, server, port)
   approvals = []
diff --git a/gerrit-antlr/pom.xml b/gerrit-antlr/pom.xml
index efcc190..aa0d7fd 100644
--- a/gerrit-antlr/pom.xml
+++ b/gerrit-antlr/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-antlr</artifactId>
diff --git a/gerrit-common/pom.xml b/gerrit-common/pom.xml
index b4395be..e7933ea 100644
--- a/gerrit-common/pom.xml
+++ b/gerrit-common/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-common</artifactId>
diff --git a/gerrit-common/src/main/java/com/google/gerrit/Common.gwt.xml b/gerrit-common/src/main/java/com/google/gerrit/Common.gwt.xml
index 171ae8a..468b477 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/Common.gwt.xml
+++ b/gerrit-common/src/main/java/com/google/gerrit/Common.gwt.xml
@@ -14,7 +14,7 @@
  limitations under the License.
 -->
 <module>
-  <inherits name='com.google.gerrit.ReviewDB' />
+  <inherits name='com.google.gerrit.reviewdb.ReviewDB' />
   <inherits name='com.google.gwtjsonrpc.GWTJSONRPC'/>
   <source path='common' />
 </module>
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index 23bef63..71df400 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -16,11 +16,11 @@
 
 import com.google.gerrit.common.data.AccountInfo;
 import com.google.gerrit.common.data.ChangeInfo;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Change.Status;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Change.Status;
 import com.google.gwtorm.client.KeyUtil;
 
 public class PageLinks {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdProviderPattern.java b/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdProviderPattern.java
index 731d765..c80d3eb 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdProviderPattern.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdProviderPattern.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.auth.openid;
 
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 
 public class OpenIdProviderPattern {
   public static OpenIdProviderPattern create(String pattern) {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdService.java b/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdService.java
index 0a24cd5..0deba34 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/auth/openid/OpenIdService.java
@@ -15,11 +15,11 @@
 package com.google.gerrit.common.auth.openid;
 
 import com.google.gerrit.common.auth.SignInMode;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.AllowCrossSiteRequest;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.AllowCrossSiteRequest;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 @RpcImpl(version = Version.V2_0)
 public interface OpenIdService extends RemoteJsonService {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
index 4a9ab66..e89cdd2 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/LoginResult.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.auth.userpass;
 
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 
 public class LoginResult {
   public boolean success;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/UserPassAuthService.java b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/UserPassAuthService.java
index 5f39bc3..1d25a3d 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/UserPassAuthService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/auth/userpass/UserPassAuthService.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.common.auth.userpass;
 
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.AllowCrossSiteRequest;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.AllowCrossSiteRequest;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 @RpcImpl(version = Version.V2_0)
 public interface UserPassAuthService extends RemoteJsonService {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccessSection.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccessSection.java
index def174f..cd64b0a 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccessSection.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccessSection.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -23,40 +23,18 @@
 import java.util.Set;
 
 /** Portion of a {@link Project} describing access rules. */
-public class AccessSection implements Comparable<AccessSection> {
+public class AccessSection extends RefConfigSection implements
+    Comparable<AccessSection> {
   /** Special name given to the global capabilities; not a valid reference. */
   public static final String GLOBAL_CAPABILITIES = "GLOBAL_CAPABILITIES";
 
-  /** Pattern that matches all references in a project. */
-  public static final String ALL = "refs/*";
-
-  /** Pattern that matches all branches in a project. */
-  public static final String HEADS = "refs/heads/*";
-
-  /** Prefix that triggers a regular expression pattern. */
-  public static final String REGEX_PREFIX = "^";
-
-  /** @return true if the name is likely to be a valid access section name. */
-  public static boolean isAccessSection(String name) {
-    return name.startsWith("refs/") || name.startsWith("^refs/");
-  }
-
-  protected String name;
   protected List<Permission> permissions;
 
   protected AccessSection() {
   }
 
   public AccessSection(String refPattern) {
-    setName(refPattern);
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
+    super(refPattern);
   }
 
   public List<Permission> getPermissions() {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountDashboardInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountDashboardInfo.java
index abcfe28..e24900b 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountDashboardInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountDashboardInfo.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
index 39c5d9c..9a4d9fb 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 /** Summary information about an {@link Account}, for simple tabular displays. */
 public class AccountInfo {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfoCache.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfoCache.java
index cf5f20b..bc028e8 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfoCache.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfoCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountProjectWatchInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountProjectWatchInfo.java
index 89a50f1..581a09b 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountProjectWatchInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountProjectWatchInfo.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Project;
 
 public final class AccountProjectWatchInfo {
   protected AccountProjectWatch watch;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
index c9aa0fd..21aca69 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
@@ -15,17 +15,16 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.common.data.GroupDetail;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountSshKey;
-import com.google.gerrit.reviewdb.ContactInformation;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
+import com.google.gerrit.reviewdb.client.ContactInformation;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountService.java
index e219074..7377d7e 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountService.java
@@ -15,15 +15,15 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AgreementInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AgreementInfo.java
index 7ae651e..0c6f6b7 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AgreementInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AgreementInfo.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountGroupAgreement;
-import com.google.gerrit.reviewdb.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
 
 import java.util.List;
 import java.util.Map;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalDetail.java
index 318c60b..3d438f2 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalDetail.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 
 import java.sql.Timestamp;
 import java.util.ArrayList;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummary.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummary.java
index 57e8b71..19c9d67 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummary.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummary.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummarySet.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummarySet.java
index 57ee928..2b11085 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummarySet.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalSummarySet.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalType.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalType.java
index 7d03457..333b91c 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalType.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalType.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalTypes.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalTypes.java
index 0518010..b1e32d1 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalTypes.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ApprovalTypes.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
 
 import java.util.HashMap;
 import java.util.List;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
index 809d462..74d1962 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetail.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -29,6 +29,7 @@
   protected boolean allowsAnonymous;
   protected boolean canAbandon;
   protected boolean canPublish;
+  protected boolean canRebase;
   protected boolean canRestore;
   protected boolean canRevert;
   protected boolean canDeleteDraft;
@@ -80,6 +81,14 @@
     canPublish = a;
   }
 
+  public boolean canRebase() {
+    return canRebase;
+  }
+
+  public void setCanRebase(final boolean a) {
+    canRebase = a;
+  }
+
   public boolean canRestore() {
     return canRestore;
   }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
index 2fbda21..8b43624 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
@@ -15,13 +15,13 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 @RpcImpl(version = Version.V2_0)
 public interface ChangeDetailService extends RemoteJsonService {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java
index eac8a9e..391d615 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 import java.sql.Timestamp;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
index 5ff85e3..f646bc6 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeListService.java
@@ -15,13 +15,13 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.Set;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
index b667877..872bddc 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeManageService.java
@@ -15,12 +15,12 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 @RpcImpl(version = Version.V2_0)
 public interface ChangeManageService extends RemoteJsonService {
@@ -44,4 +44,7 @@
 
   @SignInRequired
   void deleteDraftChange(PatchSet.Id patchSetId, AsyncCallback<VoidResult> callback);
+
+  @SignInRequired
+  void rebaseChange(PatchSet.Id patchSetId, AsyncCallback<ChangeDetail> callback);
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommentDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommentDetail.java
index 576e077..0e079b3 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/CommentDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/CommentDetail.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
index 5581c18..456ffb4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
@@ -15,10 +15,10 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AuthType;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadScheme;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
 import com.google.gwtexpui.safehtml.client.RegexFindReplace;
 
 import java.util.List;
@@ -29,7 +29,7 @@
   protected String httpPasswordUrl;
   protected List<OpenIdProviderPattern> allowedOpenIDs;
 
-  protected GitwebLink gitweb;
+  protected GitwebConfig gitweb;
   protected boolean useContributorAgreements;
   protected boolean useContactInfo;
   protected boolean allowRegisterNewEmail;
@@ -86,11 +86,11 @@
     downloadSchemes = s;
   }
 
-  public GitwebLink getGitwebLink() {
+  public GitwebConfig getGitwebLink() {
     return gitweb;
   }
 
-  public void setGitwebLink(final GitwebLink w) {
+  public void setGitwebLink(final GitwebConfig w) {
     gitweb = w;
   }
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebConfig.java
new file mode 100644
index 0000000..0503c60
--- /dev/null
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebConfig.java
@@ -0,0 +1,29 @@
+// Copyright (C) 2008 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.common.data;
+
+/** Link to an external gitweb server. */
+public class GitwebConfig {
+  public String baseUrl;
+  public GitWebType type;
+
+  protected GitwebConfig() {
+  }
+
+  public GitwebConfig(final String base, final GitWebType gitWebType) {
+    baseUrl = base;
+    type = gitWebType;
+  }
+}
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 2e46791..d3d2a4d 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
@@ -39,6 +39,16 @@
   /** Can create any project on the server. */
   public static final String CREATE_PROJECT = "createProject";
 
+  /**
+   * Denotes who may email change reviewers.
+   * <p>
+   * This can be used to deny build bots from emailing reviewers and people who
+   * have starred the changed. Instead, only the authors of the change will be
+   * emailed. The allow rules are evaluated before deny rules, however the
+   * default is to allow emailing, if no explicit rule is matched.
+   */
+  public static final String EMAIL_REVIEWERS = "emailReviewers";
+
   /** Can flush any cache except the active web_sessions cache. */
   public static final String FLUSH_CACHES = "flushCaches";
 
@@ -71,6 +81,7 @@
     NAMES_LC.add(CREATE_ACCOUNT.toLowerCase());
     NAMES_LC.add(CREATE_GROUP.toLowerCase());
     NAMES_LC.add(CREATE_PROJECT.toLowerCase());
+    NAMES_LC.add(EMAIL_REVIEWERS.toLowerCase());
     NAMES_LC.add(FLUSH_CACHES.toLowerCase());
     NAMES_LC.add(KILL_TASK.toLowerCase());
     NAMES_LC.add(PRIORITY.toLowerCase());
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupAdminService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupAdminService.java
index 087f047..f385e27 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupAdminService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupAdminService.java
@@ -15,14 +15,14 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupDetail.java
index 69e535c..65723f7 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupDetail.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfo.java
index 55577f2..547a5f4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfo.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 /** Summary information about an {@link AccountGroup}, for simple tabular displays. */
 public class GroupInfo {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfoCache.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfoCache.java
index 80d8756..6a5dd5c 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfoCache.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupInfoCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupList.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupList.java
index 9c79eb2..6352461 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupList.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupList.java
@@ -14,8 +14,6 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.common.data.GroupDetail;
-
 import java.util.List;
 
 public class GroupList {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupOptions.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupOptions.java
index 82e0618..c6ed781 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupOptions.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupOptions.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 /**
  * Options for an {@link AccountGroup}.
@@ -22,22 +22,15 @@
 public class GroupOptions {
 
   private boolean visibleToAll;
-  private boolean emailOnlyAuthors;
 
   protected GroupOptions() {
   }
 
-  public GroupOptions(final boolean visibleToAll,
-       final boolean emailOnlyAuthors) {
+  public GroupOptions(final boolean visibleToAll) {
     this.visibleToAll = visibleToAll;
-    this.emailOnlyAuthors = emailOnlyAuthors;
   }
 
   public boolean isVisibleToAll() {
     return visibleToAll;
   }
-
-  public boolean isEmailOnlyAuthors() {
-    return emailOnlyAuthors;
-  }
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupReference.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupReference.java
index cd6e172..f05d1b9 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupReference.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GroupReference.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 /** Describes a group within a projects {@link AccessSection}s. */
 public class GroupReference implements Comparable<GroupReference> {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
index d90d68b..c3d3f1e 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
 
 /** Data sent as part of the host page, to bootstrap the UI. */
 public class HostPageData {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java
index 7341c47..1c830e9 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ListBranchesResult.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Branch;
+import com.google.gerrit.reviewdb.client.Branch;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchDetailService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchDetailService.java
index c9be1d4..0191544 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchDetailService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchDetailService.java
@@ -15,19 +15,19 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Patch.Key;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Patch.Key;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
index 2214af9..2308b77 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
@@ -14,16 +14,13 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.prettify.client.ClientSideFormatter;
 import com.google.gerrit.prettify.common.EditList;
-import com.google.gerrit.prettify.common.PrettyFormatter;
 import com.google.gerrit.prettify.common.SparseFileContent;
-import com.google.gerrit.prettify.common.SparseHtmlFile;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.Patch.ChangeType;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
 
 import org.eclipse.jgit.diff.Edit;
 
@@ -167,36 +164,6 @@
     return b;
   }
 
-  public SparseHtmlFile getSparseHtmlFileA() {
-    AccountDiffPreference dp = new AccountDiffPreference(diffPrefs);
-    dp.setShowWhitespaceErrors(false);
-
-    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
-    f.setDiffPrefs(dp);
-    f.setFileName(a.getPath());
-    f.setEditFilter(PrettyFormatter.A);
-    f.setEditList(edits);
-    f.format(a);
-    return f;
-  }
-
-  public SparseHtmlFile getSparseHtmlFileB() {
-    AccountDiffPreference dp = new AccountDiffPreference(diffPrefs);
-
-    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
-    f.setDiffPrefs(dp);
-    f.setFileName(b.getPath());
-    f.setEditFilter(PrettyFormatter.B);
-    f.setEditList(edits);
-
-    if (dp.isSyntaxHighlighting() && a.isWholeFile() && !b.isWholeFile()) {
-      f.format(b.apply(a, edits));
-    } else {
-      f.format(b);
-    }
-    return f;
-  }
-
   public List<Edit> getEdits() {
     return edits;
   }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetDetail.java
index 64e666e..a2debf2 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetDetail.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
index 273f18d..075d558 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchSetPublishDetail.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAccess.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAccess.java
index 2a80d52..f935c03 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAccess.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAccess.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
index 4d10a42..1b504b0 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectAdminService.java
@@ -15,13 +15,13 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
index 7d59c8b..1d88cf8 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectDetail.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 public class ProjectDetail {
   public Project project;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java
index 8f22936..dfef806 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 public class ProjectInfo {
   protected Project.NameKey key;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectList.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectList.java
index 0da45b2..8511460 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectList.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectList.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/RefConfigSection.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/RefConfigSection.java
new file mode 100644
index 0000000..490378e
--- /dev/null
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/RefConfigSection.java
@@ -0,0 +1,48 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.common.data;
+
+public abstract class RefConfigSection {
+  /** Pattern that matches all references in a project. */
+  public static final String ALL = "refs/*";
+
+  /** Pattern that matches all branches in a project. */
+  public static final String HEADS = "refs/heads/*";
+
+  /** Prefix that triggers a regular expression pattern. */
+  public static final String REGEX_PREFIX = "^";
+
+  /** @return true if the name is likely to be a valid reference section name. */
+  public static boolean isValid(String name) {
+    return name.startsWith("refs/") || name.startsWith("^refs/");
+  }
+
+  protected String name;
+
+  public RefConfigSection() {
+  }
+
+  public RefConfigSection(String name) {
+    setName(name);
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java
index 9378526..001f9b4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/SubmitRecord.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/SubmitRecord.java
index 953ae99..5049ba4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/SubmitRecord.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/SubmitRecord.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java
index 12c8b60..85518b2 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java
@@ -14,12 +14,13 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 
@@ -35,13 +36,20 @@
       AsyncCallback<List<GroupReference>> callback);
 
   /**
+   * @see #suggestChangeReviewer(com.google.gerrit.reviewdb.client.Change.Id, String, int, AsyncCallback)
+   */
+  @Deprecated
+  void suggestReviewer(Project.NameKey project, String query, int limit,
+      AsyncCallback<List<ReviewerInfo>> callback);
+
+  /**
    * Suggests reviewers. A reviewer can be a user or a group. Inactive users,
    * the system groups {@link AccountGroup#ANONYMOUS_USERS} and
    * {@link AccountGroup#REGISTERED_USERS} and groups that have more than the
    * configured <code>addReviewer.maxAllowed</code> members are not suggested as
    * reviewers.
-   * @param project the project for which reviewers should be suggested
+   * @param changeId the change for which reviewers should be suggested
    */
-  void suggestReviewer(Project.NameKey project, String query, int limit,
+  void suggestChangeReviewer(Change.Id changeId, String query, int limit,
       AsyncCallback<List<ReviewerInfo>> callback);
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/SystemInfoService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/SystemInfoService.java
index b008ee7..78ccca1 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/SystemInfoService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/SystemInfoService.java
@@ -15,13 +15,13 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.AllowCrossSiteRequest;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.AllowCrossSiteRequest;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 import java.util.List;
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ToggleStarRequest.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ToggleStarRequest.java
index 32178fb..c9ba72f 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ToggleStarRequest.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ToggleStarRequest.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 import java.util.HashSet;
 import java.util.Set;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidNameException.java b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidNameException.java
index 5eb6e3f..d975aef 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidNameException.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidNameException.java
@@ -23,4 +23,8 @@
   public InvalidNameException() {
     super(MESSAGE);
   }
+
+  public InvalidNameException(String invalidName) {
+    super(MESSAGE + ": " + invalidName);
+  }
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java
index 55d490c..f1c35a8 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.errors;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 /** Error indicating the SSH user name does not match {@link Account#USER_NAME_PATTERN} pattern. */
 public class InvalidUserNameException extends Exception {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java b/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
index 179bc3a..ade0d98 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.common.errors;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 /** Indicates the account group does not exist. */
 public class NoSuchGroupException extends Exception {
diff --git a/gerrit-ehcache/.gitignore b/gerrit-ehcache/.gitignore
index 903c6c8..20251d4 100644
--- a/gerrit-ehcache/.gitignore
+++ b/gerrit-ehcache/.gitignore
@@ -1,4 +1,5 @@
 /target
 /.classpath
 /.project
+/.settings/org.eclipse.m2e.core.prefs
 /.settings/org.maven.ide.eclipse.prefs
diff --git a/gerrit-ehcache/pom.xml b/gerrit-ehcache/pom.xml
index 417a978..839c52b0 100644
--- a/gerrit-ehcache/pom.xml
+++ b/gerrit-ehcache/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-ehcache</artifactId>
diff --git a/gerrit-gwtdebug/pom.xml b/gerrit-gwtdebug/pom.xml
index 33b6851..734f645 100644
--- a/gerrit-gwtdebug/pom.xml
+++ b/gerrit-gwtdebug/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-gwtdebug</artifactId>
diff --git a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java b/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
index 1834cdf..d23aa35 100644
--- a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
+++ b/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
@@ -23,11 +23,11 @@
 
 import org.mortbay.component.AbstractLifeCycle;
 import org.mortbay.jetty.AbstractConnector;
+import org.mortbay.jetty.HttpFields.Field;
 import org.mortbay.jetty.Request;
 import org.mortbay.jetty.RequestLog;
 import org.mortbay.jetty.Response;
 import org.mortbay.jetty.Server;
-import org.mortbay.jetty.HttpFields.Field;
 import org.mortbay.jetty.handler.RequestLogHandler;
 import org.mortbay.jetty.nio.SelectChannelConnector;
 import org.mortbay.jetty.webapp.WebAppClassLoader;
diff --git a/gerrit-gwtui/pom.xml b/gerrit-gwtui/pom.xml
index b09b8e3..f14daf6 100644
--- a/gerrit-gwtui/pom.xml
+++ b/gerrit-gwtui/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-gwtui</artifactId>
@@ -37,7 +37,6 @@
     <dependency>
       <groupId>com.google.gwt</groupId>
       <artifactId>gwt-user</artifactId>
-      <version>${gwtVersion}</version>
     </dependency>
 
     <dependency>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index 2e8cd5e..3aee0e2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -68,12 +68,12 @@
 import com.google.gerrit.common.auth.SignInMode;
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.data.PatchSetDetail;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.RunAsyncCallback;
 import com.google.gwt.user.client.Window;
@@ -81,20 +81,34 @@
 
 public class Dispatcher {
   public static String toPatchSideBySide(final Patch.Key id) {
-    return toPatch("", id);
+    return toPatch("", null, id);
+  }
+
+  public static String toPatchSideBySide(PatchSet.Id diffBase, Patch.Key id) {
+    return toPatch("", diffBase, id);
   }
 
   public static String toPatchUnified(final Patch.Key id) {
-    return toPatch("unified", id);
+    return toPatch("unified", null, id);
   }
 
-  private static String toPatch(String type, final Patch.Key id) {
+  public static String toPatchUnified(PatchSet.Id diffBase, Patch.Key id) {
+    return toPatch("unified", diffBase, id);
+  }
+
+  private static String toPatch(String type, PatchSet.Id diffBase, Patch.Key id) {
     PatchSet.Id ps = id.getParentKey();
     Change.Id c = ps.getParentKey();
-    if (type != null && !type.isEmpty()) {
-      type = "," + type;
+    StringBuilder p = new StringBuilder();
+    p.append("/c/").append(c).append("/");
+    if (diffBase != null) {
+      p.append(diffBase.get()).append("..");
     }
-    return "/c/" + c + "/" + ps.get() + "/" + KeyUtil.encode(id.get()) + type;
+    p.append(ps.get()).append("/").append(KeyUtil.encode(id.get()));
+    if (type != null && !type.isEmpty()) {
+      p.append(",").append(type);
+    }
+    return p.toString();
   }
 
   public static String toPatch(final PatchScreen.Type type, final Patch.Key id) {
@@ -387,10 +401,20 @@
       rest = "";
     }
 
-    PatchSet.Id ps = new PatchSet.Id(id, Integer.parseInt(psIdStr));
+    PatchSet.Id base;
+    PatchSet.Id ps;
+    int dotdot = psIdStr.indexOf("..");
+    if (1 <= dotdot) {
+      base = new PatchSet.Id(id, Integer.parseInt(psIdStr.substring(0, dotdot)));
+      ps = new PatchSet.Id(id, Integer.parseInt(psIdStr.substring(dotdot + 2)));
+    } else {
+      base = null;
+      ps = new PatchSet.Id(id, Integer.parseInt(psIdStr));
+    }
+
     if (!rest.isEmpty()) {
       Patch.Key p = new Patch.Key(ps, rest);
-      patch(token, p, 0, null, null, panel);
+      patch(token, base, p, 0, null, null, panel);
     } else {
       if (panel == null) {
         Gerrit.display(token, new ChangeScreen(ps));
@@ -415,24 +439,23 @@
     }.onSuccess();
   }
 
-  public static void patch(String token, final Patch.Key id,
-      final int patchIndex, final PatchSetDetail patchSetDetail,
-      final PatchTable patchTable, final PatchScreen.TopView topView) {
-    patch(token, id, patchIndex, patchSetDetail, patchTable, topView, null);
+  public static void patch(String token, PatchSet.Id base, Patch.Key id,
+      int patchIndex, PatchSetDetail patchSetDetail,
+      PatchTable patchTable, PatchScreen.TopView topView) {
+    patch(token, base, id, patchIndex, patchSetDetail, patchTable, topView, null);
   }
 
-  public static void patch(String token, final Patch.Key id,
-      final int patchIndex, final PatchSetDetail patchSetDetail,
-      final PatchTable patchTable, final String panelType) {
-    patch(token, id, patchIndex, patchSetDetail, patchTable,
+  public static void patch(String token, PatchSet.Id base, Patch.Key id,
+      int patchIndex, PatchSetDetail patchSetDetail,
+      PatchTable patchTable, String panelType) {
+    patch(token, base, id, patchIndex, patchSetDetail, patchTable,
         null, panelType);
   }
 
-  public static void patch(String token, final Patch.Key id,
+  public static void patch(String token, final PatchSet.Id baseId, final Patch.Key id,
       final int patchIndex, final PatchSetDetail patchSetDetail,
       final PatchTable patchTable, final PatchScreen.TopView topView,
       final String panelType) {
-
     final PatchScreen.TopView top =  topView == null ?
         Gerrit.getPatchScreenTopView() : topView;
 
@@ -455,7 +478,8 @@
                 patchIndex, //
                 patchSetDetail, //
                 patchTable, //
-                top //
+                top, //
+                baseId //
             );
           } else if ("unified".equals(panel)) {
             return new PatchScreen.Unified( //
@@ -463,7 +487,8 @@
                 patchIndex, //
                 patchSetDetail, //
                 patchTable, //
-                top //
+                top, //
+                baseId //
             );
           }
         }
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 16a2d35..e578eae 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
@@ -15,8 +15,8 @@
 package com.google.gerrit.client;
 
 import com.google.gerrit.common.data.AccountInfo;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.i18n.client.DateTimeFormat;
 
 import java.util.Date;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index c04167e..6dbfeee 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -29,12 +29,13 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.auth.SignInMode;
 import com.google.gerrit.common.data.GerritConfig;
+import com.google.gerrit.common.data.GitwebConfig;
 import com.google.gerrit.common.data.HostPageData;
 import com.google.gerrit.common.data.SystemInfoService;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gwt.core.client.EntryPoint;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
@@ -53,10 +54,10 @@
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.clippy.client.CopyableLabel;
 import com.google.gwtexpui.user.client.UserAgent;
 import com.google.gwtexpui.user.client.ViewSite;
@@ -211,6 +212,11 @@
     return myConfig;
   }
 
+  public static GitwebLink getGitwebLink() {
+    GitwebConfig gw = getConfig().getGitwebLink();
+    return gw != null ? new GitwebLink(gw) : null;
+  }
+
   /** Site theme information (site specific colors)/ */
   public static HostPageData.Theme getTheme() {
     return myTheme;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index f2a3d3e..ee107d0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -81,7 +81,7 @@
   String searchHint();
   String searchButton();
 
-  String rpcStatusLoading();
+  String rpcStatusWorking();
 
   String sectionNavigation();
   String sectionActions();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index 3880f59..41db3d5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -25,7 +25,7 @@
 <p>To continue, please sign-in again.</p>
 
 notFoundTitle = Not Found
-notFoundBody = The page you requested was not found.
+notFoundBody = The page you requested was not found, or you do not have permission to view this page.
 nameAlreadyUsedBody = The name is already in use.
 noSuchAccountTitle = Code Review - Unknown User
 
@@ -64,7 +64,7 @@
 searchHint = Change #, SHA-1, tr:id, owner:email or reviewer:email
 searchButton = Search
 
-rpcStatusLoading = Loading ...
+rpcStatusWorking = Working ...
 
 sectionNavigation = Navigation
 sectionActions = Actions
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index 70cfdbc..a8315d8 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -18,10 +18,6 @@
 
 public interface GerritCss extends CssResource {
   String greenCheckClass();
-  String abandonChangeDialog();
-  String abandonMessage();
-  String revertChangeDialog();
-  String revertMessage();
   String accountContactOnFile();
   String accountContactPrivacyDetails();
   String accountDashboard();
@@ -58,6 +54,8 @@
   String changeTypeCell();
   String changeid();
   String closedstate();
+  String commentedActionDialog();
+  String commentedActionMessage();
   String commentCell();
   String commentEditorPanel();
   String commentHolder();
@@ -124,7 +122,6 @@
   String groupNamePanel();
   String groupNameTextBox();
   String groupOptionsPanel();
-  String groupOptionsNotificationsDescriptionPanel();
   String groupOwnerPanel();
   String groupOwnerTextBox();
   String groupTypePanel();
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GitwebLink.java
similarity index 85%
rename from gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java
rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/GitwebLink.java
index 5ee1b6e..5f62a52 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GitwebLink.java
@@ -12,11 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.common.data;
+package com.google.gerrit.client;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.common.data.GitWebType;
+import com.google.gerrit.common.data.ParameterizedString;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.http.client.URL;
 
 import java.util.HashMap;
@@ -28,12 +30,9 @@
 
   protected GitWebType type;
 
-  protected GitwebLink() {
-  }
-
-  public GitwebLink(final String base, final GitWebType gitWebType) {
-    baseUrl = base;
-    type = gitWebType;
+  public GitwebLink(com.google.gerrit.common.data.GitwebConfig link) {
+    baseUrl = link.baseUrl;
+    type = link.type;
   }
 
   public String getLinkName() {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java
index accec0a..bd3d483 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/HostPageDataService.java
@@ -15,11 +15,11 @@
 package com.google.gerrit.client;
 
 import com.google.gerrit.common.data.HostPageData;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.HostPageCache;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
-import com.google.gwtjsonrpc.client.RpcImpl;
-import com.google.gwtjsonrpc.client.RpcImpl.Version;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.HostPageCache;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RpcImpl;
+import com.google.gwtjsonrpc.common.RpcImpl.Version;
 
 @RpcImpl(version = Version.V2_0)
 interface HostPageDataService extends RemoteJsonService {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java
index 21c5154..76ce384 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/RpcStatus.java
@@ -47,7 +47,7 @@
     p.add(r);
 
     loading = new InlineLabel();
-    loading.setText(Gerrit.C.rpcStatusLoading());
+    loading.setText(Gerrit.C.rpcStatusWorking());
     loading.setStyleName(Gerrit.RESOURCES.css().rpcStatus());
     loading.addStyleName(Gerrit.RESOURCES.css().rpcStatusLoading());
     loading.setVisible(false);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
index d1f1296..e3d8468 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.changes.QueryScreen;
 import com.google.gerrit.client.ui.HintTextBox;
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelFull.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelFull.java
index b7a00ad..4b8f0e2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelFull.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelFull.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ContactInformation;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ContactInformation;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
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 8c6ba2e..4e0b3b2 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
@@ -18,27 +18,27 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.OnEditEnabler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ContactInformation;
-import com.google.gerrit.reviewdb.Account.FieldName;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.client.ContactInformation;
+import com.google.gerrit.reviewdb.client.Account.FieldName;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.LocaleInfo;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.FormPanel;
+import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 import com.google.gwtexpui.user.client.AutoCenterDialogBox;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
index 54de472..af619a8 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java
@@ -21,10 +21,10 @@
 import com.google.gerrit.client.ui.Hyperlink;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.AgreementInfo;
-import com.google.gerrit.reviewdb.AbstractAgreement;
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountGroupAgreement;
-import com.google.gerrit.reviewdb.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.AbstractAgreement;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java
index f3816f2..899aa03 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.client.ui.FancyFlexTable;
 import com.google.gerrit.common.auth.SignInMode;
 import com.google.gerrit.common.auth.openid.OpenIdUrls;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java
index 65525eb..abb1f4d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.client.account;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.i18n.client.LocaleInfo;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
index 1415167..84e87aa 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.client.account;
 
-import static com.google.gerrit.reviewdb.AccountGeneralPreferences.DEFAULT_PAGESIZE;
-import static com.google.gerrit.reviewdb.AccountGeneralPreferences.PAGESIZE_CHOICES;
+import static com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DEFAULT_PAGESIZE;
+import static com.google.gerrit.reviewdb.client.AccountGeneralPreferences.PAGESIZE_CHOICES;
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -33,7 +33,7 @@
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.Date;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java
index 65c2590..165168d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java
@@ -17,7 +17,7 @@
 import static com.google.gerrit.client.FormatUtil.mediumFormat;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java
index b3bd0cb..c158c2c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchesTable.java
@@ -19,16 +19,16 @@
 import com.google.gerrit.client.ui.FancyFlexTable;
 import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gerrit.common.data.AccountProjectWatchInfo;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change.Status;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change.Status;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.HashSet;
 import java.util.List;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
index 30638da..154e2ce 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
@@ -22,10 +22,10 @@
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.AgreementInfo;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountGroupAgreement;
-import com.google.gerrit.reviewdb.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
@@ -34,7 +34,7 @@
 import com.google.gwt.http.client.RequestCallback;
 import com.google.gwt.http.client.RequestException;
 import com.google.gwt.http.client.Response;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.FormPanel;
@@ -45,7 +45,7 @@
 import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.HashSet;
 import java.util.List;
@@ -250,7 +250,7 @@
     String url = cla.getAgreementUrl();
     if (url != null && url.length() > 0) {
       agreementGroup.setVisible(true);
-      agreementHtml.setText(Gerrit.C.rpcStatusLoading());
+      agreementHtml.setText(Gerrit.C.rpcStatusWorking());
       if (!url.startsWith("http:") && !url.startsWith("https:")) {
         url = GWT.getHostPageBaseURL() + url;
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java
index 605d7f3..084ea6f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java
@@ -19,8 +19,8 @@
 import com.google.gerrit.client.ui.InlineHyperlink;
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Account.FieldName;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Account.FieldName;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.FormPanel;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java
index c8a1485..73127f0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.data.SshHostKey;
 import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -39,7 +39,7 @@
 import com.google.gwtexpui.clippy.client.CopyableLabel;
 import com.google.gwtexpui.globalkey.client.NpTextArea;
 import com.google.gwtjsonrpc.client.RemoteJsonException;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.Collections;
 import java.util.HashSet;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
index 76bc212..0666bb3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
@@ -19,7 +19,7 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.OnEditEnabler;
 import com.google.gerrit.common.errors.InvalidUserNameException;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
@@ -31,7 +31,7 @@
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwtexpui.clippy.client.CopyableLabel;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 class UsernameField extends Composite {
   private CopyableLabel userNameLbl;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java
index 4e54e85..1164efc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.AccountScreen;
 import com.google.gerrit.common.PageLinks;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 public class ValidateEmailScreen extends AccountScreen {
   private final String magicToken;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java
index f4257b5..72ac1a4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.ProjectAccess;
+import com.google.gerrit.common.data.RefConfigSection;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
@@ -122,7 +123,8 @@
   void onDeleteSection(ClickEvent event) {
     isDeleted = true;
 
-    if (name.isVisible() && AccessSection.isAccessSection(name.getValue())){
+    if (name.isVisible()
+        && RefConfigSection.isValid(name.getValue())) {
       deletedName.setInnerText(Util.M.deletedReference(name.getValue()));
 
     } else {
@@ -185,7 +187,7 @@
     name.setEnabled(!readOnly);
     deleteSection.setVisible(!readOnly);
 
-    if (AccessSection.isAccessSection(value.getName())) {
+    if (RefConfigSection.isValid(value.getName())) {
       name.setVisible(true);
       name.setIgnoreEditorValue(false);
       sectionType.setInnerText(Util.C.sectionTypeReference());
@@ -225,8 +227,9 @@
           perms.add(varName);
         }
       }
-    } else if (AccessSection.isAccessSection(value.getName())) {
-      for (ApprovalType t : Gerrit.getConfig().getApprovalTypes().getApprovalTypes()) {
+    } else if (RefConfigSection.isValid(value.getName())) {
+      for (ApprovalType t : Gerrit.getConfig().getApprovalTypes()
+          .getApprovalTypes()) {
         String varName = Permission.LABEL + t.getCategory().getLabelName();
         if (value.getPermission(varName) == null) {
           perms.add(varName);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
index 5ce90e7..936bfe5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupInfoScreen.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.data.GroupOptions;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -43,7 +43,7 @@
 import com.google.gwtexpui.clippy.client.CopyableLabel;
 import com.google.gwtexpui.globalkey.client.NpTextArea;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.List;
 
@@ -70,9 +70,7 @@
   private Button externalNameSearch;
   private Grid externalMatches;
 
-  private Panel groupOptionsPanel;
   private CheckBox visibleToAllCheckBox;
-  private CheckBox emailOnlyAuthors;
   private Button saveGroupOptions;
 
   public AccountGroupInfoScreen(final GroupDetail toShow, final String token) {
@@ -100,7 +98,6 @@
     externalNameFilter.setEnabled(canModify);
     externalNameSearch.setEnabled(canModify);
     visibleToAllCheckBox.setEnabled(canModify);
-    emailOnlyAuthors.setEnabled(canModify);
   }
 
   private void initUUID() {
@@ -207,20 +204,14 @@
   }
 
   private void initGroupOptions() {
-    groupOptionsPanel = new VerticalPanel();
-    groupOptionsPanel.setStyleName(Gerrit.RESOURCES.css().groupOptionsPanel());
-    groupOptionsPanel.add(new SmallHeading(Util.C.headingGroupOptions()));
-
-    visibleToAllCheckBox = new CheckBox(Util.C.isVisibleToAll());
-    groupOptionsPanel.add(visibleToAllCheckBox);
-
-    emailOnlyAuthors = new CheckBox(Util.C.emailOnlyAuthors());
+    final VerticalPanel groupOptionsPanel = new VerticalPanel();
 
     final VerticalPanel vp = new VerticalPanel();
-    vp.setStyleName(Gerrit.RESOURCES.css()
-        .groupOptionsNotificationsDescriptionPanel());
-    vp.add(new Label(Util.C.descriptionNotifications()));
-    vp.add(emailOnlyAuthors);
+    vp.setStyleName(Gerrit.RESOURCES.css().groupOptionsPanel());
+    vp.add(new SmallHeading(Util.C.headingGroupOptions()));
+
+    visibleToAllCheckBox = new CheckBox(Util.C.isVisibleToAll());
+    vp.add(visibleToAllCheckBox);
     groupOptionsPanel.add(vp);
 
     saveGroupOptions = new Button(Util.C.buttonSaveGroupOptions());
@@ -229,8 +220,7 @@
       @Override
       public void onClick(final ClickEvent event) {
         final GroupOptions groupOptions =
-            new GroupOptions(visibleToAllCheckBox.getValue(),
-              emailOnlyAuthors.getValue());
+            new GroupOptions(visibleToAllCheckBox.getValue());
         Util.GROUP_SVC.changeGroupOptions(getGroupId(), groupOptions,
             new GerritCallback<VoidResult>() {
               public void onSuccess(final VoidResult result) {
@@ -245,7 +235,6 @@
 
     final OnEditEnabler enabler = new OnEditEnabler(saveGroupOptions);
     enabler.listenTo(visibleToAllCheckBox);
-    enabler.listenTo(emailOnlyAuthors);
   }
 
   private void initGroupType() {
@@ -460,7 +449,6 @@
     descTxt.setText(group.getDescription());
 
     visibleToAllCheckBox.setValue(group.isVisibleToAll());
-    emailOnlyAuthors.setValue(group.isEmailOnlyAuthors());
 
     switch (group.getType()) {
       case LDAP:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
index 4e13ab5..b5cca86 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupMembersScreen.java
@@ -27,10 +27,10 @@
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.data.GroupInfo;
 import com.google.gerrit.common.data.GroupInfoCache;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Button;
@@ -38,7 +38,7 @@
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Panel;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.HashSet;
 import java.util.List;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
index 2c7f110..9ac6c9a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
@@ -18,7 +18,7 @@
 
 import com.google.gerrit.client.ui.MenuScreen;
 import com.google.gerrit.common.data.GroupDetail;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 public abstract class AccountGroupScreen extends MenuScreen {
   public static final String INFO = "info";
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
index c928eb9..9250ca3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
@@ -44,8 +44,6 @@
   String requireChangeID();
   String headingGroupOptions();
   String isVisibleToAll();
-  String emailOnlyAuthors();
-  String descriptionNotifications();
   String buttonSaveGroupOptions();
   String suggestedGroupLabel();
   String parentSuggestions();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index f2a8ad6..389ed2c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -29,9 +29,6 @@
 parentSuggestions = Parent Suggestion
 columnProjectName = Project Name
 
-emailOnlyAuthors = Authors
-descriptionNotifications = Send email notifications about comments and actions by users in this group only to:
-
 headingGroupUUID = Group UUID
 headingOwner = Owners
 headingDescription = Description
@@ -128,6 +125,7 @@
   createAccount, \
   createGroup, \
   createProject, \
+  emailReviewers, \
   flushCaches, \
   killTask, \
   priority, \
@@ -140,6 +138,7 @@
 createAccount = Create Account
 createGroup = Create Group
 createProject = Create Project
+emailReviewers = Email Reviewers
 flushCaches = Flush Caches
 killTask = Kill Task
 priority = Priority
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
index 7f2ae07..0ce2d77 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
 import com.google.gerrit.client.ui.ProjectsTable;
 import com.google.gerrit.client.ui.Screen;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
@@ -36,7 +36,7 @@
 import com.google.gwt.user.client.ui.SuggestBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.List;
 
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 f1d9ac1..9d62d34 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
@@ -23,7 +23,7 @@
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.GroupList;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gwt.event.dom.client.BlurEvent;
 import com.google.gwt.event.dom.client.BlurHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java
index 7585f8a..7f73226 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupTable.java
@@ -19,7 +19,7 @@
 import com.google.gerrit.client.ui.Hyperlink;
 import com.google.gerrit.client.ui.NavigationTable;
 import com.google.gerrit.common.data.GroupDetail;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
@@ -32,6 +32,8 @@
 
 
 public class GroupTable extends NavigationTable<AccountGroup> {
+  private static final int NUM_COLS = 5;
+
   private final boolean enableLink;
 
   public GroupTable(final boolean enableLink) {
@@ -52,8 +54,7 @@
     table.setText(0, 2, Util.C.columnGroupDescription());
     table.setText(0, 3, Util.C.headingOwner());
     table.setText(0, 4, Util.C.columnGroupType());
-    table.setText(0, 5, Util.C.columnGroupNotifications());
-    table.setText(0, 6, Util.C.columnGroupVisibleToAll());
+    table.setText(0, 5, Util.C.columnGroupVisibleToAll());
     table.addClickHandler(new ClickHandler() {
       @Override
       public void onClick(ClickEvent event) {
@@ -66,12 +67,9 @@
     });
 
     final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
-    fmt.addStyleName(0, 6, Gerrit.RESOURCES.css().dataHeader());
+    for (int i = 1; i <= NUM_COLS; i++) {
+      fmt.addStyleName(0, i, Gerrit.RESOURCES.css().dataHeader());
+    }
   }
 
   @Override
@@ -107,21 +105,15 @@
     table.setText(row, 2, k.getDescription());
     table.setText(row, 3, detail.ownerGroup.getName());
     table.setText(row, 4, k.getType().toString());
-    if (k.isEmailOnlyAuthors()) {
-      table.setWidget(row, 5, new Image(Gerrit.RESOURCES.greenCheck()));
-    }
     if (k.isVisibleToAll()) {
-      table.setWidget(row, 6, new Image(Gerrit.RESOURCES.greenCheck()));
+      table.setWidget(row, 5, new Image(Gerrit.RESOURCES.greenCheck()));
     }
 
     final FlexCellFormatter fmt = table.getFlexCellFormatter();
-    fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
     fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().groupName());
-    fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
-    fmt.addStyleName(row, 6, Gerrit.RESOURCES.css().dataCell());
+    for (int i = 1; i <= NUM_COLS; i++) {
+      fmt.addStyleName(row, i, Gerrit.RESOURCES.css().dataCell());
+    }
 
     setRowItem(row, k);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
index a11cd5c..d10afd1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
+import com.google.gerrit.common.data.RefConfigSection;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
@@ -114,7 +115,8 @@
     rules = ListEditor.of(new RuleEditorSource());
 
     exclusiveGroup.setEnabled(!readOnly);
-    exclusiveGroup.setVisible(AccessSection.isAccessSection(section.getName()));
+    exclusiveGroup.setVisible(RefConfigSection
+        .isValid(section.getName()));
 
     if (readOnly) {
       addContainer.removeFromParent();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java
index e6e11b0..e3bf555 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessEditor.java
@@ -16,12 +16,12 @@
 
 import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.GitwebLink;
 import com.google.gerrit.client.ui.Hyperlink;
 import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GitwebLink;
 import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.dom.client.Style.Display;
@@ -110,7 +110,7 @@
       inheritsFrom.getStyle().setDisplay(Display.NONE);
     }
 
-    final GitwebLink c = Gerrit.getConfig().getGitwebLink();
+    final GitwebLink c = Gerrit.getGitwebLink();
     if (value.isConfigVisible() && c != null) {
       history.getStyle().setDisplay(Display.BLOCK);
       gitweb.setText(c.getLinkName());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
index fc864de..1ed919b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
@@ -19,7 +19,7 @@
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ProjectAccess;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.editor.client.SimpleBeanEditorDriver;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
index 7c51700..f3ecbb3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
@@ -17,16 +17,16 @@
 import com.google.gerrit.client.ConfirmationCallback;
 import com.google.gerrit.client.ConfirmationDialog;
 import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.GitwebLink;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.FancyFlexTable;
 import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.common.data.GitwebLink;
 import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.common.errors.InvalidRevisionException;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -226,7 +226,7 @@
       fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
       fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
       fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
-      if (Gerrit.getConfig().getGitwebLink() != null) {
+      if (Gerrit.getGitwebLink() != null) {
         fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
       }
     }
@@ -293,7 +293,7 @@
     }
 
     void populate(final int row, final Branch k) {
-      final GitwebLink c = Gerrit.getConfig().getGitwebLink();
+      final GitwebLink c = Gerrit.getGitwebLink();
 
       if (k.getCanDelete()) {
         table.setWidget(row, 1, new CheckBox());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index a85fe0e..944a169 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -20,8 +20,8 @@
 import com.google.gerrit.client.ui.OnEditEnabler;
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.data.ProjectDetail;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.SubmitType;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
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 d89676c..3599c3c 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
@@ -22,7 +22,7 @@
 import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ProjectList;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java
index 392f295..ccfe2e6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java
@@ -18,7 +18,7 @@
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.ui.MenuScreen;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 public abstract class ProjectScreen extends MenuScreen {
   public static final String INFO = "info";
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java
index e07829e..6ff9bff 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/RangeBox.java
@@ -20,8 +20,8 @@
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.IntegerBox;
-import com.google.gwt.user.client.ui.ValueListBox;
 import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
+import com.google.gwt.user.client.ui.ValueListBox;
 
 import java.io.IOException;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java
index e3bcab1..aa5b7b6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/Util.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.data.GroupAdminService;
 import com.google.gerrit.common.data.ProjectAdminService;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.GWT;
 import com.google.gwtjsonrpc.client.JsonUtil;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
index 2991dc9..ccdd1ec 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassMessages.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.client.auth.userpass;
 
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gwt.i18n.client.Messages;
 
 public interface UserPassMessages extends Messages {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
index f5f3245..1d881b6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/AccountDashboardScreen.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.AccountDashboardInfo;
 import com.google.gerrit.common.data.AccountInfo;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 
 public class AccountDashboardScreen extends Screen implements ChangeListScreen {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
index d775bbc..09716cc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
@@ -21,9 +21,9 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.patches.PatchUtil;
 import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.ReviewerSuggestOracle;
 import com.google.gerrit.client.ui.AccountDashboardLink;
 import com.google.gerrit.client.ui.AddMemberBox;
+import com.google.gerrit.client.ui.ReviewerSuggestOracle;
 import com.google.gerrit.common.data.AccountInfoCache;
 import com.google.gerrit.common.data.ApprovalDetail;
 import com.google.gerrit.common.data.ApprovalType;
@@ -31,9 +31,9 @@
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.ReviewerResult;
 import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.DOM;
@@ -134,13 +134,12 @@
   }
 
   void display(ChangeDetail detail) {
-    reviewerSuggestOracle.setProject(detail.getChange().getProject());
+    changeId = detail.getChange().getId();
+    reviewerSuggestOracle.setChange(changeId);
 
     List<String> columns = new ArrayList<String>();
     List<ApprovalDetail> rows = detail.getApprovals();
 
-    changeId = detail.getChange().getId();
-
     final Element missingList = missing.getElement();
     while (DOM.getChildCount(missingList) > 0) {
       DOM.removeChild(missingList, DOM.getChild(missingList, 0));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeCache.java
new file mode 100644
index 0000000..27f76f6
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeCache.java
@@ -0,0 +1,71 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.changes;
+
+import com.google.gerrit.client.ui.ListenableValue;
+import com.google.gerrit.common.data.ChangeInfo;
+import com.google.gerrit.reviewdb.client.Change;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** A Cache to store common client side data by change */
+public class ChangeCache {
+  private static Map<Change.Id, ChangeCache> caches =
+    new HashMap<Change.Id, ChangeCache>();
+
+  public static ChangeCache get(Change.Id chg) {
+    ChangeCache cache = caches.get(chg);
+    if (cache == null) {
+      cache = new ChangeCache(chg);
+      caches.put(chg, cache);
+    }
+    return cache;
+  }
+
+  private Change.Id changeId;
+  private ChangeDetailCache detail;
+  private ListenableValue<ChangeInfo> info;
+  private StarCache starred;
+
+  protected ChangeCache(Change.Id chg) {
+    changeId = chg;
+  }
+
+  public Change.Id getChangeId() {
+    return changeId;
+  }
+
+  public ChangeDetailCache getChangeDetailCache() {
+    if (detail == null) {
+      detail = new ChangeDetailCache(changeId);
+    }
+    return detail;
+  }
+
+  public ListenableValue<ChangeInfo> getChangeInfoCache() {
+    if (info == null) {
+      info = new ListenableValue<ChangeInfo>();
+    }
+    return info;
+  }
+
+  public StarCache getStarCache() {
+    if (starred == null) {
+      starred = new StarCache(changeId);
+    }
+    return starred;
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index 3cddd2b..3372096 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -111,19 +111,20 @@
   String patchSetInfoParents();
   String initialCommit();
 
+  String buttonRebaseChange();
+
   String buttonRevertChangeBegin();
   String buttonRevertChangeSend();
-  String buttonRevertChangeCancel();
   String headingRevertMessage();
   String revertChangeTitle();
 
   String buttonAbandonChangeBegin();
   String buttonAbandonChangeSend();
-  String buttonAbandonChangeCancel();
   String headingAbandonMessage();
   String abandonChangeTitle();
   String oldVersionHistory();
   String baseDiffItem();
+  String autoMerge();
 
   String buttonReview();
   String buttonPublishCommentsSend();
@@ -134,7 +135,6 @@
 
   String buttonRestoreChangeBegin();
   String restoreChangeTitle();
-  String buttonRestoreChangeCancel();
   String headingRestoreMessage();
   String buttonRestoreChangeSend();
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 35991f4..ad70674 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -90,21 +90,21 @@
 
 buttonAbandonChangeBegin = Abandon Change
 buttonAbandonChangeSend = Abandon Change
-buttonAbandonChangeCancel = Cancel
 headingAbandonMessage = Abandon Message:
 abandonChangeTitle = Code Review - Abandon Change
 oldVersionHistory = Old Version History:
 baseDiffItem = Base
+autoMerge = Auto Merge
+
+buttonRebaseChange = Rebase Change
 
 buttonRevertChangeBegin = Revert Change
 buttonRevertChangeSend = Revert Change
-buttonRevertChangeCancel = Cancel
 headingRevertMessage = Revert Commit Message:
 revertChangeTitle = Code Review - Revert Merged Change
 
 buttonRestoreChangeBegin = Restore Change
 restoreChangeTitle = Code Review - Restore Change
-buttonRestoreChangeCancel = Cancel
 headingRestoreMessage = Restore Message:
 buttonRestoreChangeSend = Restore Change
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
index 0532326..9282709 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.client.changes;
 
 import com.google.gerrit.common.data.AccountInfoCache;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java
new file mode 100644
index 0000000..bb28e11
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDetailCache.java
@@ -0,0 +1,79 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.changes;
+
+import com.google.gerrit.client.ui.ListenableValue;
+import com.google.gerrit.common.data.ChangeDetail;
+import com.google.gerrit.reviewdb.client.Change;
+
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwt.user.client.ui.FocusWidget;
+
+public class ChangeDetailCache extends ListenableValue<ChangeDetail> {
+  public static class GerritCallback extends
+      com.google.gerrit.client.rpc.GerritCallback<ChangeDetail> {
+    @Override
+    public void onSuccess(ChangeDetail detail) {
+      setChangeDetail(detail);
+    }
+  }
+
+  /*
+   * GerritCallback which will re-enable a FocusWidget
+   * {@link com.google.gwt.user.client.ui.FocusWidget} if we are returning
+   * with a failed result.
+   *
+   * It is up to the caller to handle the original disabling of the Widget.
+   */
+  public static class GerritWidgetCallback extends GerritCallback {
+    private FocusWidget widget;
+
+    public GerritWidgetCallback(FocusWidget widget) {
+      this.widget = widget;
+    }
+
+    @Override
+    public void onFailure(Throwable caught) {
+      widget.setEnabled(true);
+      super.onFailure(caught);
+    }
+  }
+
+  public static class IgnoreErrorCallback implements AsyncCallback<ChangeDetail> {
+    @Override
+    public void onSuccess(ChangeDetail detail) {
+      setChangeDetail(detail);
+    }
+
+    @Override
+    public void onFailure(Throwable caught) {
+    }
+  }
+
+  public static void setChangeDetail(ChangeDetail detail) {
+    Change.Id chgId = detail.getChange().getId();
+    ChangeCache.get(chgId).getChangeDetailCache().set(detail);
+  }
+
+  private final Change.Id changeId;
+
+  public ChangeDetailCache(final Change.Id chg) {
+    changeId = chg;
+  }
+
+  public void refresh() {
+    Util.DETAIL_SVC.changeDetail(changeId, new GerritCallback());
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
index eb91180..f8373cc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeInfoBlock.java
@@ -22,8 +22,8 @@
 import com.google.gerrit.client.ui.ChangeLink;
 import com.google.gerrit.client.ui.ProjectLink;
 import com.google.gerrit.common.data.AccountInfoCache;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
index 1b382a8..8d5e105 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
@@ -16,8 +16,6 @@
 
 import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.CommentPanel;
 import com.google.gerrit.client.ui.ComplexDisclosurePanel;
 import com.google.gerrit.client.ui.ExpandAllCommand;
@@ -28,17 +26,16 @@
 import com.google.gerrit.common.data.AccountInfoCache;
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.ChangeInfo;
-import com.google.gerrit.common.data.ToggleStarRequest;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Change.Status;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Change.Status;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.ui.DisclosurePanel;
@@ -53,18 +50,19 @@
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtjsonrpc.client.VoidResult;
 
 import java.sql.Timestamp;
 import java.util.List;
 
 
-public class ChangeScreen extends Screen {
+public class ChangeScreen extends Screen
+    implements ValueChangeHandler<ChangeDetail> {
   private final Change.Id changeId;
   private final PatchSet.Id openPatchSetId;
+  private ChangeDetailCache detailCache;
+  private StarCache starred;
 
   private Image starChange;
-  private boolean starred;
   private ChangeDescriptionBlock descriptionBlock;
   private ApprovalTable approvals;
 
@@ -130,7 +128,7 @@
   @Override
   protected void onLoad() {
     super.onLoad();
-    refresh();
+    detailCache.refresh();
   }
 
   @Override
@@ -156,33 +154,17 @@
     }
   }
 
-  public void refresh() {
-    Util.DETAIL_SVC.changeDetail(changeId,
-        new ScreenLoadCallback<ChangeDetail>(this) {
-          @Override
-          protected void preDisplay(final ChangeDetail r) {
-            display(r);
-          }
-
-          @Override
-          protected void postDisplay() {
-            patchSetsBlock.setRegisterKeys(true);
-          }
-        });
-  }
-
-  private void setStarred(final boolean s) {
-    if (s) {
-      starChange.setResource(Gerrit.RESOURCES.starFilled());
-    } else {
-      starChange.setResource(Gerrit.RESOURCES.starOpen());
-    }
-    starred = s;
-  }
-
   @Override
   protected void onInitUI() {
     super.onInitUI();
+
+    ChangeCache cache = ChangeCache.get(changeId);
+
+    detailCache = cache.getChangeDetailCache();
+    detailCache.addValueChangeHandler(this);
+
+    starred = cache.getStarCache();
+
     addStyleName(Gerrit.RESOURCES.css().changeScreen());
 
     keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
@@ -191,19 +173,12 @@
     keysNavigation.add(new ExpandCollapseDependencySectionKeyCommand(0, 'd', Util.C.expandCollapseDependencies()));
 
     if (Gerrit.isSignedIn()) {
-      keysAction.add(new StarKeyCommand(0, 's', Util.C.changeTableStar()));
+      keysAction.add(starred.new KeyCommand(0, 's', Util.C.changeTableStar()));
       keysAction.add(new PublishCommentsKeyCommand(0, 'r', Util.C
           .keyPublishComments()));
 
-      starChange = new Image(Gerrit.RESOURCES.starOpen());
+      starChange = starred.createStar();
       starChange.setStyleName(Gerrit.RESOURCES.css().changeScreenStarIcon());
-      starChange.setVisible(Gerrit.isSignedIn());
-      starChange.addClickHandler(new ClickHandler() {
-        @Override
-        public void onClick(final ClickEvent event) {
-          toggleStar();
-        }
-      });
       setTitleWest(starChange);
     }
 
@@ -250,7 +225,6 @@
         }
       }
     });
-    patchesList.addItem(Util.C.baseDiffItem());
 
     patchesGrid = new Grid(1, 2);
     patchesGrid.setStyleName(Gerrit.RESOURCES.css().selectPatchSetOldVersion());
@@ -258,7 +232,7 @@
     patchesGrid.setWidget(0, 1, patchesList);
     add(patchesGrid);
 
-    patchSetsBlock = new PatchSetsBlock(this);
+    patchSetsBlock = new PatchSetsBlock();
     add(patchSetsBlock);
 
     comments = new FlowPanel();
@@ -284,18 +258,16 @@
     setPageTitle(titleBuf.toString());
   }
 
-  void update(final ChangeDetail detail) {
-    display(detail);
-    patchSetsBlock.setRegisterKeys(true);
+  @Override
+  public void onValueChange(ValueChangeEvent<ChangeDetail> event) {
+    if (isAttached()) {
+      display(event.getValue());
+    }
   }
 
   private void display(final ChangeDetail detail) {
     displayTitle(detail.getChange().getKey(), detail.getChange().getSubject());
 
-    if (starChange != null) {
-      setStarred(detail.isStarred());
-    }
-
     if (Status.MERGED == detail.getChange().getStatus()) {
       includedInPanel.setVisible(true);
       includedInPanel.addOpenHandler(includedInTable);
@@ -312,6 +284,11 @@
     neededBy.display(detail.getNeededBy());
     approvals.display(detail);
 
+    if (detail.getCurrentPatchSetDetail().getInfo().getParents().size() > 1) {
+      patchesList.addItem(Util.C.autoMerge());
+    } else {
+      patchesList.addItem(Util.C.baseDiffItem());
+    }
     for (PatchSet pId : detail.getPatchSets()) {
       if (patchesList != null) {
         patchesList.addItem(Util.M.patchSetHeader(pId.getPatchSetId()), pId
@@ -344,10 +321,17 @@
     }
 
     dependenciesPanel.setOpen(depsOpen);
+
+    dependenciesPanel.getHeader().clear();
     if (outdated > 0) {
       dependenciesPanel.getHeader().add(new InlineLabel(
         Util.M.outdatedHeader(outdated)));
     }
+
+    if (!isCurrentView()) {
+      display();
+    }
+    patchSetsBlock.setRegisterKeys(true);
   }
 
   private void addComments(final ChangeDetail detail) {
@@ -417,24 +401,6 @@
     return menuBar;
   }
 
-  private void toggleStar() {
-    final boolean prior = starred;
-    setStarred(!prior);
-
-    final ToggleStarRequest req = new ToggleStarRequest();
-    req.toggle(changeId, starred);
-    Util.LIST_SVC.toggleStars(req, new GerritCallback<VoidResult>() {
-      public void onSuccess(final VoidResult result) {
-      }
-
-      @Override
-      public void onFailure(final Throwable caught) {
-        super.onFailure(caught);
-        setStarred(prior);
-      }
-    });
-  }
-
   public class UpToListKeyCommand extends KeyCommand {
     public UpToListKeyCommand(int mask, char key, String help) {
       super(mask, key, help);
@@ -457,17 +423,6 @@
     }
   }
 
-  public class StarKeyCommand extends NeedsSignInKeyCommand {
-    public StarKeyCommand(int mask, char key, String help) {
-      super(mask, key, help);
-    }
-
-    @Override
-    public void onKeyPress(final KeyPressEvent event) {
-      toggleStar();
-    }
-  }
-
   public class PublishCommentsKeyCommand extends NeedsSignInKeyCommand {
     public PublishCommentsKeyCommand(int mask, char key, String help) {
       super(mask, key, help);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 3b71ee2..5a568f1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -33,29 +33,25 @@
 import com.google.gerrit.common.data.ApprovalSummarySet;
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ChangeInfo;
-import com.google.gerrit.common.data.ToggleStarRequest;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyPressEvent;
-import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTMLTable.Cell;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.UIObject;
-import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
-import com.google.gwt.user.client.ui.HTMLTable.Cell;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwtjsonrpc.client.VoidResult;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -136,7 +132,7 @@
           return;
         }
         if (cell.getCellIndex() == C_STAR) {
-          onStarClick(cell.getRowIndex());
+          // Don't do anything (handled by star itself).
         } else if (cell.getCellIndex() == C_OWNER) {
           // Don't do anything.
         } else if (getRowItem(cell.getRowIndex()) != null) {
@@ -149,23 +145,7 @@
   protected void onStarClick(final int row) {
     final ChangeInfo c = getRowItem(row);
     if (c != null && Gerrit.isSignedIn()) {
-      final boolean prior = c.isStarred();
-      c.setStarred(!prior);
-      setStar(row, c);
-
-      final ToggleStarRequest req = new ToggleStarRequest();
-      req.toggle(c.getId(), c.isStarred());
-      Util.LIST_SVC.toggleStars(req, new GerritCallback<VoidResult>() {
-        public void onSuccess(final VoidResult result) {
-        }
-
-        @Override
-        public void onFailure(final Throwable caught) {
-          super.onFailure(caught);
-          c.setStarred(prior);
-          setStar(row, c);
-        }
-      });
+       ChangeCache.get(c.getId()).getStarCache().toggleStar();
     }
   }
 
@@ -212,10 +192,13 @@
   }
 
   private void populateChangeRow(final int row, final ChangeInfo c) {
+    ChangeCache cache = ChangeCache.get(c.getId());
+    cache.getChangeInfoCache().set(c);
+
     final String idstr = c.getKey().abbreviate();
     table.setWidget(row, C_ARROW, null);
     if (Gerrit.isSignedIn()) {
-      setStar(row, c);
+      table.setWidget(row, C_STAR, cache.getStarCache().createStar());
     }
     table.setWidget(row, C_ID, new TableChangeLink(idstr, c));
 
@@ -229,7 +212,10 @@
     if (! c.isLatest()) {
       s += " [OUTDATED]";
       table.getRowFormatter().addStyleName(row, Gerrit.RESOURCES.css().outdated());
+    } else {
+      table.getRowFormatter().removeStyleName(row, Gerrit.RESOURCES.css().outdated());
     }
+
     table.setWidget(row, C_SUBJECT, new TableChangeLink(s, c));
     table.setWidget(row, C_OWNER, link(c.getOwner()));
     table.setWidget(row, C_PROJECT, new ProjectLink(c.getProject().getKey(), c
@@ -244,22 +230,6 @@
     return AccountDashboardLink.link(accountCache, id);
   }
 
-  private void setStar(final int row, final ChangeInfo c) {
-    final ImageResource star;
-    if (c.isStarred()) {
-      star = Gerrit.RESOURCES.starFilled();
-    } else {
-      star = Gerrit.RESOURCES.starOpen();
-    }
-
-    final Widget i = table.getWidget(row, C_STAR);
-    if (i instanceof Image) {
-      ((Image) i).setResource(star);
-    } else {
-      table.setWidget(row, C_STAR, new Image(star));
-    }
-  }
-
   public void addSection(final Section s) {
     assert s.parent == null;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java
deleted file mode 100644
index 01d6299..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.client.changes;
-
-import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.SmallHeading;
-import com.google.gerrit.common.data.ChangeDetail;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.logical.shared.CloseEvent;
-import com.google.gwt.event.logical.shared.CloseHandler;
-import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwt.user.client.ui.Button;
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.PopupPanel;
-import com.google.gwtexpui.globalkey.client.GlobalKey;
-import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtexpui.user.client.AutoCenterDialogBox;
-
-public abstract class CommentedChangeActionDialog extends AutoCenterDialogBox implements CloseHandler<PopupPanel>{
-  private final FlowPanel panel;
-  private final NpTextArea message;
-  private final Button sendButton;
-  private final Button cancelButton;
-  private final PatchSet.Id psid;
-  private final AsyncCallback<ChangeDetail> callback;
-
-  private boolean buttonClicked = false;
-
-  public CommentedChangeActionDialog(final PatchSet.Id psi,
-      final AsyncCallback<ChangeDetail> callback, final String dialogTitle,
-      final String dialogHeading, final String buttonSend,
-      final String buttonCancel, final String dialogStyle,
-      final String messageStyle) {
-     this(psi, callback, dialogTitle, dialogHeading, buttonSend, buttonCancel, dialogStyle, messageStyle, null);
-  }
-
-  public CommentedChangeActionDialog(final PatchSet.Id psi,
-      final AsyncCallback<ChangeDetail> callback, final String dialogTitle,
-      final String dialogHeading, final String buttonSend,
-      final String buttonCancel, final String dialogStyle,
-      final String messageStyle, final String defaultMessage) {
-    super(/* auto hide */false, /* modal */true);
-    setGlassEnabled(true);
-
-    psid = psi;
-    this.callback = callback;
-    addStyleName(dialogStyle);
-    setText(dialogTitle);
-
-    panel = new FlowPanel();
-    add(panel);
-
-    panel.add(new SmallHeading(dialogHeading));
-
-    final FlowPanel mwrap = new FlowPanel();
-    mwrap.setStyleName(messageStyle);
-    panel.add(mwrap);
-
-    message = new NpTextArea();
-    message.setCharacterWidth(60);
-    message.setVisibleLines(10);
-    message.setText(defaultMessage);
-    DOM.setElementPropertyBoolean(message.getElement(), "spellcheck", true);
-    mwrap.add(message);
-
-    final FlowPanel buttonPanel = new FlowPanel();
-    panel.add(buttonPanel);
-    sendButton = new Button(buttonSend);
-    sendButton.addClickHandler(new ClickHandler() {
-      @Override
-      public void onClick(final ClickEvent event) {
-        sendButton.setEnabled(false);
-        cancelButton.setEnabled(false);
-        onSend();
-      }
-    });
-    buttonPanel.add(sendButton);
-
-    cancelButton = new Button(buttonCancel);
-    DOM.setStyleAttribute(cancelButton.getElement(), "marginLeft", "300px");
-    cancelButton.addClickHandler(new ClickHandler() {
-      @Override
-      public void onClick(final ClickEvent event) {
-        buttonClicked = true;
-        if (callback != null) {
-          callback.onFailure(null);
-        }
-        hide();
-      }
-    });
-    buttonPanel.add(cancelButton);
-
-    addCloseHandler(this);
-  }
-
-  @Override
-  public void center() {
-    super.center();
-    GlobalKey.dialog(this);
-    message.setFocus(true);
-  }
-
-  @Override
-  public void onClose(CloseEvent<PopupPanel> event) {
-    if (!buttonClicked) {
-      // the dialog was closed without one of the buttons being pressed
-      // e.g. the user pressed ESC to close the dialog
-      if (callback != null) {
-        callback.onFailure(null);
-      }
-    }
-  }
-
-  public abstract void onSend();
-
-  public PatchSet.Id getPatchSetId() {
-    return psid;
-  }
-
-  public String getMessageText() {
-    return message.getText().trim();
-  }
-
-  public GerritCallback<ChangeDetail> createCallback() {
-    return new GerritCallback<ChangeDetail>(){
-      @Override
-      public void onSuccess(ChangeDetail result) {
-        buttonClicked = true;
-        if (callback != null) {
-          callback.onSuccess(result);
-        }
-        hide();
-      }
-
-      @Override
-      public void onFailure(Throwable caught) {
-        sendButton.setEnabled(true);
-        cancelButton.setEnabled(true);
-        super.onFailure(caught);
-      }
-    };
-  }
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandLink.java
index 53771a97..c095d4d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandLink.java
@@ -15,14 +15,14 @@
 package com.google.gerrit.client.changes;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.Accessibility;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 abstract class DownloadCommandLink extends Anchor implements ClickHandler {
   final AccountGeneralPreferences.DownloadCommand cmdType;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandPanel.java
index 0affcfb..1516da1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadCommandPanel.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.client.changes;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadCommand;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
 import com.google.gwt.user.client.ui.Accessibility;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Widget;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlLink.java
index 6e72e20..2afafaa 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlLink.java
@@ -15,14 +15,14 @@
 package com.google.gerrit.client.changes;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.Accessibility;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 class DownloadUrlLink extends Anchor implements ClickHandler {
   final AccountGeneralPreferences.DownloadScheme urlType;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlPanel.java
index f4260e2..b3c9ebc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/DownloadUrlPanel.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.client.changes;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.user.client.ui.Accessibility;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Widget;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java
index 533999d..3a1ccde 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/IncludedInTable.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.common.data.IncludedInDetail;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.event.logical.shared.OpenEvent;
 import com.google.gwt.event.logical.shared.OpenHandler;
 import com.google.gwt.user.client.ui.Composite;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
index 6ca102f..72300b2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PagedSingleListScreen.java
@@ -21,10 +21,10 @@
 import com.google.gerrit.client.ui.Screen;
 import com.google.gerrit.common.data.ChangeInfo;
 import com.google.gerrit.common.data.SingleListChangeInfo;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index d3c3f76..81b4f14 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -17,57 +17,59 @@
 import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.FormatUtil;
 import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.GitwebLink;
 import com.google.gerrit.client.patches.PatchUtil;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.AccountDashboardLink;
+import com.google.gerrit.client.ui.CommentedActionDialog;
 import com.google.gerrit.client.ui.ComplexDisclosurePanel;
 import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ChangeDetail;
-import com.google.gerrit.common.data.GitwebLink;
 import com.google.gerrit.common.data.PatchSetDetail;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadCommand;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadScheme;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.UserIdentity;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.logical.shared.OpenEvent;
 import com.google.gwt.event.logical.shared.OpenHandler;
 import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.FocusWidget;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwtexpui.clippy.client.CopyableLabel;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements OpenHandler<DisclosurePanel> {
+class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel
+    implements OpenHandler<DisclosurePanel> {
   private static final int R_AUTHOR = 0;
   private static final int R_COMMITTER = 1;
   private static final int R_PARENTS = 2;
   private static final int R_DOWNLOAD = 3;
   private static final int R_CNT = 4;
 
-  private final ChangeScreen changeScreen;
+  private final ChangeDetailCache detailCache;
   private final ChangeDetail changeDetail;
   private final PatchSet patchSet;
   private final FlowPanel body;
@@ -83,38 +85,22 @@
    * Creates a closed complex disclosure panel for a patch set.
    * The patch set details are loaded when the complex disclosure panel is opened.
    */
-  PatchSetComplexDisclosurePanel(final ChangeScreen parent, final ChangeDetail detail,
-      final PatchSet ps) {
-    this(parent, detail, ps, false);
-    addOpenHandler(this);
-  }
-
-  /**
-   * Creates an open complex disclosure panel for a patch set.
-   */
-  PatchSetComplexDisclosurePanel(final ChangeScreen parent, final ChangeDetail detail,
-      final PatchSetDetail psd) {
-    this(parent, detail, psd.getPatchSet(), true);
-    ensureLoaded(psd);
-  }
-
-  private PatchSetComplexDisclosurePanel(final ChangeScreen parent, final ChangeDetail detail,
-      final PatchSet ps, boolean isOpen) {
+  public PatchSetComplexDisclosurePanel(final PatchSet ps, boolean isOpen) {
     super(Util.M.patchSetHeader(ps.getPatchSetId()), isOpen);
-    changeScreen = parent;
-    changeDetail = detail;
+    detailCache = ChangeCache.get(ps.getId().getParentKey()).getChangeDetailCache();
+    changeDetail = detailCache.get();
     patchSet = ps;
+
     body = new FlowPanel();
     setContent(body);
 
-    final GitwebLink gw = Gerrit.getConfig().getGitwebLink();
-
+    final GitwebLink gw = Gerrit.getGitwebLink();
     final InlineLabel revtxt = new InlineLabel(ps.getRevision().get() + " ");
     revtxt.addStyleName(Gerrit.RESOURCES.css().patchSetRevision());
     getHeader().add(revtxt);
     if (gw != null) {
       final Anchor revlink =
-          new Anchor(gw.getLinkName(), false, gw.toRevision(detail.getChange()
+          new Anchor(gw.getLinkName(), false, gw.toRevision(changeDetail.getChange()
               .getProject(), ps));
       revlink.addStyleName(Gerrit.RESOURCES.css().patchSetLink());
       getHeader().add(revlink);
@@ -125,6 +111,12 @@
       draftLabel.addStyleName(Gerrit.RESOURCES.css().patchSetRevision());
       getHeader().add(draftLabel);
     }
+
+    if (isOpen) {
+      ensureLoaded(changeDetail.getCurrentPatchSetDetail());
+    } else {
+      addOpenHandler(this);
+    }
   }
 
   public void setDiffBaseId(PatchSet.Id diffBaseId) {
@@ -165,8 +157,7 @@
     if (!patchSet.getId().equals(diffBaseId)) {
       patchTable = new PatchTable();
       patchTable.setSavePointerId("PatchTable " + patchSet.getId());
-      patchTable.setPatchSetIdToCompareWith(diffBaseId);
-      patchTable.display(detail);
+      patchTable.display(diffBaseId, detail);
 
       actionsPanel = new FlowPanel();
       actionsPanel.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
@@ -468,15 +459,22 @@
         @Override
         public void onClick(final ClickEvent event) {
           b.setEnabled(false);
-          new CommentedChangeActionDialog(patchSet.getId(), createCommentedCallback(b, true),
-              Util.C.revertChangeTitle(), Util.C.headingRevertMessage(),
-              Util.C.buttonRevertChangeSend(), Util.C.buttonRevertChangeCancel(),
-              Gerrit.RESOURCES.css().revertChangeDialog(), Gerrit.RESOURCES.css().revertMessage(),
-              Util.M.revertChangeDefaultMessage(detail.getInfo().getSubject(), detail.getPatchSet().getRevision().get())) {
-                public void onSend() {
-                  Util.MANAGE_SVC.revertChange(getPatchSetId() , getMessageText(), createCallback());
-                }
-              }.center();
+          new ActionDialog(b, true, Util.C.revertChangeTitle(),
+              Util.C.headingRevertMessage()) {
+            {
+              sendButton.setText(Util.C.buttonRevertChangeSend());
+              message.setText(Util.M.revertChangeDefaultMessage(
+                  detail.getInfo().getSubject(),
+                  detail.getPatchSet().getRevision().get())
+              );
+            }
+
+            @Override
+            public void onSend() {
+              Util.MANAGE_SVC.revertChange(patchSet.getId(), getMessageText(),
+                 createCallback());
+            }
+          }.center();
         }
       });
       actionsPanel.add(b);
@@ -488,14 +486,18 @@
         @Override
         public void onClick(final ClickEvent event) {
           b.setEnabled(false);
-          new CommentedChangeActionDialog(patchSet.getId(), createCommentedCallback(b, false),
-              Util.C.abandonChangeTitle(), Util.C.headingAbandonMessage(),
-              Util.C.buttonAbandonChangeSend(), Util.C.buttonAbandonChangeCancel(),
-              Gerrit.RESOURCES.css().abandonChangeDialog(), Gerrit.RESOURCES.css().abandonMessage()) {
-                public void onSend() {
-                  Util.MANAGE_SVC.abandonChange(getPatchSetId() , getMessageText(), createCallback());
-                }
-              }.center();
+          new ActionDialog(b, false, Util.C.abandonChangeTitle(),
+              Util.C.headingAbandonMessage()) {
+            {
+              sendButton.setText(Util.C.buttonAbandonChangeSend());
+            }
+
+            @Override
+            public void onSend() {
+              Util.MANAGE_SVC.abandonChange(patchSet.getId(), getMessageText(),
+                  createCallback());
+            }
+          }.center();
         }
       });
       actionsPanel.add(b);
@@ -531,14 +533,31 @@
         @Override
         public void onClick(final ClickEvent event) {
           b.setEnabled(false);
-          new CommentedChangeActionDialog(patchSet.getId(), createCommentedCallback(b, false),
-              Util.C.restoreChangeTitle(), Util.C.headingRestoreMessage(),
-              Util.C.buttonRestoreChangeSend(), Util.C.buttonRestoreChangeCancel(),
-              Gerrit.RESOURCES.css().abandonChangeDialog(), Gerrit.RESOURCES.css().abandonMessage()) {
-                public void onSend() {
-                  Util.MANAGE_SVC.restoreChange(getPatchSetId(), getMessageText(), createCallback());
-                }
-              }.center();
+          new ActionDialog(b, false, Util.C.restoreChangeTitle(),
+              Util.C.headingRestoreMessage()) {
+            {
+              sendButton.setText(Util.C.buttonRestoreChangeSend());
+            }
+
+            @Override
+            public void onSend() {
+              Util.MANAGE_SVC.restoreChange(patchSet.getId(), getMessageText(),
+                  createCallback());
+            }
+          }.center();
+        }
+      });
+      actionsPanel.add(b);
+    }
+
+    if (changeDetail.canRebase()) {
+      final Button b = new Button(Util.C.buttonRebaseChange());
+      b.addClickHandler(new ClickHandler() {
+        @Override
+        public void onClick(final ClickEvent event) {
+          b.setEnabled(false);
+          Util.MANAGE_SVC.rebaseChange(patchSet.getId(),
+              new ChangeDetailCache.GerritWidgetCallback(b));
         }
       });
       actionsPanel.add(b);
@@ -548,12 +567,10 @@
   private void populateDiffAllActions(final PatchSetDetail detail) {
     final Button diffAllSideBySide = new Button(Util.C.buttonDiffAllSideBySide());
     diffAllSideBySide.addClickHandler(new ClickHandler() {
-
       @Override
       public void onClick(ClickEvent event) {
         for (Patch p : detail.getPatches()) {
-          Window.open(Window.Location.getPath() + "#"
-              + Dispatcher.toPatchSideBySide(p.getKey()), "_blank", null);
+          openWindow(Dispatcher.toPatchSideBySide(diffBaseId, p.getKey()));
         }
       }
     });
@@ -561,18 +578,21 @@
 
     final Button diffAllUnified = new Button(Util.C.buttonDiffAllUnified());
     diffAllUnified.addClickHandler(new ClickHandler() {
-
       @Override
       public void onClick(ClickEvent event) {
         for (Patch p : detail.getPatches()) {
-          Window.open(Window.Location.getPath() + "#"
-              + Dispatcher.toPatchUnified(p.getKey()), "_blank", null);
+          openWindow(Dispatcher.toPatchUnified(diffBaseId, p.getKey()));
         }
       }
     });
     actionsPanel.add(diffAllUnified);
   }
 
+  private void openWindow(String token) {
+    String url = Window.Location.getPath() + "#" + token;
+    Window.open(url, "_blank", null);
+  }
+
   private void populateReviewAction() {
     final Button b = new Button(Util.C.buttonReview());
     b.addClickHandler(new ClickHandler() {
@@ -593,7 +613,7 @@
         Util.MANAGE_SVC.publish(patchSet.getId(),
             new GerritCallback<ChangeDetail>() {
               public void onSuccess(ChangeDetail result) {
-                changeScreen.update(result);
+                detailCache.set(result);
               }
 
               @Override
@@ -617,7 +637,7 @@
             new GerritCallback<ChangeDetail>() {
               public void onSuccess(final ChangeDetail result) {
                 if (result != null) {
-                  changeScreen.update(result);
+                  detailCache.set(result);
                 } else {
                   Gerrit.display(PageLinks.MINE);
                 }
@@ -646,18 +666,15 @@
         new GerritCallback<PatchSetDetail>() {
           @Override
           public void onSuccess(PatchSetDetail result) {
-
             if (patchSet.getId().equals(diffBaseId)) {
               patchTable.setVisible(false);
               actionsPanel.setVisible(false);
             } else {
-
               if (patchTable != null) {
                 patchTable.removeFromParent();
               }
               patchTable = new PatchTable();
-              patchTable.setPatchSetIdToCompareWith(diffBaseId);
-              patchTable.display(result);
+              patchTable.display(diffBaseId, result);
               body.add(patchTable);
 
               for (ClickHandler clickHandler : registeredClickHandler) {
@@ -713,7 +730,7 @@
         new SubmitFailureDialog(result, msg).center();
       }
     }
-    changeScreen.update(result);
+    detailCache.set(result);
   }
 
   public PatchSet getPatchSet() {
@@ -739,19 +756,24 @@
     }
   }
 
-  private AsyncCallback<ChangeDetail> createCommentedCallback(final Button b, final boolean redirect) {
-    return new AsyncCallback<ChangeDetail>() {
-      public void onSuccess(ChangeDetail result) {
-        if (redirect) {
-          Gerrit.display(PageLinks.toChange(result.getChange().getId()));
-        } else {
-          changeScreen.update(result);
-        }
-      }
+  private abstract class ActionDialog extends CommentedActionDialog<ChangeDetail> {
+    public ActionDialog(final FocusWidget enableOnFailure, final boolean redirect,
+        String dialogTitle, String dialogHeading) {
+      super(dialogTitle, dialogHeading, new ChangeDetailCache.IgnoreErrorCallback() {
+          @Override
+          public void onSuccess(ChangeDetail result) {
+            if (redirect) {
+              Gerrit.display(PageLinks.toChange(result.getChange().getId()));
+            } else {
+              super.onSuccess(result);
+            }
+          }
 
-      public void onFailure(Throwable caught) {
-        b.setEnabled(true);
-      }
-    };
+          @Override
+          public void onFailure(Throwable caught) {
+            enableOnFailure.setEnabled(true);
+          }
+        });
+    }
   }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
index e854cab..7e659a1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
@@ -17,8 +17,8 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ChangeDetail;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -43,11 +43,9 @@
  * that keyboard navigation to each changed file in all patch sets is possible.
  */
 public class PatchSetsBlock extends Composite {
-
   private final Map<PatchSet.Id, PatchSetComplexDisclosurePanel> patchSetPanels =
       new HashMap<PatchSet.Id, PatchSetComplexDisclosurePanel>();
 
-  private final ChangeScreen parent;
   private final FlowPanel body;
   private HandlerRegistration regNavigation;
 
@@ -65,8 +63,7 @@
   /** Patch sets on this change, in order. */
   private List<PatchSet> patchSets;
 
-  PatchSetsBlock(final ChangeScreen parent) {
-    this.parent = parent;
+  PatchSetsBlock() {
     body = new FlowPanel();
     initWidget(body);
   }
@@ -79,12 +76,6 @@
     currentPatchSetId = currps.getId();
     patchSets = detail.getPatchSets();
 
-    final List<PatchSet.Id> changePatchSets = new ArrayList<PatchSet.Id>();
-
-    for (final PatchSet ps : patchSets) {
-      changePatchSets.add(ps.getId());
-    }
-
     if (Gerrit.isSignedIn()) {
       final AccountGeneralPreferences p =
           Gerrit.getUserAccount().getGeneralPreferences();
@@ -96,19 +87,13 @@
     patchSetPanelsList = new ArrayList<PatchSetComplexDisclosurePanel>();
 
     for (final PatchSet ps : patchSets) {
-      final PatchSetComplexDisclosurePanel p;
-      if (ps == currps) {
-        p = new PatchSetComplexDisclosurePanel(parent, detail, detail
-            .getCurrentPatchSetDetail());
-        if (diffBaseId != null) {
-          p.setDiffBaseId(diffBaseId);
+      final PatchSetComplexDisclosurePanel p =
+          new PatchSetComplexDisclosurePanel(ps, ps == currps);
+      if (diffBaseId != null) {
+        p.setDiffBaseId(diffBaseId);
+        if (ps == currps) {
           p.refresh();
         }
-      } else {
-        p = new PatchSetComplexDisclosurePanel(parent, detail, ps);
-        if (diffBaseId != null) {
-          p.setDiffBaseId(diffBaseId);
-        }
       }
       add(p);
       patchSetPanelsList.add(p);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
index a028619..7177525 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
@@ -21,11 +21,11 @@
 import com.google.gerrit.client.ui.NavigationTable;
 import com.google.gerrit.client.ui.PatchLink;
 import com.google.gerrit.common.data.PatchSetDetail;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Patch.ChangeType;
-import com.google.gerrit.reviewdb.Patch.Key;
-import com.google.gerrit.reviewdb.Patch.PatchType;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
+import com.google.gerrit.reviewdb.client.Patch.Key;
+import com.google.gerrit.reviewdb.client.Patch.PatchType;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.RepeatingCommand;
@@ -55,6 +55,7 @@
   private Command onLoadCommand;
   private MyTable myTable;
   private String savePointerId;
+  private PatchSet.Id base;
   private List<Patch> patchList;
   private ListenableAccountDiffPreference listenablePrefs;
 
@@ -62,8 +63,6 @@
   private boolean active;
   private boolean registerKeys;
 
-  private PatchSet.Id patchSetIdToCompareWith;
-
   public PatchTable(ListenableAccountDiffPreference prefs) {
     listenablePrefs = prefs;
     myBody = new FlowPanel();
@@ -83,12 +82,13 @@
     return -1;
   }
 
-  public void display(PatchSetDetail detail) {
+  public void display(PatchSet.Id base, PatchSetDetail detail) {
+    this.base = base;
     this.detail = detail;
     this.patchList = detail.getPatches();
     myTable = null;
 
-    final DisplayCommand cmd = new DisplayCommand(patchList, patchSetIdToCompareWith);
+    final DisplayCommand cmd = new DisplayCommand(patchList, base);
     if (cmd.execute()) {
       cmd.initMeter();
       Scheduler.get().scheduleIncremental(cmd);
@@ -223,9 +223,9 @@
     PatchLink link;
     if (patchType == PatchScreen.Type.SIDE_BY_SIDE
         && patch.getPatchType() == Patch.PatchType.UNIFIED) {
-      link = new PatchLink.SideBySide("", thisKey, index, detail, this);
+      link = new PatchLink.SideBySide("", base, thisKey, index, detail, this);
     } else {
-      link = new PatchLink.Unified("", thisKey, index, detail, this);
+      link = new PatchLink.Unified("", base, thisKey, index, detail, this);
     }
     SafeHtmlBuilder text = new SafeHtmlBuilder();
     text.append(before);
@@ -275,14 +275,6 @@
     listenablePrefs = prefs;
   }
 
-  public PatchSet.Id getPatchSetIdToCompareWith() {
-    return patchSetIdToCompareWith;
-  }
-
-  public void setPatchSetIdToCompareWith(final PatchSet.Id psId) {
-    patchSetIdToCompareWith = psId;
-  }
-
   private class MyTable extends NavigationTable<Patch> {
     private static final int C_PATH = 2;
     private static final int C_DRAFT = 3;
@@ -381,13 +373,11 @@
 
       Widget nameCol;
       if (patch.getPatchType() == Patch.PatchType.UNIFIED) {
-        nameCol =
-            new PatchLink.SideBySide(getDisplayFileName(patch), patch.getKey(),
-                row - 1, detail, PatchTable.this);
+        nameCol = new PatchLink.SideBySide(getDisplayFileName(patch), base,
+            patch.getKey(), row - 1, detail, PatchTable.this);
       } else {
-        nameCol =
-            new PatchLink.Unified(getDisplayFileName(patch), patch.getKey(),
-                row - 1, detail, PatchTable.this);
+        nameCol = new PatchLink.Unified(getDisplayFileName(patch), base,
+            patch.getKey(), row - 1, detail, PatchTable.this);
       }
       if (patch.getSourceFileName() != null) {
         final String text;
@@ -409,16 +399,15 @@
 
       int C_UNIFIED = C_SIDEBYSIDE + 1;
       if (patch.getPatchType() == Patch.PatchType.UNIFIED) {
-        table.setWidget(row, C_SIDEBYSIDE, new PatchLink.SideBySide(Util.C
-            .patchTableDiffSideBySide(), patch.getKey(), row - 1, detail,
-            PatchTable.this));
-
+        table.setWidget(row, C_SIDEBYSIDE, new PatchLink.SideBySide(
+            Util.C.patchTableDiffSideBySide(), base, patch.getKey(), row - 1,
+            detail, PatchTable.this));
       } else if (patch.getPatchType() == Patch.PatchType.BINARY) {
         C_UNIFIED = C_SIDEBYSIDE + 2;
       }
-      table.setWidget(row, C_UNIFIED, new PatchLink.Unified(Util.C
-          .patchTableDiffUnified(), patch.getKey(), row - 1, detail,
-          PatchTable.this));
+      table.setWidget(row, C_UNIFIED, new PatchLink.Unified(
+          Util.C.patchTableDiffUnified(), base, patch.getKey(), row - 1,
+          detail, PatchTable.this));
     }
 
     void appendHeader(final SafeHtmlBuilder m) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
index 03ddfd0..0c08491 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
@@ -29,25 +29,25 @@
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.PatchSetPublishDetail;
 import com.google.gerrit.common.data.PermissionRange;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.FormPanel;
+import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.VerticalPanel;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -297,8 +297,8 @@
           draftsPanel.add(panel);
           // Parent table can be null here since we are not showing any
           // next/previous links
-          panel.add(new PatchLink.SideBySide(PatchTable
-              .getDisplayFileName(patchKey), patchKey, 0, null, null));
+          panel.add(new PatchLink.SideBySide(
+              PatchTable.getDisplayFileName(patchKey), null, patchKey, 0, null, null));
           priorFile = fn;
         }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java
index 5540a6d..cf9c526 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java
@@ -19,8 +19,8 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ChangeInfo;
 import com.google.gerrit.common.data.SingleListChangeInfo;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwtorm.client.KeyUtil;
 
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarCache.java
new file mode 100644
index 0000000..d7624a6
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/StarCache.java
@@ -0,0 +1,139 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.changes;
+
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.rpc.GerritCallback;
+import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
+import com.google.gerrit.common.data.ChangeDetail;
+import com.google.gerrit.common.data.ChangeInfo;
+import com.google.gerrit.common.data.ToggleStarRequest;
+import com.google.gerrit.reviewdb.client.Change;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwtjsonrpc.common.VoidResult;
+
+public class StarCache implements HasValueChangeHandlers<Boolean> {
+  public class KeyCommand extends NeedsSignInKeyCommand {
+    public KeyCommand(int mask, char key, String help) {
+      super(mask, key, help);
+    }
+
+    @Override
+    public void onKeyPress(final KeyPressEvent event) {
+      StarCache.this.toggleStar();
+    }
+  }
+
+  ChangeCache cache;
+
+  private HandlerManager manager = new HandlerManager(this);
+
+  public StarCache(final Change.Id chg) {
+    cache = ChangeCache.get(chg);
+  }
+
+  public boolean get() {
+    ChangeDetail detail = cache.getChangeDetailCache().get();
+    if (detail != null) {
+      return detail.isStarred();
+    }
+    ChangeInfo info = cache.getChangeInfoCache().get();
+    if (info != null) {
+      return info.isStarred();
+    }
+    return false;
+  }
+
+  public void set(final boolean s) {
+    if (Gerrit.isSignedIn() && s != get()) {
+      final ToggleStarRequest req = new ToggleStarRequest();
+      req.toggle(cache.getChangeId(), s);
+
+      Util.LIST_SVC.toggleStars(req, new GerritCallback<VoidResult>() {
+        public void onSuccess(final VoidResult result) {
+          setStarred(s);
+          fireEvent(new ValueChangeEvent<Boolean>(s){});
+        }
+      });
+    }
+  }
+
+  private void setStarred(final boolean s) {
+    ChangeDetail detail = cache.getChangeDetailCache().get();
+    if (detail != null) {
+      detail.setStarred(s);
+    }
+    ChangeInfo info = cache.getChangeInfoCache().get();
+    if (info != null) {
+      info.setStarred(s);
+    }
+  }
+
+  public void toggleStar() {
+    set(!get());
+  }
+
+  @SuppressWarnings("unchecked")
+  public Image createStar() {
+    final Image star = new Image(getResource());
+    star.setVisible(Gerrit.isSignedIn());
+
+    star.addClickHandler(new ClickHandler() {
+      @Override
+      public void onClick(final ClickEvent event) {
+        StarCache.this.toggleStar();
+      }
+    });
+
+    @SuppressWarnings("rawtypes")
+    ValueChangeHandler starUpdater = new ValueChangeHandler() {
+        @Override
+        public void onValueChange(ValueChangeEvent event) {
+          star.setResource(StarCache.this.getResource());
+        }
+      };
+
+    cache.getChangeDetailCache().addValueChangeHandler(starUpdater);
+    cache.getChangeInfoCache().addValueChangeHandler(starUpdater);
+
+    this.addValueChangeHandler(starUpdater);
+
+    return star;
+  }
+
+  private ImageResource getResource() {
+    return get() ? Gerrit.RESOURCES.starFilled() : Gerrit.RESOURCES.starOpen();
+  }
+
+  public void fireEvent(GwtEvent<?> event) {
+    manager.fireEvent(event);
+  }
+
+  public HandlerRegistration addValueChangeHandler(
+      ValueChangeHandler<Boolean> handler) {
+    return manager.addHandler(ValueChangeEvent.getType(), handler);
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitFailureDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitFailureDialog.java
index f9f6f99..bedfb74 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitFailureDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/SubmitFailureDialog.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.client.ErrorDialog;
 import com.google.gerrit.common.data.ChangeDetail;
-import com.google.gerrit.reviewdb.ChangeMessage;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
 class SubmitFailureDialog extends ErrorDialog {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
index 3fe63ed..e84cac8 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/Util.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.common.data.ChangeDetailService;
 import com.google.gerrit.common.data.ChangeListService;
 import com.google.gerrit.common.data.ChangeManageService;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.core.client.GWT;
 import com.google.gwtjsonrpc.client.JsonUtil;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 20837c4..1081e47 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -1209,7 +1209,6 @@
 
 
 /** PublishCommentsScreen **/
-
 .publishCommentsScreen .smallHeading {
   font-size: small;
   font-weight: bold;
@@ -1259,57 +1258,29 @@
 }
 
 
-/** AbandonChangeDialog **/
-
-.abandonChangeDialog .gwt-DisclosurePanel .header td {
+/** CommentedActionDialog **/
+.commentedActionDialog .gwt-DisclosurePanel .header td {
   font-weight: bold;
   white-space: nowrap;
 }
-
-.abandonChangeDialog .smallHeading {
+.commentedActionDialog .smallHeading {
   font-size: small;
   font-weight: bold;
   white-space: nowrap;
 }
-.abandonChangeDialog .abandonMessage {
+.commentedActionDialog .commentedActionMessage {
   margin-left: 10px;
   background: trimColor;
   padding: 5px 5px 5px 5px;
 }
-.abandonChangeDialog .abandonMessage textarea {
+.commentedActionDialog .commentedActionMessage textarea {
   font-size: small;
 }
-.abandonChangeDialog .gwt-Hyperlink {
+.commentedActionDialog .gwt-Hyperlink {
   white-space: nowrap;
   font-size: small;
 }
 
-/** RevertChangeDialog **/
-
-.revertChangeDialog .gwt-DisclosurePanel .header td {
-  font-weight: bold;
-  white-space: nowrap;
-}
-
-.revertChangeDialog .smallHeading {
-  font-size: small;
-  font-weight: bold;
-  white-space: nowrap;
-}
-.revertChangeDialog .revertMessage {
-  margin-left: 10px;
-  background: trimColor;
-  padding: 5px 5px 5px 5px;
-}
-.revertChangeDialog .revertMessage textarea {
-  font-size: small;
-}
-.revertChangeDialog .gwt-Hyperlink {
-  white-space: nowrap;
-  font-size: small;
-}
-
-
 /** PatchBrowserPopup **/
 .patchBrowserPopup {
   opacity: 0.90;
@@ -1339,10 +1310,6 @@
   margin-bottom: 2px;
 }
 .groupOptionsPanel {
-  margin-bottom: 3px;
-}
-.groupOptionsNotificationsDescriptionPanel {
-  margin-top: 5px;
   margin-bottom: 5px;
 }
 .groupOwnerPanel {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/AbstractPatchContentTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/AbstractPatchContentTable.java
index 396f1bf..8282caa 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/AbstractPatchContentTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/AbstractPatchContentTable.java
@@ -26,10 +26,14 @@
 import com.google.gerrit.common.data.AccountInfoCache;
 import com.google.gerrit.common.data.CommentDetail;
 import com.google.gerrit.common.data.PatchScript;
+import com.google.gerrit.prettify.client.ClientSideFormatter;
+import com.google.gerrit.prettify.common.PrettyFormatter;
 import com.google.gerrit.prettify.common.SparseFileContent;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.prettify.common.SparseHtmlFile;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.BlurEvent;
 import com.google.gwt.event.dom.client.BlurHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -45,9 +49,9 @@
 import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.UIObject;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
@@ -171,6 +175,36 @@
     render(s);
   }
 
+  protected SparseHtmlFile getSparseHtmlFileA(PatchScript s) {
+    AccountDiffPreference dp = new AccountDiffPreference(s.getDiffPrefs());
+    dp.setShowWhitespaceErrors(false);
+
+    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
+    f.setDiffPrefs(dp);
+    f.setFileName(s.getA().getPath());
+    f.setEditFilter(PrettyFormatter.A);
+    f.setEditList(s.getEdits());
+    f.format(s.getA());
+    return f;
+  }
+
+  protected SparseHtmlFile getSparseHtmlFileB(PatchScript s) {
+    AccountDiffPreference dp = new AccountDiffPreference(s.getDiffPrefs());
+
+    PrettyFormatter f = ClientSideFormatter.FACTORY.get();
+    f.setDiffPrefs(dp);
+    f.setFileName(s.getB().getPath());
+    f.setEditFilter(PrettyFormatter.B);
+    f.setEditList(s.getEdits());
+
+    if (dp.isSyntaxHighlighting() && s.getA().isWholeFile() && !s.getB().isWholeFile()) {
+      f.format(s.getB().apply(s.getA(), s.getEdits()));
+    } else {
+      f.format(s.getB());
+    }
+    return f;
+  }
+
   protected abstract void render(PatchScript script);
 
   protected abstract void onInsertComment(PatchLine pl);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
index 5df1e14..b0d825b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.CommentPanel;
-import com.google.gerrit.reviewdb.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.DoubleClickEvent;
@@ -26,11 +26,11 @@
 import com.google.gwt.event.dom.client.KeyDownEvent;
 import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Widget;
 import com.google.gwtexpui.globalkey.client.NpTextArea;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.sql.Timestamp;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/HistoryTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/HistoryTable.java
index e35097e..cb54411 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/HistoryTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/HistoryTable.java
@@ -14,11 +14,12 @@
 
 package com.google.gerrit.client.patches;
 
+import com.google.gerrit.client.Dispatcher;
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.changes.Util;
 import com.google.gerrit.client.ui.FancyFlexTable;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
@@ -43,19 +44,28 @@
   }
 
   void onClick(final HistoryRadio b) {
+    PatchSet.Id sideA = screen.idSideA;
+    PatchSet.Id sideB = screen.idSideB;
     switch (b.file) {
       case 0:
-        screen.setSideA(b.patchSetId);
+        sideA = b.patchSetId;
         break;
       case 1:
-        screen.setSideB(b.patchSetId);
+        sideB = b.patchSetId;
         break;
       default:
         return;
     }
-
     enableAll(false);
-    screen.refresh(false);
+    Patch.Key k = new Patch.Key(sideB, screen.getPatchKey().get());
+    switch (screen.getPatchScreenType()) {
+      case SIDE_BY_SIDE:
+        Gerrit.display(Dispatcher.toPatchSideBySide(sideA, k));
+        break;
+      case UNIFIED:
+        Gerrit.display(Dispatcher.toPatchUnified(sideA, k));
+        break;
+    }
   }
 
   void enableAll(final boolean on) {
@@ -76,7 +86,11 @@
     table.setText(3, 0, Util.C.patchTableColumnComments());
     fmt.setStyleName(3, 0, Gerrit.RESOURCES.css().dataHeader());
 
-    table.setText(0, 1, PatchUtil.C.patchBase());
+    if (screen.getPatchSetDetail().getInfo().getParents().size() > 1) {
+      table.setText(0, 1, PatchUtil.C.patchBaseAutoMerge());
+    } else {
+      table.setText(0, 1, PatchUtil.C.patchBase());
+    }
     fmt.setStyleName(0, 1, Gerrit.RESOURCES.css().dataCell());
     fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topMostCell());
     fmt.setStyleName(1, 1, Gerrit.RESOURCES.css().dataCell());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
index 6d42cc9..9f36342 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java
@@ -19,12 +19,12 @@
 import com.google.gerrit.client.changes.Util;
 import com.google.gerrit.client.ui.ChangeLink;
 import com.google.gerrit.client.ui.InlineHyperlink;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchBrowserPopup.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchBrowserPopup.java
index e3fb1e9..9af1aa3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchBrowserPopup.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchBrowserPopup.java
@@ -17,15 +17,15 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.changes.PatchTable;
 import com.google.gerrit.client.changes.Util;
-import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.client.Patch;
 import com.google.gwt.event.logical.shared.ResizeEvent;
 import com.google.gwt.event.logical.shared.ResizeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
+import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.HidePopupPanelCommand;
 import com.google.gwtexpui.user.client.PluginSafeDialogBox;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
index 32f7096..fd34729 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
@@ -27,6 +27,7 @@
 
   String noDifference();
   String patchBase();
+  String patchBaseAutoMerge();
   String patchHeaderPatchSet();
   String patchHeaderOld();
   String patchHeaderNew();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
index f9f407e..6a1dbc1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
@@ -10,6 +10,7 @@
 
 noDifference = No Differences
 patchBase = Base
+patchBaseAutoMerge = Auto Merge
 patchHeaderPatchSet = Patch Set
 patchHeaderOld = Old Version
 patchHeaderNew = New Version
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index 1671d6e..ffc8960 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -29,23 +29,23 @@
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.prettify.client.ClientSideFormatter;
 import com.google.gerrit.prettify.common.PrettyFactory;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 public abstract class PatchScreen extends Screen implements
     CommentEditorContainer {
@@ -54,8 +54,8 @@
   public static class SideBySide extends PatchScreen {
     public SideBySide(final Patch.Key id, final int patchIndex,
         final PatchSetDetail patchSetDetail, final PatchTable patchTable,
-        final TopView topView) {
-      super(id, patchIndex, patchSetDetail, patchTable, topView);
+        final TopView topView, final PatchSet.Id baseId) {
+       super(id, patchIndex, patchSetDetail, patchTable, topView, baseId);
     }
 
     @Override
@@ -72,8 +72,8 @@
   public static class Unified extends PatchScreen {
     public Unified(final Patch.Key id, final int patchIndex,
         final PatchSetDetail patchSetDetail, final PatchTable patchTable,
-        final TopView topView) {
-      super(id, patchIndex, patchSetDetail, patchTable, topView);
+        final TopView topView, final PatchSet.Id baseId) {
+      super(id, patchIndex, patchSetDetail, patchTable, topView, baseId);
     }
 
     @Override
@@ -87,10 +87,6 @@
     }
   }
 
-  // Which patch set id's are being diff'ed
-  private static PatchSet.Id diffSideA = null;
-  private static PatchSet.Id diffSideB = null;
-
   /**
    * What should be displayed in the top of the screen
    */
@@ -137,20 +133,14 @@
 
   protected PatchScreen(final Patch.Key id, final int patchIndex,
       final PatchSetDetail detail, final PatchTable patchTable,
-      final TopView top) {
+      final TopView top, final PatchSet.Id baseId) {
     patchKey = id;
     patchSetDetail = detail;
     fileList = patchTable;
     topView = top;
 
-    if (patchTable != null) {
-      diffSideA = patchTable.getPatchSetIdToCompareWith();
-    } else {
-      diffSideA = null;
-    }
-
-    idSideA = diffSideA; // null here means we're diff'ing from the Base
-    idSideB = diffSideB != null ? diffSideB : id.getParentKey();
+    idSideA = baseId; // null here means we're diff'ing from the Base
+    idSideB = id.getParentKey();
     this.patchIndex = patchIndex;
 
     reviewed = new CheckBox(Util.C.reviewed());
@@ -189,6 +179,13 @@
   }
 
   private void update(AccountDiffPreference dp) {
+    // Did the user just turn on auto-review?
+    if (!reviewed.getValue() && prefs.getOld().isManualReview()
+        && !dp.isManualReview()) {
+      reviewed.setValue(true);
+      setReviewedByCurrentUser(true);
+    }
+
     if (lastScript != null && canReuse(dp, lastScript)) {
       lastScript.setDiffPrefs(dp);
       RpcStatus.INSTANCE.onRpcStart(null);
@@ -308,7 +305,7 @@
               patchSetDetail = result;
               if (fileList == null) {
                 fileList = new PatchTable(prefs);
-                fileList.display(result);
+                fileList.display(idSideA, result);
                 patchIndex = fileList.indexOf(patchKey);
               }
               refresh(true);
@@ -343,6 +340,10 @@
 
   public abstract PatchScreen.Type getPatchScreenType();
 
+  public PatchSet.Id getSideA() {
+    return idSideA;
+  }
+
   public Patch.Key getPatchKey() {
     return patchKey;
   }
@@ -431,7 +432,7 @@
       contentTable = new UnifiedDiffTable();
       contentTable.fileList = fileList;
       contentPanel.add(contentTable);
-      setToken(Dispatcher.toPatchUnified(patchKey));
+      setToken(Dispatcher.toPatchUnified(idSideA, patchKey));
     }
 
     if (hasDifferences) {
@@ -450,10 +451,20 @@
       bottomNav.display(patchIndex, getPatchScreenType(), fileList);
     }
 
-    // Mark this file reviewed as soon we display the diff screen
-    if (Gerrit.isSignedIn() && isFirst) {
-      reviewed.setValue(true);
-      setReviewedByCurrentUser(true /* reviewed */);
+    if (Gerrit.isSignedIn()) {
+      boolean isReviewed = false;
+      if (isFirst && !prefs.get().isManualReview()) {
+        isReviewed = true;
+        setReviewedByCurrentUser(isReviewed);
+      } else {
+        for (Patch p : patchSetDetail.getPatches()) {
+          if (p.getKey().equals(patchKey)) {
+            isReviewed = p.isReviewedByCurrentUser();
+            break;
+          }
+        }
+      }
+      reviewed.setValue(isReviewed);
     }
 
     intralineFailure = isFirst && script.hasIntralineFailure();
@@ -477,19 +488,6 @@
     contentTable.setRegisterKeys(isCurrentView() && showPatch);
   }
 
-  public void setSideA(PatchSet.Id patchSetId) {
-    idSideA = patchSetId;
-    diffSideA = patchSetId;
-    if (fileList != null) {
-      fileList.setPatchSetIdToCompareWith(patchSetId);
-    }
-  }
-
-  public void setSideB(PatchSet.Id patchSetId) {
-    idSideB = patchSetId;
-    diffSideB = patchSetId;
-  }
-
   public void setTopView(TopView tv) {
     topView = tv;
     topPanel.clear();
@@ -519,7 +517,7 @@
         Util.DETAIL_SVC.patchSetDetail(psid,
             new GerritCallback<PatchSetDetail>() {
               public void onSuccess(final PatchSetDetail result) {
-                fileList.display(result);
+                fileList.display(idSideA, result);
               }
             });
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
index df0fff5..871eb2b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
@@ -20,8 +20,8 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
 import com.google.gerrit.client.ui.NpIntTextBox;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.KeyCodes;
@@ -41,7 +41,7 @@
 import com.google.gwt.user.client.ui.HasWidgets;
 import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 public class PatchScriptSettingsPanel extends Composite implements
     HasValueChangeHandlers<AccountDiffPreference> {
@@ -79,6 +79,9 @@
   CheckBox showTabs;
 
   @UiField
+  CheckBox manualReview;
+
+  @UiField
   CheckBox skipDeleted;
 
   @UiField
@@ -212,6 +215,7 @@
     skipUncommented.setValue(dp.isSkipUncommented());
     expandAllComments.setValue(dp.isExpandAllComments());
     retainHeader.setValue(dp.isRetainHeader());
+    manualReview.setValue(dp.isManualReview());
   }
 
   @UiHandler("update")
@@ -243,6 +247,7 @@
     dp.setSkipUncommented(skipUncommented.getValue());
     dp.setExpandAllComments(expandAllComments.getValue());
     dp.setRetainHeader(retainHeader.getValue());
+    dp.setManualReview(manualReview.getValue());
 
     listenablePrefs.set(dp);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.ui.xml
index e819ffa..2c7afff 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.ui.xml
@@ -147,20 +147,29 @@
       </g:CheckBox>
     </td>
 
+    <td valign='bottom' rowspan='2'>
+      <g:CheckBox
+          ui:field='manualReview'
+          text='Manual Review'
+          tabIndex='13'>
+        <ui:attribute name='text'/>
+      </g:CheckBox>
+    </td>
+
     <td rowspan='2'>
       <br/>
       <g:Button
           ui:field='update'
           text='Update'
           styleName='{style.updateButton}'
-          tabIndex='13'>
+          tabIndex='14'>
         <ui:attribute name='text'/>
       </g:Button>
       <g:Button
           ui:field='save'
           text='Save'
           styleName='{style.updateButton}'
-          tabIndex='14'>
+          tabIndex='15'>
         <ui:attribute name='text'/>
       </g:Button>
     </td>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
index 853cedc..6379e23 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/SideBySideTable.java
@@ -25,9 +25,9 @@
 import com.google.gerrit.common.data.PatchScript.FileMode;
 import com.google.gerrit.prettify.common.EditList;
 import com.google.gerrit.prettify.common.SparseHtmlFile;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.Patch.ChangeType;
-import com.google.gerrit.reviewdb.PatchLineComment;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
@@ -89,8 +89,8 @@
 
   @Override
   protected void render(final PatchScript script) {
-    a = script.getSparseHtmlFileA();
-    b = script.getSparseHtmlFileB();
+    a = getSparseHtmlFileA(script);
+    b = getSparseHtmlFileB(script);
     final ArrayList<Object> lines = new ArrayList<Object>();
     final SafeHtmlBuilder nc = new SafeHtmlBuilder();
     final boolean intraline =
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UnifiedDiffTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UnifiedDiffTable.java
index ef6a181..f0f619e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UnifiedDiffTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UnifiedDiffTable.java
@@ -23,10 +23,10 @@
 import com.google.gerrit.common.data.PatchScript;
 import com.google.gerrit.common.data.PatchScript.DisplayMethod;
 import com.google.gerrit.prettify.common.EditList;
-import com.google.gerrit.prettify.common.SparseHtmlFile;
 import com.google.gerrit.prettify.common.EditList.Hunk;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
+import com.google.gerrit.prettify.common.SparseHtmlFile;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
@@ -95,8 +95,8 @@
 
   @Override
   protected void render(final PatchScript script) {
-    final SparseHtmlFile a = script.getSparseHtmlFileA();
-    final SparseHtmlFile b = script.getSparseHtmlFileB();
+    final SparseHtmlFile a = getSparseHtmlFileA(script);
+    final SparseHtmlFile b = getSparseHtmlFileB(script);
     final SafeHtmlBuilder nc = new SafeHtmlBuilder();
 
     // Display the patch header
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
index 3faa998..72318dd 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.changes.ChangeScreen;
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java
index 1871bb7..98ae46f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java
@@ -24,11 +24,11 @@
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.common.errors.NotSignedInException;
 import com.google.gwt.core.client.GWT;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwt.user.client.rpc.InvocationException;
-import com.google.gwtjsonrpc.client.JsonUtil;
 import com.google.gwtjsonrpc.client.RemoteJsonException;
 import com.google.gwtjsonrpc.client.ServerUnavailableException;
+import com.google.gwtjsonrpc.common.JsonConstants;
 
 /** Abstract callback handling generic error conditions automatically */
 public abstract class GerritCallback<T> implements AsyncCallback<T> {
@@ -70,7 +70,7 @@
 
   private static boolean isInvalidXSRF(final Throwable caught) {
     return caught instanceof InvocationException
-        && caught.getMessage().equals(JsonUtil.ERROR_INVALID_XSRF);
+        && caught.getMessage().equals(JsonConstants.ERROR_INVALID_XSRF);
   }
 
   private static boolean isNotSignedIn(final Throwable caught) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountDashboardLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountDashboardLink.java
index bd8a1ce..5233a6b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountDashboardLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountDashboardLink.java
@@ -20,7 +20,7 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.AccountInfo;
 import com.google.gerrit.common.data.AccountInfoCache;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 /** Link to any user's account dashboard. */
 public class AccountDashboardLink extends InlineHyperlink {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
index 5d8ee8b..885f53b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.client.RpcStatus;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gwt.user.client.ui.SuggestOracle;
 import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
index 01d7d8b..fddae84 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/BranchLink.java
@@ -17,9 +17,9 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.changes.QueryScreen;
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Link to the open changes of a project. */
 public class BranchLink extends InlineHyperlink {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
index f022f7e..d708286 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
@@ -18,8 +18,8 @@
 import com.google.gerrit.client.changes.ChangeScreen;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ChangeInfo;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.DOM;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java
index f5ef2f4..a3c7a3c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentLinkProcessor.java
@@ -15,10 +15,10 @@
 package com.google.gerrit.client.ui;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwtexpui.safehtml.client.RegexFindReplace;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java
index 249c70c..0cea2c7 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java
@@ -35,11 +35,11 @@
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java
new file mode 100644
index 0000000..26b61f5
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentedActionDialog.java
@@ -0,0 +1,142 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.client.ui;
+
+import com.google.gerrit.client.Gerrit;
+import com.google.gerrit.client.rpc.GerritCallback;
+import com.google.gerrit.client.ui.SmallHeading;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.user.client.DOM;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwtexpui.globalkey.client.GlobalKey;
+import com.google.gwtexpui.globalkey.client.NpTextArea;
+import com.google.gwtexpui.user.client.AutoCenterDialogBox;
+
+public abstract class CommentedActionDialog<T> extends AutoCenterDialogBox
+    implements CloseHandler<PopupPanel> {
+  protected final FlowPanel panel;
+  protected final NpTextArea message;
+  protected final Button sendButton;
+  protected final Button cancelButton;
+  protected final FlowPanel buttonPanel;
+  protected AsyncCallback<T> callback;
+
+  protected boolean sent = false;
+
+  public CommentedActionDialog(final String title, final String heading,
+      AsyncCallback<T> callback) {
+    super(/* auto hide */false, /* modal */true);
+    this.callback = callback;
+
+    setGlassEnabled(true);
+    setText(title);
+
+    addStyleName(Gerrit.RESOURCES.css().commentedActionDialog());
+
+    message = new NpTextArea();
+    message.setCharacterWidth(60);
+    message.setVisibleLines(10);
+    DOM.setElementPropertyBoolean(message.getElement(), "spellcheck", true);
+
+    sendButton = new Button(Util.C.commentedActionButtonSend());
+    sendButton.addClickHandler(new ClickHandler() {
+      @Override
+      public void onClick(final ClickEvent event) {
+        enableButtons(false);
+        onSend();
+      }
+    });
+
+    cancelButton = new Button(Util.C.commentedActionButtonCancel());
+    DOM.setStyleAttribute(cancelButton.getElement(), "marginLeft", "300px");
+    cancelButton.addClickHandler(new ClickHandler() {
+      @Override
+      public void onClick(final ClickEvent event) {
+        hide();
+      }
+    });
+
+    final FlowPanel mwrap = new FlowPanel();
+    mwrap.setStyleName(Gerrit.RESOURCES.css().commentedActionMessage());
+    mwrap.add(message);
+
+    buttonPanel = new FlowPanel();
+    buttonPanel.add(sendButton);
+    buttonPanel.add(cancelButton);
+
+    panel = new FlowPanel();
+    panel.add(new SmallHeading(heading));
+    panel.add(mwrap);
+    panel.add(buttonPanel);
+    add(panel);
+
+    addCloseHandler(this);
+  }
+
+  public void enableButtons(boolean enable) {
+    sendButton.setEnabled(enable);
+    cancelButton.setEnabled(enable);
+  }
+
+  @Override
+  public void center() {
+    super.center();
+    GlobalKey.dialog(this);
+    message.setFocus(true);
+  }
+
+  @Override
+  public void onClose(CloseEvent<PopupPanel> event) {
+    if (!sent) {
+      // the dialog was closed without the send button being pressed
+      // e.g. the user pressed Cancel or ESC to close the dialog
+      if (callback != null) {
+        callback.onFailure(null);
+      }
+    }
+    sent = false;
+  }
+
+  public abstract void onSend();
+
+  public String getMessageText() {
+    return message.getText().trim();
+  }
+
+  public AsyncCallback<T> createCallback() {
+    return new GerritCallback<T>(){
+      @Override
+      public void onSuccess(T result) {
+        sent = true;
+        if (callback != null) {
+          callback.onSuccess(result);
+        }
+        hide();
+      }
+
+      @Override
+      public void onFailure(Throwable caught) {
+        enableButtons(true);
+        super.onFailure(caught);
+      }
+    };
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java
index 3fca1b1..1edb8fd 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/FancyFlexTable.java
@@ -21,8 +21,8 @@
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.client.ui.Widget;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 
 import java.util.Iterator;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
index 814fb1f..09550a6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.client.ui;
 
 import com.google.gerrit.client.Gerrit;
-
 import com.google.gwt.event.dom.client.BlurEvent;
 import com.google.gwt.event.dom.client.BlurHandler;
 import com.google.gwt.event.dom.client.FocusEvent;
@@ -24,10 +23,10 @@
 import com.google.gwt.event.dom.client.KeyDownEvent;
 import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
 import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.Widget;
 import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwtexpui.globalkey.client.NpTextBox;
 
 
 public class HintTextBox extends NpTextBox {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableAccountDiffPreference.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableAccountDiffPreference.java
index 41de2cd..27bc107 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableAccountDiffPreference.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableAccountDiffPreference.java
@@ -17,11 +17,11 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.account.Util;
 import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gwtjsonrpc.common.VoidResult;
 
 public class ListenableAccountDiffPreference
-    extends ListenableValue<AccountDiffPreference> {
+    extends ListenableOldValue<AccountDiffPreference> {
 
   public ListenableAccountDiffPreference() {
     reset();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
similarity index 63%
copy from gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java
copy to gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
index 8b13392..5c3e127 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ListenableOldValue.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2010 The Android Open Source Project
+// Copyright (C) 2012 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,12 +14,17 @@
 
 package com.google.gerrit.client.ui;
 
-import com.google.gwt.i18n.client.Constants;
+public class ListenableOldValue<T> extends ListenableValue<T> {
 
-public interface ProjectConstants extends Constants {
-  String projectName();
-  String projectDescription();
-  String projectListOpen();
-  String projectListPrev();
-  String projectListNext();
+  private T oldValue;
+
+  public T getOld() {
+    return oldValue;
+  }
+
+  public void set(final T value) {
+    oldValue = get();
+    super.set(value);
+    oldValue = null; // allow it to be gced before the next event
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java
index 0d45529..8d74bc3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/NavigationTable.java
@@ -20,11 +20,11 @@
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.UIObject;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java
index 5028540..f79dc51 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java
@@ -18,9 +18,11 @@
 import com.google.gerrit.client.changes.PatchTable;
 import com.google.gerrit.client.patches.PatchScreen;
 import com.google.gerrit.common.data.PatchSetDetail;
-import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 public class PatchLink extends InlineHyperlink {
+  protected PatchSet.Id base;
   protected Patch.Key patchKey;
   protected int patchIndex;
   protected PatchSetDetail patchSetDetail;
@@ -29,17 +31,19 @@
 
   /**
    * @param text The text of this link
+   * @param base optional base to compare against.
    * @param patchKey The key for this patch
    * @param patchIndex The index of the current patch in the patch set
    * @param historyToken The history token
    * @param patchSetDetail Detailed information about the patch set.
    * @param parentPatchTable The table used to display this link
    */
-  protected PatchLink(final String text, final Patch.Key patchKey,
-      final int patchIndex, final String historyToken,
-      final PatchSetDetail patchSetDetail, final PatchTable parentPatchTable,
-      final PatchScreen.TopView topView) {
+  protected PatchLink(String text, PatchSet.Id base, Patch.Key patchKey,
+      int patchIndex, String historyToken,
+      PatchSetDetail patchSetDetail, PatchTable parentPatchTable,
+      PatchScreen.TopView topView) {
     super(text, historyToken);
+    this.base = base;
     this.patchKey = patchKey;
     this.patchIndex = patchIndex;
     this.patchSetDetail = patchSetDetail;
@@ -53,9 +57,9 @@
    * @param type The type of the link to create (unified/side-by-side)
    * @param patchScreen The patchScreen to grab contents to link to from
    */
-  public PatchLink(final String text, final PatchScreen.Type type,
-      final PatchScreen patchScreen) {
+  public PatchLink(String text, PatchScreen.Type type, PatchScreen patchScreen) {
     this(text, //
+        patchScreen.getSideA(), //
         patchScreen.getPatchKey(), //
         patchScreen.getPatchIndex(), //
         Dispatcher.toPatch(type, patchScreen.getPatchKey()), //
@@ -69,6 +73,7 @@
   public void go() {
     Dispatcher.patch( //
         getTargetHistoryToken(), //
+        base, //
         patchKey, //
         patchIndex, //
         patchSetDetail, //
@@ -78,19 +83,21 @@
   }
 
   public static class SideBySide extends PatchLink {
-    public SideBySide(final String text, final Patch.Key patchKey,
-        final int patchIndex, PatchSetDetail patchSetDetail,
+    public SideBySide(String text, PatchSet.Id base, Patch.Key patchKey,
+        int patchIndex, PatchSetDetail patchSetDetail,
         PatchTable parentPatchTable) {
-      super(text, patchKey, patchIndex, Dispatcher.toPatchSideBySide(patchKey),
+      super(text, base, patchKey, patchIndex,
+          Dispatcher.toPatchSideBySide(base, patchKey),
           patchSetDetail, parentPatchTable, null);
     }
   }
 
   public static class Unified extends PatchLink {
-    public Unified(final String text, final Patch.Key patchKey,
-        final int patchIndex, PatchSetDetail patchSetDetail,
+    public Unified(String text, PatchSet.Id base, final Patch.Key patchKey,
+        int patchIndex, PatchSetDetail patchSetDetail,
         PatchTable parentPatchTable) {
-      super(text, patchKey, patchIndex, Dispatcher.toPatchUnified(patchKey),
+      super(text, base, patchKey, patchIndex,
+          Dispatcher.toPatchUnified(base, patchKey),
           patchSetDetail, parentPatchTable, null);
     }
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
index b2c4c3e..05def9c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectLink.java
@@ -17,9 +17,9 @@
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.changes.QueryScreen;
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Change.Status;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Change.Status;
 
 /** Link to the open changes of a project. */
 public class ProjectLink extends InlineHyperlink {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java
index 49fe165..be82eff 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectNameSuggestOracle.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.client.RpcStatus;
 import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.user.client.ui.SuggestOracle;
 import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
index 96089b9..b768643 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
@@ -15,8 +15,7 @@
 package com.google.gerrit.client.ui;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.ui.NavigationTable;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ReviewerSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ReviewerSuggestOracle.java
index 75a3b83..747ef40 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ReviewerSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ReviewerSuggestOracle.java
@@ -20,7 +20,7 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.common.data.AccountInfo;
 import com.google.gerrit.common.data.ReviewerInfo;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.user.client.ui.SuggestOracle;
 import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle;
 
@@ -30,13 +30,13 @@
 /** Suggestion Oracle for reviewers. */
 public class ReviewerSuggestOracle extends HighlightSuggestOracle {
 
-  private Project.NameKey project;
+  private Change.Id changeId;
 
   @Override
   protected void onRequestSuggestions(final Request req, final Callback callback) {
     RpcStatus.hide(new Runnable() {
       public void run() {
-        SuggestUtil.SVC.suggestReviewer(project, req.getQuery(),
+        SuggestUtil.SVC.suggestChangeReviewer(changeId, req.getQuery(),
             req.getLimit(), new GerritCallback<List<ReviewerInfo>>() {
               public void onSuccess(final List<ReviewerInfo> result) {
                 final List<ReviewerSuggestion> r =
@@ -52,8 +52,8 @@
     });
   }
 
-  public void setProject(final Project.NameKey project) {
-    this.project = project;
+  public void setChange(Change.Id changeId) {
+    this.changeId = changeId;
   }
 
   private static class ReviewerSuggestion implements SuggestOracle.Suggestion {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java
similarity index 86%
rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java
rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java
index 8b13392..ebbb049 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.java
@@ -16,7 +16,10 @@
 
 import com.google.gwt.i18n.client.Constants;
 
-public interface ProjectConstants extends Constants {
+public interface UIConstants extends Constants {
+  String commentedActionButtonSend();
+  String commentedActionButtonCancel();
+
   String projectName();
   String projectDescription();
   String projectListOpen();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties
similarity index 69%
rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.properties
rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties
index 15de117..aa00cee 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/UIConstants.properties
@@ -1,3 +1,6 @@
+commentedActionButtonSend = Submit
+commentedActionButtonCancel = Cancel
+
 projectName = Project Name
 projectDescription = Project Description
 projectListOpen = Select project
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java
index ebed764..98f13ef 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Util.java
@@ -17,5 +17,5 @@
 import com.google.gwt.core.client.GWT;
 
 public class Util {
-  public static final ProjectConstants C = GWT.create(ProjectConstants.class);
+  public static final UIConstants C = GWT.create(UIConstants.class);
 }
diff --git a/gerrit-httpd/pom.xml b/gerrit-httpd/pom.xml
index 6c2190d..a6374da 100644
--- a/gerrit-httpd/pom.xml
+++ b/gerrit-httpd/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-httpd</artifactId>
@@ -55,11 +55,6 @@
     </dependency>
 
     <dependency>
-      <groupId>com.google.gwt</groupId>
-      <artifactId>gwt-servlet</artifactId>
-    </dependency>
-
-    <dependency>
       <groupId>eu.medsea.mimeutil</groupId>
       <artifactId>mime-util</artifactId>
     </dependency>
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/AdvertisedObjectsCacheKey.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/AdvertisedObjectsCacheKey.java
index 95a4f14..d594d77 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/AdvertisedObjectsCacheKey.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/AdvertisedObjectsCacheKey.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.httpd;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Project;
 
 class AdvertisedObjectsCacheKey {
   private final Account.Id account;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
index 270b476..fb30a4d 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
@@ -19,8 +19,8 @@
 
 import com.google.gerrit.httpd.WebSessionManager.Key;
 import com.google.gerrit.httpd.WebSessionManager.Val;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.CurrentUser;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
index 468c6d8..9c4c598 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
@@ -69,6 +69,7 @@
         return;
     }
 
+    p.setIncludeComments(get(req, "comments", false));
     p.setIncludeCurrentPatchSet(get(req, "current-patch-set", false));
     p.setIncludePatchSets(get(req, "patch-sets", false));
     p.setIncludeApprovals(get(req, "all-approvals", false));
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
index b7709be..407784e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
@@ -3,7 +3,7 @@
 package com.google.gerrit.httpd;
 
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryParseException;
@@ -11,7 +11,7 @@
 import com.google.gerrit.server.query.change.ChangeDataSource;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryRewriter;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
index 469af22..1953480 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.GerritConfig;
-import com.google.gerrit.common.data.GitwebLink;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.common.data.GitwebConfig;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AnonymousCowardName;
@@ -127,7 +127,7 @@
     config.setEditableAccountFields(fields);
 
     if (gitWebConfig.getUrl() != null) {
-      config.setGitwebLink(new GitwebLink(gitWebConfig.getUrl(), gitWebConfig
+      config.setGitwebLink(new GitwebConfig(gitWebConfig.getUrl(), gitWebConfig
           .getGitWebType()));
     }
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
index 145891f..c36df04a 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java
@@ -15,13 +15,14 @@
 package com.google.gerrit.httpd;
 
 import com.google.gerrit.common.data.Capable;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.git.AsyncReceiveCommits;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ReceiveCommits;
 import com.google.gerrit.server.git.TagCache;
@@ -215,7 +216,7 @@
       }
 
       if (!pc.allRefsAreVisible()) {
-        up.setRefFilter(new VisibleRefFilter(tagCache, repo, pc, db.get(), true));
+        up.setAdvertiseRefsHook(new VisibleRefFilter(tagCache, repo, pc, db.get(), true));
       }
 
       next.doFilter(request, response);
@@ -231,11 +232,12 @@
   }
 
   static class ReceiveFactory implements ReceivePackFactory<HttpServletRequest> {
-    private final ReceiveCommits.Factory factory;
+    private final AsyncReceiveCommits.Factory factory;
     private final Provider<WebSession> session;
 
     @Inject
-    ReceiveFactory(ReceiveCommits.Factory factory, Provider<WebSession> session) {
+    ReceiveFactory(AsyncReceiveCommits.Factory factory,
+        Provider<WebSession> session) {
       this.factory = factory;
       this.session = session;
     }
@@ -251,7 +253,7 @@
       }
 
       final IdentifiedUser user = (IdentifiedUser) pc.getCurrentUser();
-      final ReceiveCommits rc = factory.create(pc, db);
+      final ReceiveCommits rc = factory.create(pc, db).getReceiveCommits();
       rc.getReceivePack().setRefLogIdent(user.newRefLogIdent());
       req.setAttribute(ATT_RC, rc);
       session.get().setAccessPath(AccessPath.GIT);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java
index 9f437bf..7de4bc3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitWebConfig.java
@@ -54,6 +54,7 @@
     type.setBranch(cfg.getString("gitweb", null, "branch"));
     type.setProject(cfg.getString("gitweb", null, "project"));
     type.setRevision(cfg.getString("gitweb", null, "revision"));
+    type.setFileHistory(cfg.getString("gitweb", null, "filehistory"));
     String pathSeparator = cfg.getString("gitweb", null, "pathSeparator");
     if (pathSeparator != null) {
       if (pathSeparator.length() == 1) {
@@ -77,6 +78,9 @@
     } else if (type.getRevision() == null) {
       log.warn("No Pattern specified for gitweb.revision, disabling.");
       type = null;
+    } else if (type.getFileHistory() == null) {
+      log.warn("No Pattern specified for gitweb.filehistory, disabling.");
+      type = null;
     }
 
     if ((cfgUrl != null && cfgUrl.isEmpty())
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpIdentifiedUserProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpIdentifiedUserProvider.java
index ba2d135..6c420a5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpIdentifiedUserProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpIdentifiedUserProvider.java
@@ -22,16 +22,16 @@
 import com.google.inject.ProvisionException;
 
 class HttpIdentifiedUserProvider implements Provider<IdentifiedUser> {
-  private final WebSession session;
+  private final Provider<CurrentUser> currUserProvider;
 
   @Inject
-  HttpIdentifiedUserProvider(WebSession session) {
-    this.session = session;
+  HttpIdentifiedUserProvider(Provider<CurrentUser> currUserProvider) {
+    this.currUserProvider = currUserProvider;
   }
 
   @Override
   public IdentifiedUser get() {
-    CurrentUser user = session.getCurrentUser();
+    CurrentUser user = currUserProvider.get();
     if (user instanceof IdentifiedUser) {
       return (IdentifiedUser) user;
     }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpLogoutServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpLogoutServlet.java
index 7b2c3f0..13a6f43 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpLogoutServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/HttpLogoutServlet.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd;
 
+import com.google.common.base.Strings;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.CanonicalWebUrl;
@@ -53,7 +54,17 @@
     if (logoutUrl != null) {
       rsp.sendRedirect(logoutUrl);
     } else {
-      rsp.sendRedirect(urlProvider.get());
+      String url = urlProvider.get();
+      if (Strings.isNullOrEmpty(url)) {
+        url = req.getContextPath();
+      }
+      if (Strings.isNullOrEmpty(url)) {
+        url = "/";
+      }
+      if (!url.endsWith("/")) {
+        url += "/";
+      }
+      rsp.sendRedirect(url);
     }
   }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
index 1964c29..f90c20d 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -23,8 +23,8 @@
 import com.google.gerrit.httpd.raw.SshInfoServlet;
 import com.google.gerrit.httpd.raw.StaticServlet;
 import com.google.gerrit.httpd.raw.ToolServlet;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwtexpui.server.CacheControlFilter;
 import com.google.inject.Key;
 import com.google.inject.Provider;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
index eb71733..8ee2c41 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java
@@ -36,6 +36,8 @@
 import com.google.gerrit.server.config.GerritRequestModule;
 import com.google.gerrit.server.contact.ContactStore;
 import com.google.gerrit.server.contact.ContactStoreProvider;
+import com.google.gerrit.server.util.GuiceRequestScopePropagator;
+import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -76,6 +78,7 @@
         filter("/*").through(RequestCleanupFilter.class);
       }
     });
+    bind(RequestScopePropagator.class).to(GuiceRequestScopePropagator.class);
 
     if (wantSSL) {
       install(new RequireSslFilter.Module());
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSession.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSession.java
index 869b8e7..2925896 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSession.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSession.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.httpd;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.AuthResult;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSessionManager.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSessionManager.java
index 186d5da..55d0ca5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSessionManager.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebSessionManager.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.httpd;
 
+import static com.google.gerrit.httpd.CacheBasedWebSession.MAX_AGE_MINUTES;
 import static com.google.gerrit.server.ioutil.BasicSerialization.readFixInt64;
 import static com.google.gerrit.server.ioutil.BasicSerialization.readString;
 import static com.google.gerrit.server.ioutil.BasicSerialization.readVarInt32;
@@ -21,13 +22,12 @@
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeFixInt64;
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeString;
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeVarInt32;
-import static com.google.gerrit.httpd.CacheBasedWebSession.MAX_AGE_MINUTES;
 import static java.util.concurrent.TimeUnit.HOURS;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
index d80cbaf..4710c39 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -14,22 +14,21 @@
 
 package com.google.gerrit.httpd.auth.become;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.httpd.HtmlDomUtil;
 import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.account.AuthResult;
-import com.google.gerrit.server.config.CanonicalWebUrl;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -44,7 +43,6 @@
 import java.util.List;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
@@ -58,17 +56,14 @@
 
   private final SchemaFactory<ReviewDb> schema;
   private final Provider<WebSession> webSession;
-  private final Provider<String> urlProvider;
   private final AccountManager accountManager;
 
   @Inject
   BecomeAnyAccountLoginServlet(final Provider<WebSession> ws,
       final SchemaFactory<ReviewDb> sf,
-      final @CanonicalWebUrl @Nullable Provider<String> up,
       final AccountManager am, final ServletContext servletContext) {
     webSession = ws;
     schema = sf;
-    urlProvider = up;
     accountManager = am;
   }
 
@@ -120,7 +115,7 @@
     if (res != null) {
       webSession.get().login(res, false);
       final StringBuilder rdr = new StringBuilder();
-      rdr.append(urlProvider.get());
+      rdr.append(req.getContextPath());
       if (IS_DEV && req.getParameter("gwt.codesvr") != null) {
         if (rdr.indexOf("?") < 0) {
           rdr.append("?");
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
index 1afd72d..eb8a76b 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpAuthFilter.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.httpd.HtmlDomUtil;
 import com.google.gerrit.httpd.WebSession;
 import com.google.gerrit.httpd.raw.HostPageServlet;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
index a77dfc9..9d14872 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/ldap/UserPassAuthServiceImpl.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.common.auth.userpass.LoginResult;
 import com.google.gerrit.common.auth.userpass.UserPassAuthService;
 import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.account.AccountUserNameException;
@@ -25,7 +25,7 @@
 import com.google.gerrit.server.account.AuthResult;
 import com.google.gerrit.server.auth.AuthenticationUnavailableException;
 import com.google.gerrit.server.config.AuthConfig;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
index a4df147..e397961 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.httpd.GitWebConfig;
 import com.google.gerrit.httpd.HtmlDomUtil;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java
index a72fd08..fb04226 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebServlet.java
@@ -32,7 +32,7 @@
 import com.google.gerrit.common.data.GerritConfig;
 import com.google.gerrit.httpd.GitWebConfig;
 import com.google.gerrit.launcher.GerritLauncher;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.SitePaths;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java
index b4c3519..adf4ad5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/CatServlet.java
@@ -14,16 +14,16 @@
 
 package com.google.gerrit.httpd.raw;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.FileTypeRegistry;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
index f105df0..6a43d95 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.gwtexpui.linker.server.Permutation;
 import com.google.gwtexpui.linker.server.PermutationSelector;
 import com.google.gwtjsonrpc.server.JsonServlet;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
index 5a72230..d387f6e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/LegacyGerritServlet.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.httpd.raw;
 
 import com.google.gerrit.httpd.HtmlDomUtil;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
index c33a2aa..988dadb 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticServlet.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.httpd.raw;
 
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
index 4a688aa..810cc2a 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
@@ -25,7 +25,7 @@
 import com.google.gerrit.common.Version;
 import com.google.gerrit.server.tools.ToolsCatalog;
 import com.google.gerrit.server.tools.ToolsCatalog.Entry;
-import com.google.gwt.user.server.rpc.RPCServletUtils;
+import com.google.gwtjsonrpc.server.RPCServletUtils;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
index ed21b39..26db6f9 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
@@ -18,14 +18,14 @@
 import com.google.gerrit.common.errors.InvalidQueryException;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 /** Support for services which require a {@link ReviewDb} instance. */
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
index 777d63e..9a101d3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
@@ -22,13 +22,14 @@
 import com.google.gerrit.common.data.ToggleStarRequest;
 import com.google.gerrit.common.errors.InvalidQueryException;
 import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeAccess;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.StarredChange;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.StarredChange;
+import com.google.gerrit.reviewdb.server.ChangeAccess;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.account.AccountControl;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
@@ -38,11 +39,11 @@
 import com.google.gerrit.server.query.change.ChangeDataSource;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
 import com.google.gerrit.server.query.change.ChangeQueryRewriter;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -253,6 +254,15 @@
           Collections.sort(d.getClosed(), SORT_KEY_COMP);
         }
 
+        // User dashboards are visible to other users, if the current user
+        // can see any of the changes in the dashboard.
+        if (!target.equals(me)
+            && d.getByOwner().isEmpty()
+            && d.getClosed().isEmpty()
+            && d.getForReview().isEmpty()) {
+          throw new Failure(new NoSuchEntityException());
+        }
+
         d.setAccounts(ac.create());
         return d;
       }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java
index 8f7754a..3513f89 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServlet.java
@@ -18,10 +18,10 @@
 import com.google.gerrit.common.errors.NotSignedInException;
 import com.google.gerrit.httpd.WebSession;
 import com.google.gson.GsonBuilder;
-import com.google.gwtjsonrpc.client.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
 import com.google.gwtjsonrpc.server.ActiveCall;
 import com.google.gwtjsonrpc.server.JsonServlet;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java
index 823ee7a..9361130 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/GerritJsonServletProvider.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.httpd.rpc;
 
-import com.google.gwtjsonrpc.client.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/Handler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/Handler.java
index 29aaf2c..911d1cc 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/Handler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/Handler.java
@@ -19,9 +19,9 @@
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.NoSuchRefException;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.concurrent.Callable;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/RpcServletModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/RpcServletModule.java
index 29abee6..876fee3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/RpcServletModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/RpcServletModule.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.httpd.rpc;
 
-import com.google.gwtjsonrpc.client.RemoteJsonService;
+import com.google.gwtjsonrpc.common.RemoteJsonService;
 import com.google.inject.Key;
 import com.google.inject.Scopes;
 import com.google.inject.internal.UniqueAnnotations;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
index bf77c6a..f3e8e65e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
@@ -19,25 +19,30 @@
 import com.google.gerrit.common.data.ReviewerInfo;
 import com.google.gerrit.common.data.SuggestService;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
+import com.google.gerrit.server.account.AccountControl;
+import com.google.gerrit.server.account.AccountVisibility;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.account.GroupControl;
 import com.google.gerrit.server.account.GroupMembers;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.patch.AddReviewer;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -45,7 +50,6 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -55,17 +59,18 @@
     SuggestService {
   private static final String MAX_SUFFIX = "\u9fa5";
 
+  private final Provider<ReviewDb> reviewDbProvider;
   private final ProjectControl.Factory projectControlFactory;
   private final ProjectCache projectCache;
   private final AccountCache accountCache;
   private final GroupControl.Factory groupControlFactory;
   private final GroupMembers.Factory groupMembersFactory;
-  private final IdentifiedUser.GenericFactory userFactory;
-  private final Provider<CurrentUser> currentUser;
-  private final SuggestAccountsEnum suggestAccounts;
+  private final IdentifiedUser.GenericFactory identifiedUserFactory;
+  private final AccountControl.Factory accountControlFactory;
+  private final ChangeControl.Factory changeControlFactory;
   private final Config cfg;
   private final GroupCache groupCache;
-
+  private final boolean suggestAccounts;
 
   @Inject
   SuggestServiceImpl(final Provider<ReviewDb> schema,
@@ -73,21 +78,37 @@
       final ProjectCache projectCache, final AccountCache accountCache,
       final GroupControl.Factory groupControlFactory,
       final GroupMembers.Factory groupMembersFactory,
-      final IdentifiedUser.GenericFactory userFactory,
       final Provider<CurrentUser> currentUser,
+      final IdentifiedUser.GenericFactory identifiedUserFactory,
+      final AccountControl.Factory accountControlFactory,
+      final ChangeControl.Factory changeControlFactory,
       @GerritServerConfig final Config cfg, final GroupCache groupCache) {
     super(schema, currentUser);
+    this.reviewDbProvider = schema;
     this.projectControlFactory = projectControlFactory;
     this.projectCache = projectCache;
     this.accountCache = accountCache;
     this.groupControlFactory = groupControlFactory;
     this.groupMembersFactory = groupMembersFactory;
-    this.userFactory = userFactory;
-    this.currentUser = currentUser;
-    this.suggestAccounts =
-        cfg.getEnum("suggest", null, "accounts", SuggestAccountsEnum.ALL);
+    this.identifiedUserFactory = identifiedUserFactory;
+    this.accountControlFactory = accountControlFactory;
+    this.changeControlFactory = changeControlFactory;
     this.cfg = cfg;
     this.groupCache = groupCache;
+
+    if ("OFF".equals(cfg.getString("suggest", null, "accounts"))) {
+      this.suggestAccounts = false;
+    } else {
+      boolean suggestAccounts;
+      try {
+        AccountVisibility av =
+            cfg.getEnum("suggest", null, "accounts", AccountVisibility.ALL);
+        suggestAccounts = (av != AccountVisibility.NONE);
+      } catch (IllegalArgumentException err) {
+        suggestAccounts = cfg.getBoolean("suggest", null, "accounts", true);
+      }
+      this.suggestAccounts = suggestAccounts;
+    }
   }
 
   public void suggestProjectNameKey(final String query, final int limit,
@@ -112,19 +133,29 @@
     callback.onSuccess(r);
   }
 
+  private interface VisibilityControl {
+    boolean isVisible(Account account) throws OrmException;
+  }
+
   public void suggestAccount(final String query, final Boolean active,
       final int limit, final AsyncCallback<List<AccountInfo>> callback) {
     run(callback, new Action<List<AccountInfo>>() {
       public List<AccountInfo> run(final ReviewDb db) throws OrmException {
-        return suggestAccount(db, query, active, limit);
+        return suggestAccount(db, query, active, limit, new VisibilityControl() {
+          @Override
+          public boolean isVisible(Account account) throws OrmException {
+            return accountControlFactory.get().canSee(account);
+          }
+        });
       }
     });
   }
 
   private List<AccountInfo> suggestAccount(final ReviewDb db,
-      final String query, final Boolean active, final int limit)
+      final String query, final Boolean active, final int limit,
+      VisibilityControl visibilityControl)
       throws OrmException {
-    if (suggestAccounts == SuggestAccountsEnum.OFF) {
+    if (!suggestAccounts) {
       return Collections.<AccountInfo> emptyList();
     }
 
@@ -136,12 +167,12 @@
     final LinkedHashMap<Account.Id, AccountInfo> r =
         new LinkedHashMap<Account.Id, AccountInfo>();
     for (final Account p : db.accounts().suggestByFullName(a, b, n)) {
-      addSuggestion(r, p, new AccountInfo(p), active);
+      addSuggestion(r, p, new AccountInfo(p), active, visibilityControl);
     }
     if (r.size() < n) {
       for (final Account p : db.accounts().suggestByPreferredEmail(a, b,
           n - r.size())) {
-        addSuggestion(r, p, new AccountInfo(p), active);
+        addSuggestion(r, p, new AccountInfo(p), active, visibilityControl);
       }
     }
     if (r.size() < n) {
@@ -151,7 +182,7 @@
           final Account p = accountCache.get(e.getAccountId()).getAccount();
           final AccountInfo info = new AccountInfo(p);
           info.setPreferredEmail(e.getEmailAddress());
-          addSuggestion(r, p, info, active);
+          addSuggestion(r, p, info, active, visibilityControl);
         }
       }
     }
@@ -159,57 +190,19 @@
   }
 
   private void addSuggestion(Map<Account.Id, AccountInfo> map, Account account,
-      AccountInfo info, Boolean active) {
+      AccountInfo info, Boolean active, VisibilityControl visibilityControl)
+      throws OrmException {
     if (map.containsKey(account.getId())) {
       return;
     }
     if (active != null && active != account.isActive()) {
       return;
     }
-    switch (suggestAccounts) {
-      case ALL:
-        map.put(account.getId(), info);
-        break;
-      case SAME_GROUP: {
-        Set<AccountGroup.UUID> usersGroups = groupsOf(account);
-        usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
-        usersGroups.remove(AccountGroup.REGISTERED_USERS);
-        for (AccountGroup.UUID myGroup : currentUser.get().getEffectiveGroups()) {
-          if (usersGroups.contains(myGroup)) {
-            map.put(account.getId(), info);
-            break;
-          }
-        }
-        break;
-      }
-      case VISIBLE_GROUP: {
-        Set<AccountGroup.UUID> usersGroups = groupsOf(account);
-        usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
-        usersGroups.remove(AccountGroup.REGISTERED_USERS);
-        for (AccountGroup.UUID usersGroup : usersGroups) {
-          try {
-            if (groupControlFactory.controlFor(usersGroup).isVisible()) {
-              map.put(account.getId(), info);
-              break;
-            }
-          } catch (NoSuchGroupException e) {
-            continue;
-          }
-        }
-        break;
-      }
-      case OFF:
-        break;
-      default:
-        throw new IllegalStateException("Bad SuggestAccounts " + suggestAccounts);
+    if (visibilityControl.isVisible(account)) {
+      map.put(account.getId(), info);
     }
   }
 
-  private Set<AccountGroup.UUID> groupsOf(Account account) {
-    IdentifiedUser user = userFactory.create(account.getId());
-    return new HashSet<AccountGroup.UUID>(user.getEffectiveGroups());
-  }
-
   public void suggestAccountGroup(final String query, final int limit,
       final AsyncCallback<List<GroupReference>> callback) {
     run(callback, new Action<List<GroupReference>>() {
@@ -242,13 +235,35 @@
   }
 
   @Override
-  public void suggestReviewer(final Project.NameKey project,
+  public void suggestReviewer(Project.NameKey project, String query, int limit,
+      AsyncCallback<List<ReviewerInfo>> callback) {
+    // The RPC is deprecated, but return an empty list for RPC API compatibility.
+    callback.onSuccess(Collections.<ReviewerInfo>emptyList());
+  }
+
+  @Override
+  public void suggestChangeReviewer(final Change.Id change,
       final String query, final int limit,
       final AsyncCallback<List<ReviewerInfo>> callback) {
     run(callback, new Action<List<ReviewerInfo>>() {
       public List<ReviewerInfo> run(final ReviewDb db) throws OrmException {
+        final ChangeControl changeControl;
+        try {
+          changeControl = changeControlFactory.controlFor(change);
+        } catch (NoSuchChangeException e) {
+          return Collections.emptyList();
+        }
+        VisibilityControl visibilityControl = new VisibilityControl() {
+          @Override
+          public boolean isVisible(Account account) throws OrmException {
+            IdentifiedUser who =
+                identifiedUserFactory.create(reviewDbProvider, account.getId());
+            return changeControl.forUser(who).isVisible(reviewDbProvider.get());
+          }
+        };
+
         final List<AccountInfo> suggestedAccounts =
-            suggestAccount(db, query, Boolean.TRUE, limit);
+            suggestAccount(db, query, Boolean.TRUE, limit, visibilityControl);
         final List<ReviewerInfo> reviewer =
             new ArrayList<ReviewerInfo>(suggestedAccounts.size());
         for (final AccountInfo a : suggestedAccounts) {
@@ -257,7 +272,7 @@
         final List<GroupReference> suggestedAccountGroups =
             suggestAccountGroup(db, query, limit);
         for (final GroupReference g : suggestedAccountGroups) {
-          if (suggestGroupAsReviewer(project, g)) {
+          if (suggestGroupAsReviewer(changeControl.getProject().getNameKey(), g)) {
             reviewer.add(new ReviewerInfo(g));
           }
         }
@@ -300,4 +315,4 @@
 
     return true;
   }
-}
\ No newline at end of file
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java
index 393c44b..9de7d88 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SystemInfoServiceImpl.java
@@ -17,13 +17,13 @@
 import com.google.gerrit.common.data.GerritConfig;
 import com.google.gerrit.common.data.SshHostKey;
 import com.google.gerrit.common.data.SystemInfoService;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ssh.SshInfo;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
index be28840..aa94759f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
@@ -24,14 +24,14 @@
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountSshKey;
-import com.google.gerrit.reviewdb.AuthType;
-import com.google.gerrit.reviewdb.ContactInformation;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.client.ContactInformation;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountByEmailCache;
@@ -49,9 +49,9 @@
 import com.google.gerrit.server.mail.EmailTokenVerifier;
 import com.google.gerrit.server.mail.RegisterNewEmailSender;
 import com.google.gerrit.server.ssh.SshKeyCache;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
index 3951554..2fe3124 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
@@ -20,22 +20,22 @@
 import com.google.gerrit.common.errors.InvalidQueryException;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.query.QueryParseException;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmDuplicateKeyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
index 4f62330..39712e4 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AgreementInfoFactory.java
@@ -16,11 +16,11 @@
 
 import com.google.gerrit.common.data.AgreementInfo;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupAgreement;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.inject.Inject;
@@ -59,7 +59,7 @@
 
     final List<AccountGroupAgreement> groupAccepted =
         new ArrayList<AccountGroupAgreement>();
-    for (final AccountGroup.UUID groupUUID : user.getEffectiveGroups()) {
+    for (final AccountGroup.UUID groupUUID : user.getEffectiveGroups().getKnownGroups()) {
       AccountGroup group = groupCache.get(groupUUID);
       if (group == null) {
         continue;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
index 6639ac5..ebebd04 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
@@ -17,11 +17,11 @@
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
 import com.google.gerrit.common.errors.PermissionDeniedException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.PerformCreateGroup;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/DeleteExternalIds.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/DeleteExternalIds.java
index 4edd571..12bc761 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/DeleteExternalIds.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/DeleteExternalIds.java
@@ -15,12 +15,12 @@
 package com.google.gerrit.httpd.rpc.account;
 
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountByEmailCache;
 import com.google.gerrit.server.account.AccountCache;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/ExternalIdDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/ExternalIdDetailFactory.java
index de0dec9..d876f2e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/ExternalIdDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/ExternalIdDetailFactory.java
@@ -14,15 +14,15 @@
 
 package com.google.gerrit.httpd.rpc.account;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
 import com.google.gerrit.httpd.WebSession;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.AuthConfig;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import java.util.Collections;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
index 448baf9..e90c2bf 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
@@ -24,13 +24,13 @@
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupIncludeAudit;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupIncludeAudit;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountResolver;
@@ -38,9 +38,9 @@
 import com.google.gerrit.server.account.GroupControl;
 import com.google.gerrit.server.account.GroupIncludeCache;
 import com.google.gerrit.server.account.Realm;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -131,7 +131,6 @@
         final AccountGroup group = db.accountGroups().get(groupId);
         assertAmGroupOwner(db, group);
         group.setVisibleToAll(groupOptions.isVisibleToAll());
-        group.setEmailOnlyAuthors(groupOptions.isEmailOnlyAuthors());
         db.accountGroups().update(Collections.singleton(group));
         groupCache.evict(group);
         return VoidResult.INSTANCE;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupDetailHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupDetailHandler.java
index 513c90f..ce74218 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupDetailHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupDetailHandler.java
@@ -17,9 +17,9 @@
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.GroupDetailFactory;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/MyGroupsFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/MyGroupsFactory.java
index d0557ae..fd274fd 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/MyGroupsFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/MyGroupsFactory.java
@@ -19,7 +19,7 @@
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.VisibleGroups;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import java.util.List;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/RenameGroup.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/RenameGroup.java
index 2d7770e..09dc582 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/RenameGroup.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/RenameGroup.java
@@ -18,9 +18,9 @@
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.PerformRenameGroup;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
index c8bb0f7..3aecb0c 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/AbandonChangeHandler.java
@@ -18,13 +18,13 @@
 import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.changedetail.AbandonChange;
 import com.google.gerrit.server.mail.EmailException;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
index d226fd0..47a9395 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
@@ -22,17 +22,16 @@
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetAncestor;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.ChangeUtil;
-import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
 import com.google.gerrit.server.config.GerritServerConfig;
@@ -42,8 +41,8 @@
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.workflow.CategoryFunction;
 import com.google.gerrit.server.workflow.FunctionState;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -130,6 +129,8 @@
 
     detail.setCanRevert(change.getStatus() == Change.Status.MERGED && control.canAddPatchSet());
 
+    detail.setCanRebase(detail.getChange().getStatus().isOpen() && control.canRebase());
+
     detail.setCanEdit(control.getRefControl().canWrite());
 
     if (detail.getChange().getStatus().isOpen()) {
@@ -161,7 +162,6 @@
   private void loadPatchSets() throws OrmException {
     ResultSet<PatchSet> source = db.patchSets().byChange(changeId);
     List<PatchSet> patches = new ArrayList<PatchSet>();
-    CurrentUser user = control.getCurrentUser();
     for (PatchSet ps : source) {
       if (control.isPatchVisible(ps, db)) {
         patches.add(ps);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
index fa0579e..8090451 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
@@ -19,10 +19,10 @@
 import com.google.gerrit.common.data.IncludedInDetail;
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.common.data.PatchSetPublishDetail;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.inject.Inject;
 
 class ChangeDetailServiceImpl implements ChangeDetailService {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
index f055498..f99921b 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeManageServiceImpl.java
@@ -16,14 +16,15 @@
 
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.ChangeManageService;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
 import com.google.inject.Inject;
 
 class ChangeManageServiceImpl implements ChangeManageService {
   private final SubmitAction.Factory submitAction;
   private final AbandonChangeHandler.Factory abandonChangeHandlerFactory;
+  private final RebaseChange.Factory rebaseChangeFactory;
   private final RestoreChangeHandler.Factory restoreChangeHandlerFactory;
   private final RevertChange.Factory revertChangeFactory;
   private final PublishAction.Factory publishAction;
@@ -32,12 +33,14 @@
   @Inject
   ChangeManageServiceImpl(final SubmitAction.Factory patchSetAction,
       final AbandonChangeHandler.Factory abandonChangeHandlerFactory,
+      final RebaseChange.Factory rebaseChangeFactory,
       final RestoreChangeHandler.Factory restoreChangeHandlerFactory,
       final RevertChange.Factory revertChangeFactory,
       final PublishAction.Factory publishAction,
       final DeleteDraftChange.Factory deleteDraftChangeFactory) {
     this.submitAction = patchSetAction;
     this.abandonChangeHandlerFactory = abandonChangeHandlerFactory;
+    this.rebaseChangeFactory = rebaseChangeFactory;
     this.restoreChangeHandlerFactory = restoreChangeHandlerFactory;
     this.revertChangeFactory = revertChangeFactory;
     this.publishAction = publishAction;
@@ -54,6 +57,11 @@
     abandonChangeHandlerFactory.create(patchSetId, message).to(callback);
   }
 
+  public void rebaseChange(final PatchSet.Id patchSetId,
+      final AsyncCallback<ChangeDetail> callback) {
+    rebaseChangeFactory.create(patchSetId).to(callback);
+  }
+
   public void revertChange(final PatchSet.Id patchSetId, final String message,
       final AsyncCallback<ChangeDetail> callback) {
     revertChangeFactory.create(patchSetId, message).to(callback);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
index 4224293..b672a439 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeModule.java
@@ -31,6 +31,7 @@
         factory(AbandonChangeHandler.Factory.class);
         factory(RestoreChangeHandler.Factory.class);
         factory(RevertChange.Factory.class);
+        factory(RebaseChange.Factory.class);
         factory(ChangeDetailFactory.Factory.class);
         factory(IncludedInDetailFactory.Factory.class);
         factory(PatchSetDetailFactory.Factory.class);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/DeleteDraftChange.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/DeleteDraftChange.java
index ab809ce..66c11c0 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/DeleteDraftChange.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/DeleteDraftChange.java
@@ -15,16 +15,16 @@
 package com.google.gerrit.httpd.rpc.changedetail;
 
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ReplicationQueue;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java
index 398ca7e..c07ee51 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/IncludedInDetailFactory.java
@@ -17,13 +17,13 @@
 import com.google.gerrit.common.data.IncludedInDetail;
 import com.google.gerrit.common.errors.InvalidRevisionException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
index 9ef715f..de3ff2f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
@@ -17,15 +17,15 @@
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.AccountPatchReview;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountPatchReview;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.patch.PatchList;
@@ -35,7 +35,7 @@
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
index 32a58d0..638bfe3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetPublishDetailFactory.java
@@ -20,19 +20,19 @@
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PublishAction.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PublishAction.java
index f6241fa..4ea279f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PublishAction.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PublishAction.java
@@ -18,11 +18,11 @@
 import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.changedetail.PublishDraft;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RebaseChange.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RebaseChange.java
new file mode 100644
index 0000000..3c29074
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RebaseChange.java
@@ -0,0 +1,110 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.rpc.changedetail;
+
+import com.google.gerrit.common.ChangeHookRunner;
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.common.data.ChangeDetail;
+import com.google.gerrit.common.errors.NoSuchEntityException;
+import com.google.gerrit.httpd.rpc.Handler;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.git.ReplicationQueue;
+import com.google.gerrit.server.mail.EmailException;
+import com.google.gerrit.server.mail.RebasedPatchSetSender;
+import com.google.gerrit.server.patch.PatchSetInfoFactory;
+import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
+import com.google.gerrit.server.project.ChangeControl;
+import com.google.gerrit.server.project.InvalidChangeOperationException;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.PersonIdent;
+
+import java.io.IOException;
+
+class RebaseChange extends Handler<ChangeDetail> {
+  interface Factory {
+    RebaseChange create(PatchSet.Id patchSetId);
+  }
+
+  private final ChangeControl.Factory changeControlFactory;
+  private final ReviewDb db;
+  private final IdentifiedUser currentUser;
+  private final RebasedPatchSetSender.Factory rebasedPatchSetSenderFactory;
+
+  private final ChangeDetailFactory.Factory changeDetailFactory;
+  private final ReplicationQueue replication;
+
+  private final PatchSet.Id patchSetId;
+
+  private final ChangeHookRunner hooks;
+
+  private final GitRepositoryManager gitManager;
+  private final PatchSetInfoFactory patchSetInfoFactory;
+
+  private final PersonIdent myIdent;
+
+  private final ApprovalTypes approvalTypes;
+
+  @Inject
+  RebaseChange(final ChangeControl.Factory changeControlFactory,
+      final ReviewDb db, final IdentifiedUser currentUser,
+      final RebasedPatchSetSender.Factory rebasedPatchSetSenderFactory,
+      final ChangeDetailFactory.Factory changeDetailFactory,
+      @Assisted final PatchSet.Id patchSetId, final ChangeHookRunner hooks,
+      final GitRepositoryManager gitManager,
+      final PatchSetInfoFactory patchSetInfoFactory,
+      final ReplicationQueue replication,
+      @GerritPersonIdent final PersonIdent myIdent,
+      final ApprovalTypes approvalTypes) {
+    this.changeControlFactory = changeControlFactory;
+    this.db = db;
+    this.currentUser = currentUser;
+    this.rebasedPatchSetSenderFactory = rebasedPatchSetSenderFactory;
+    this.changeDetailFactory = changeDetailFactory;
+
+    this.patchSetId = patchSetId;
+    this.hooks = hooks;
+    this.gitManager = gitManager;
+
+    this.patchSetInfoFactory = patchSetInfoFactory;
+    this.replication = replication;
+    this.myIdent = myIdent;
+
+    this.approvalTypes = approvalTypes;
+  }
+
+  @Override
+  public ChangeDetail call() throws NoSuchChangeException, OrmException,
+      EmailException, NoSuchEntityException, PatchSetInfoNotAvailableException,
+      MissingObjectException, IncorrectObjectTypeException, IOException,
+      InvalidChangeOperationException {
+
+    ChangeUtil.rebaseChange(patchSetId, currentUser, db,
+        rebasedPatchSetSenderFactory, hooks, gitManager, patchSetInfoFactory,
+        replication, myIdent, changeControlFactory, approvalTypes);
+
+    return changeDetailFactory.create(patchSetId.getParentKey()).call();
+  }
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
index 667861a..f018750 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChangeHandler.java
@@ -18,13 +18,13 @@
 import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.changedetail.RestoreChange;
 import com.google.gerrit.server.mail.EmailException;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RevertChange.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RevertChange.java
index da74941..9fb9ae1 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RevertChange.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RevertChange.java
@@ -18,9 +18,9 @@
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
@@ -32,7 +32,7 @@
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/SubmitAction.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/SubmitAction.java
index 38574bc..80100ad 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/SubmitAction.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/SubmitAction.java
@@ -18,12 +18,12 @@
 import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.changedetail.Submit;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewerHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewerHandler.java
index 953657b..60d6e60 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewerHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewerHandler.java
@@ -17,7 +17,7 @@
 import com.google.gerrit.common.data.ReviewerResult;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.httpd.rpc.changedetail.ChangeDetailFactory;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.patch.AddReviewer;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
index 50d6cea..e90467e 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchDetailServiceImpl.java
@@ -14,45 +14,41 @@
 
 package com.google.gerrit.httpd.rpc.patch;
 
-import com.google.gerrit.common.data.ChangeDetail;
-import com.google.gerrit.common.data.ReviewerResult;
-import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.data.ApprovalSummary;
 import com.google.gerrit.common.data.ApprovalSummarySet;
 import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.PatchDetailService;
 import com.google.gerrit.common.data.PatchScript;
+import com.google.gerrit.common.data.ReviewResult;
+import com.google.gerrit.common.data.ReviewerResult;
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.httpd.rpc.changedetail.ChangeDetailFactory;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountPatchReview;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.Patch.Key;
-import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountPatchReview;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Patch.Key;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
 import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.ReplicationQueue;
-import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.patch.PublishComments;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.workflow.FunctionState;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -75,9 +71,6 @@
   private final PublishComments.Factory publishCommentsFactory;
   private final PatchScriptFactory.Factory patchScriptFactoryFactory;
   private final SaveDraft.Factory saveDraftFactory;
-  private final PatchSetInfoFactory patchSetInfoFactory;
-  private final GitRepositoryManager gitManager;
-  private final ReplicationQueue replication;
   private final ChangeDetailFactory.Factory changeDetailFactory;
 
   @Inject
@@ -93,9 +86,6 @@
       final PatchScriptFactory.Factory patchScriptFactoryFactory,
       final PublishComments.Factory publishCommentsFactory,
       final SaveDraft.Factory saveDraftFactory,
-      final PatchSetInfoFactory patchSetInfoFactory,
-      final GitRepositoryManager gitManager,
-      final ReplicationQueue replication,
       final ChangeDetailFactory.Factory changeDetailFactory) {
     super(schema, currentUser);
     this.approvalTypes = approvalTypes;
@@ -109,9 +99,6 @@
     this.patchScriptFactoryFactory = patchScriptFactoryFactory;
     this.publishCommentsFactory = publishCommentsFactory;
     this.saveDraftFactory = saveDraftFactory;
-    this.patchSetInfoFactory = patchSetInfoFactory;
-    this.gitManager = gitManager;
-    this.replication = replication;
     this.changeDetailFactory = changeDetailFactory;
   }
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
index 302135e..ad7746f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
@@ -19,12 +19,12 @@
 import com.google.gerrit.common.data.PatchScript.DisplayMethod;
 import com.google.gerrit.prettify.common.EditList;
 import com.google.gerrit.prettify.common.SparseFileContent;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 import com.google.gerrit.server.FileTypeRegistry;
 import com.google.gerrit.server.patch.IntraLineDiff;
 import com.google.gerrit.server.patch.IntraLineDiffKey;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptFactory.java
index 5a60623..66b3278 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptFactory.java
@@ -17,16 +17,16 @@
 import com.google.gerrit.common.data.CommentDetail;
 import com.google.gerrit.common.data.PatchScript;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.Patch.ChangeType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
@@ -37,7 +37,7 @@
 import com.google.gerrit.server.patch.PatchListKey;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/RemoveReviewerHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/RemoveReviewerHandler.java
index 8849e8e..2b31c1c 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/RemoveReviewerHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/RemoveReviewerHandler.java
@@ -17,8 +17,8 @@
 import com.google.gerrit.common.data.ReviewerResult;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.httpd.rpc.changedetail.ChangeDetailFactory;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.patch.RemoveReviewer;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/SaveDraft.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/SaveDraft.java
index 0f14635..06c21df 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/SaveDraft.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/SaveDraft.java
@@ -15,17 +15,17 @@
 package com.google.gerrit.httpd.rpc.patch;
 
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
index db03f16..44c3141 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
@@ -19,8 +19,8 @@
 import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.common.errors.InvalidRevisionException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ReplicationQueue;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java
index 18d037f..777329b 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectAccess.java
@@ -22,8 +22,8 @@
 import com.google.gerrit.common.errors.InvalidNameException;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.ProjectConfig;
@@ -31,14 +31,13 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.RefControl;
-import com.google.gwtorm.client.OrmConcurrencyException;
+import com.google.gwtorm.server.OrmConcurrencyException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -117,28 +116,12 @@
           }
           replace(config, toDelete, section);
 
-        } else if (AccessSection.isAccessSection(name)) {
+        } else if (AccessSection.isValid(name)) {
           if (!projectControl.controlForRef(name).isOwner()) {
             continue;
           }
 
-          if (name.startsWith(AccessSection.REGEX_PREFIX)) {
-            if (!Repository.isValidRefName(RefControl.shortestExample(name))) {
-              throw new InvalidNameException();
-            }
-
-          } else if (name.equals(AccessSection.ALL)) {
-            // This is a special case we have to allow, it fails below.
-
-          } else if (name.endsWith("/*")) {
-            String prefix = name.substring(0, name.length() - 2);
-            if (!Repository.isValidRefName(prefix)) {
-              throw new InvalidNameException();
-            }
-
-          } else if (!Repository.isValidRefName(name)) {
-            throw new InvalidNameException();
-          }
+          RefControl.validateRefPattern(name);
 
           replace(config, toDelete, section);
         }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectSettings.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectSettings.java
index 7d1ad51..bd6e460 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectSettings.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ChangeProjectSettings.java
@@ -16,15 +16,15 @@
 
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.ProjectConfig;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.PerRequestProjectControlCache;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.OrmConcurrencyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmConcurrencyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/CreateProjectHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/CreateProjectHandler.java
index 8360615..039a301 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/CreateProjectHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/CreateProjectHandler.java
@@ -16,13 +16,13 @@
 
 import com.google.gerrit.common.errors.ProjectCreationFailedException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.SubmitType;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
 import com.google.gerrit.server.project.CreateProject;
 import com.google.gerrit.server.project.CreateProjectArgs;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gwtjsonrpc.common.VoidResult;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteBranches.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteBranches.java
index 0f19bbc..073e2d7 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteBranches.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/DeleteBranches.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ReplicationQueue;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
index 7be0f66..68fde45 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ListBranches.java
@@ -16,9 +16,9 @@
 
 import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
index d2a2900..7ac4ec3 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
@@ -18,10 +18,11 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.data.ProjectAccess;
+import com.google.gerrit.common.data.RefConfigSection;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.account.GroupControl;
 import com.google.gerrit.server.config.AllProjectsName;
@@ -122,7 +123,7 @@
           ownerOf.add(name);
         }
 
-      } else if (AccessSection.isAccessSection(name)) {
+      } else if (RefConfigSection.isValid(name)) {
         RefControl rc = pc.controlForRef(name);
         if (rc.isOwner()) {
           local.add(section);
@@ -184,17 +185,12 @@
       detail.setRevision(config.getRevision().name());
     }
 
+    detail.setInheritsFrom(config.getProject().getParent(allProjectsName));
+
     if (projectName.equals(allProjectsName)) {
       if (pc.isOwner()) {
         ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
       }
-      detail.setInheritsFrom(null);
-
-    } else if (config.getProject().getParent() != null) {
-      detail.setInheritsFrom(config.getProject().getParent());
-
-    } else {
-      detail.setInheritsFrom(allProjectsName);
     }
 
     detail.setLocal(local);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
index bf7eeae..a6bb74f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAdminServiceImpl.java
@@ -20,10 +20,10 @@
 import com.google.gerrit.common.data.ProjectAdminService;
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.common.data.ProjectList;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.gwtjsonrpc.client.VoidResult;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gwtjsonrpc.common.AsyncCallback;
+import com.google.gwtjsonrpc.common.VoidResult;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
index 05f66e9..d782da4 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectDetailFactory.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/SuggestParentCandidatesHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/SuggestParentCandidatesHandler.java
index a6442e3..ba0e4cd 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/SuggestParentCandidatesHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/SuggestParentCandidatesHandler.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.httpd.rpc.project;
 
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.SuggestParentCandidates;
 import com.google.inject.Inject;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjectDetails.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjectDetails.java
index 9899147..e12cfb1 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjectDetails.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjectDetails.java
@@ -17,7 +17,7 @@
 
 import com.google.gerrit.common.data.ProjectDetail;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
index 8d4596f..ba65617 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/VisibleProjects.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.data.ProjectList;
 import com.google.gerrit.httpd.rpc.Handler;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectCache;
diff --git a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
index 51fcf2e..5cfde6a 100644
--- a/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
+++ b/gerrit-httpd/src/test/java/com/google/gerrit/httpd/rpc/project/ListBranchesTest.java
@@ -31,8 +31,8 @@
 import static org.junit.Assert.fail;
 
 import com.google.gerrit.common.data.ListBranchesResult;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
diff --git a/gerrit-launcher/pom.xml b/gerrit-launcher/pom.xml
index 5707a22..7d07652 100644
--- a/gerrit-launcher/pom.xml
+++ b/gerrit-launcher/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-launcher</artifactId>
diff --git a/gerrit-main/pom.xml b/gerrit-main/pom.xml
index 96f1886..9d8320c 100644
--- a/gerrit-main/pom.xml
+++ b/gerrit-main/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-main</artifactId>
diff --git a/gerrit-openid/pom.xml b/gerrit-openid/pom.xml
index 74328cc..ed2625e 100644
--- a/gerrit-openid/pom.xml
+++ b/gerrit-openid/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-openid</artifactId>
@@ -50,11 +50,6 @@
     </dependency>
 
     <dependency>
-      <groupId>com.google.gwt</groupId>
-      <artifactId>gwt-servlet</artifactId>
-    </dependency>
-
-    <dependency>
       <groupId>org.openid4java</groupId>
       <artifactId>openid4java-consumer</artifactId>
       <type>pom</type>
diff --git a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
index 02ef765..0593bce 100644
--- a/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
+++ b/gerrit-openid/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.common.auth.openid.OpenIdService;
 import com.google.gerrit.common.auth.openid.OpenIdUrls;
 import com.google.gerrit.httpd.WebSession;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.UrlEncoded;
 import com.google.gerrit.server.account.AccountException;
@@ -30,7 +30,7 @@
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwtjsonrpc.common.AsyncCallback;
 import com.google.gwtorm.client.KeyUtil;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
diff --git a/gerrit-patch-commonsnet/pom.xml b/gerrit-patch-commonsnet/pom.xml
index f267920..75ee12e 100644
--- a/gerrit-patch-commonsnet/pom.xml
+++ b/gerrit-patch-commonsnet/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-patch-commonsnet</artifactId>
diff --git a/gerrit-patch-jgit/pom.xml b/gerrit-patch-jgit/pom.xml
index 4c2aa0b..f8190f5 100644
--- a/gerrit-patch-jgit/pom.xml
+++ b/gerrit-patch-jgit/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-patch-jgit</artifactId>
diff --git a/gerrit-pgm/pom.xml b/gerrit-pgm/pom.xml
index e816797..1463d15 100644
--- a/gerrit-pgm/pom.xml
+++ b/gerrit-pgm/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-pgm</artifactId>
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
index 7382096..25b7699 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.httpd.WebSshGlueModule;
 import com.google.gerrit.httpd.auth.openid.OpenIdModule;
 import com.google.gerrit.lifecycle.LifecycleManager;
+import com.google.gerrit.pgm.http.jetty.GetUserFilter;
 import com.google.gerrit.pgm.http.jetty.JettyEnv;
 import com.google.gerrit.pgm.http.jetty.JettyModule;
 import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter;
@@ -32,7 +33,7 @@
 import com.google.gerrit.pgm.util.LogFileCompressor;
 import com.google.gerrit.pgm.util.RuntimeShutdown;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.AuthConfigModule;
 import com.google.gerrit.server.config.CanonicalWebUrlModule;
@@ -41,6 +42,7 @@
 import com.google.gerrit.server.config.MasterNodeStartup;
 import com.google.gerrit.server.contact.HttpContactStoreConnection;
 import com.google.gerrit.server.git.PushReplication;
+import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
 import com.google.gerrit.server.mail.SmtpEmailSender;
@@ -200,6 +202,7 @@
     modules.add(new LogFileCompressor.Module());
     modules.add(new WorkQueue.Module());
     modules.add(new ChangeHookRunner.Module());
+    modules.add(new ReceiveCommitsExecutorModule());
     modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
     modules.add(new EhcachePoolImpl.Module());
     modules.add(new SmtpEmailSender.Module());
@@ -274,6 +277,7 @@
     if (authConfig.getAuthType() == AuthType.OPENID) {
       modules.add(new OpenIdModule());
     }
+    modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
 
     return sysInjector.createChildInjector(modules);
   }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
index 7842b6c..5f0bc80 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ExportReviewNotes.java
@@ -21,10 +21,10 @@
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountCacheImpl;
 import com.google.gerrit.server.account.GroupCacheImpl;
 import com.google.gerrit.server.cache.CachePool;
@@ -37,8 +37,8 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 import com.google.gerrit.server.schema.SchemaVersionCheck;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -97,7 +97,6 @@
             Scopes.SINGLETON);
         bind(String.class).annotatedWith(CanonicalWebUrl.class)
             .toProvider(CanonicalWebUrlProvider.class).in(Scopes.SINGLETON);
-        bind(CachePool.class);
 
         install(AccountCacheImpl.module());
         install(GroupCacheImpl.module());
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
index 68ac33d..f06946f 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
@@ -28,18 +28,18 @@
 import com.google.gerrit.pgm.util.ErrorLogFile;
 import com.google.gerrit.pgm.util.IoUtil;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.schema.SchemaUpdater;
 import com.google.gerrit.server.schema.UpdateUI;
 import com.google.gerrit.server.util.HostPlatform;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
-import com.google.gwtorm.client.StatementExecutor;
 import com.google.gwtorm.jdbc.JdbcExecutor;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.gwtorm.server.StatementExecutor;
 import com.google.inject.AbstractModule;
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
index 082279c..323d7f28 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
@@ -18,11 +18,11 @@
 
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.schema.SchemaVersionCheck;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ProtoGen.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ProtoGen.java
index bc7b254..17b7017 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ProtoGen.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ProtoGen.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.pgm;
 
 import com.google.gerrit.pgm.util.AbstractProgram;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gwtorm.schema.java.JavaSchemaModel;
 
 import org.eclipse.jgit.storage.file.LockFile;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Rulec.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Rulec.java
index 19b1ab9..451ed30 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Rulec.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Rulec.java
@@ -18,7 +18,7 @@
 
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.rules.PrologCompiler;
 import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.git.GitRepositoryManager;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ScanTrackingIds.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ScanTrackingIds.java
index 8bf5f98..c09329a 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ScanTrackingIds.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/ScanTrackingIds.java
@@ -18,16 +18,16 @@
 
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.config.TrackingFooters;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.schema.SchemaVersionCheck;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java
new file mode 100644
index 0000000..f54b3c5
--- /dev/null
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java
@@ -0,0 +1,86 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.pgm.http.jetty;
+
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.servlet.ServletModule;
+
+import org.eclipse.jgit.lib.Config;
+
+import java.io.IOException;
+import java.net.URI;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * Stores as a request attribute, so the {@link HttpLog} can include the the
+ * user for the request outside of the request scope.
+ */
+@Singleton
+public class GetUserFilter implements Filter {
+
+  static final String REQ_ATTR_KEY = CurrentUser.class.toString();
+
+  public static class Module extends ServletModule {
+
+    private boolean loggingEnabled;
+
+    @Inject
+    Module(@GerritServerConfig final Config cfg) {
+      URI[] urls = JettyServer.listenURLs(cfg);
+      boolean reverseProxy = JettyServer.isReverseProxied(urls);
+      this.loggingEnabled = cfg.getBoolean("httpd", "requestlog", !reverseProxy);
+    }
+
+    @Override
+    protected void configureServlets() {
+      if (loggingEnabled) {
+        filter("/*").through(GetUserFilter.class);
+      }
+    }
+  }
+
+  private final Provider<CurrentUser> userProvider;
+
+  @Inject
+  GetUserFilter(final Provider<CurrentUser> userProvider) {
+    this.userProvider = userProvider;
+  }
+
+  @Override
+  public void doFilter(
+      ServletRequest req, ServletResponse resp, FilterChain chain)
+      throws IOException, ServletException {
+    req.setAttribute(REQ_ATTR_KEY, userProvider.get());
+    chain.doFilter(req, resp);
+  }
+
+  @Override
+  public void destroy() {
+  }
+
+  @Override
+  public void init(FilterConfig arg0) {
+  }
+}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HttpLog.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
index a4e13d3..65e73bd 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HttpLog.java
@@ -17,8 +17,6 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Provider;
-import com.google.inject.servlet.GuiceHelper;
 
 import org.apache.log4j.Appender;
 import org.apache.log4j.AsyncAppender;
@@ -55,11 +53,8 @@
   private static final String P_USER_AGENT = "User-Agent";
 
   private final AsyncAppender async;
-  private final Provider<CurrentUser> userProvider;
 
-  HttpLog(final SitePaths site, final Provider<CurrentUser> userProvider) {
-    this.userProvider = userProvider;
-
+  HttpLog(final SitePaths site) {
     final DailyRollingFileAppender dst = new DailyRollingFileAppender();
     dst.setName(LOG_NAME);
     dst.setLayout(new MyLayout());
@@ -91,15 +86,11 @@
 
   @Override
   public void log(final Request req, final Response rsp) {
-    GuiceHelper.runInContext(req, rsp, new Runnable() {
-      @Override
-      public void run() {
-        doLog(req, rsp);
-      }
-    });
+    CurrentUser user = (CurrentUser) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
+    doLog(req, rsp, user);
   }
 
-  private void doLog(Request req, Response rsp) {
+  private void doLog(Request req, Response rsp, CurrentUser user) {
     final LoggingEvent event = new LoggingEvent( //
         Logger.class.getName(), // fqnOfCategoryClass
         null, // logger (optional)
@@ -119,7 +110,6 @@
       uri = uri + "?" + qs;
     }
 
-    CurrentUser user = userProvider.get();
     if (user instanceof IdentifiedUser) {
       IdentifiedUser who = (IdentifiedUser) user;
       if (who.getUserName() != null && !who.getUserName().isEmpty()) {
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index a309e4e..fa5ef59 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -19,17 +19,14 @@
 
 import com.google.gerrit.launcher.GerritLauncher;
 import com.google.gerrit.lifecycle.LifecycleListener;
-import com.google.gerrit.reviewdb.AuthType;
-import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
-import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import com.google.inject.servlet.GuiceFilter;
-import com.google.inject.servlet.GuiceHelper;
 import com.google.inject.servlet.GuiceServletContextListener;
 
 import org.eclipse.jetty.io.EndPoint;
@@ -68,10 +65,6 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 @Singleton
 public class JettyServer {
   static class Lifecycle implements LifecycleListener {
@@ -112,7 +105,7 @@
 
   @Inject
   JettyServer(@GerritServerConfig final Config cfg, final SitePaths site,
-      final JettyEnv env, final Provider<CurrentUser> userProvider)
+      final JettyEnv env)
       throws MalformedURLException, IOException {
     this.site = site;
 
@@ -122,24 +115,8 @@
 
     Handler app = makeContext(env, cfg);
     if (cfg.getBoolean("httpd", "requestlog", !reverseProxy)) {
-      RequestLogHandler handler = new RequestLogHandler() {
-        @Override
-        public void handle(String target, Request baseRequest,
-            final HttpServletRequest req, final HttpServletResponse rsp)
-            throws IOException, ServletException {
-          // Force the user to construct, so it's available to our HttpLog
-          // later on when the request gets logged out to the access file.
-          //
-          GuiceHelper.runInContext(req, rsp, new Runnable() {
-            @Override
-            public void run() {
-              userProvider.get();
-            }
-          });
-          super.handle(target, baseRequest, req, rsp);
-        }
-      };
-      handler.setRequestLog(new HttpLog(site, userProvider));
+      RequestLogHandler handler = new RequestLogHandler();
+      handler.setRequestLog(new HttpLog(site));
       handler.setHandler(app);
       app = handler;
     }
@@ -164,7 +141,7 @@
     final int acceptors = cfg.getInt("httpd", "acceptorThreads", 2);
     final AuthType authType = ConfigUtil.getEnum(cfg, "auth", null, "type", AuthType.OPENID);
 
-    reverseProxy = true;
+    reverseProxy = isReverseProxied(listenUrls);
     final Connector[] connectors = new Connector[listenUrls.length];
     for (int idx = 0; idx < listenUrls.length; idx++) {
       final URI u = listenUrls[idx];
@@ -179,7 +156,6 @@
       }
 
       if ("http".equals(u.getScheme())) {
-        reverseProxy = false;
         defaultPort = 80;
         c = new SelectChannelConnector();
       } else if ("https".equals(u.getScheme())) {
@@ -198,7 +174,6 @@
           ssl.setNeedClientAuth(true);
         }
 
-        reverseProxy = false;
         defaultPort = 443;
         c = ssl;
 
@@ -256,7 +231,16 @@
     return connectors;
   }
 
-  private URI[] listenURLs(final Config cfg) {
+  static boolean isReverseProxied(final URI[] listenUrls) {
+    for (URI u : listenUrls) {
+      if ("http".equals(u.getScheme()) || "https".equals(u.getScheme())) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  static URI[] listenURLs(final Config cfg) {
     String[] urls = cfg.getStringList("httpd", null, "listenurl");
     if (urls.length == 0) {
       urls = new String[] {"http://*:8080/"};
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
index a4007d5..f809c73 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
@@ -17,7 +17,7 @@
 import static com.google.gerrit.pgm.init.InitUtil.dnOf;
 
 import com.google.gerrit.pgm.util.ConsoleUI;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gwtjsonrpc.server.SignedToken;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
index 8b4803f..98d2e47 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitHttpd.java
@@ -21,7 +21,7 @@
 import static com.google.gerrit.pgm.init.InitUtil.toURI;
 
 import com.google.gerrit.pgm.util.ConsoleUI;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gwtjsonrpc.server.SignedToken;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/AbstractProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/AbstractProgram.java
index ecd0a16..833b4d8 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/AbstractProgram.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/AbstractProgram.java
@@ -34,9 +34,6 @@
   @Option(name = "--show-stack-trace", usage = "display stack trace on failure")
   protected boolean showStackTrace;
 
-  @Option(name = "--help", usage = "display this help text", aliases = {"-h"})
-  private boolean help;
-
   private String getName() {
     String n = getClass().getName();
     int dot = n.lastIndexOf('.');
@@ -52,21 +49,15 @@
     try {
       clp.parseArgument(argv);
     } catch (CmdLineException err) {
-      if (!help) {
+      if (!clp.wasHelpRequestedByOption()) {
         System.err.println("fatal: " + err.getMessage());
         return 1;
       }
     }
 
-    if (help) {
-      final StringWriter msg = new StringWriter();
-      msg.write(getName());
-      clp.printSingleLineUsage(msg, null);
-      msg.write('\n');
-
-      msg.write('\n');
-      clp.printUsage(msg, null);
-      msg.write('\n');
+    if (clp.wasHelpRequestedByOption()) {
+      StringWriter msg = new StringWriter();
+      clp.printDetailedUsage(getName(), msg);
       System.err.println(msg.toString());
       return 1;
     }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
index 7bc6c0a..4893579 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -24,7 +24,7 @@
 import com.google.gerrit.server.schema.DataSourceProvider;
 import com.google.gerrit.server.schema.DatabaseModule;
 import com.google.gerrit.server.schema.SchemaModule;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.AbstractModule;
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
diff --git a/gerrit-pgm/src/main/java/com/google/inject/servlet/GuiceHelper.java b/gerrit-pgm/src/main/java/com/google/inject/servlet/GuiceHelper.java
deleted file mode 100644
index 5b6cc09..0000000
--- a/gerrit-pgm/src/main/java/com/google/inject/servlet/GuiceHelper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.inject.servlet;
-
-import com.google.inject.servlet.GuiceFilter.Context;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class GuiceHelper {
-  public static void runInContext(HttpServletRequest req,
-      HttpServletResponse rsp, Runnable thunk) {
-    Context previous = GuiceFilter.localContext.get();
-    try {
-      GuiceFilter.localContext.set(new Context(req, rsp));
-      thunk.run();
-    } finally {
-      GuiceFilter.localContext.set(previous);
-    }
-  }
-
-  private GuiceHelper() {
-  }
-}
diff --git a/gerrit-prettify/pom.xml b/gerrit-prettify/pom.xml
index 4f05573..f5bd3d6 100644
--- a/gerrit-prettify/pom.xml
+++ b/gerrit-prettify/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-prettify</artifactId>
diff --git a/gerrit-prettify/src/main/java/com/google/gerrit/prettify/common/PrettyFormatter.java b/gerrit-prettify/src/main/java/com/google/gerrit/prettify/common/PrettyFormatter.java
index 5d1592d..c9a9ab8 100644
--- a/gerrit-prettify/src/main/java/com/google/gerrit/prettify/common/PrettyFormatter.java
+++ b/gerrit-prettify/src/main/java/com/google/gerrit/prettify/common/PrettyFormatter.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.prettify.common;
 
-import com.google.gerrit.reviewdb.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
 import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
 
diff --git a/gerrit-reviewdb/pom.xml b/gerrit-reviewdb/pom.xml
index 5e8a37c..24d6a1b 100644
--- a/gerrit-reviewdb/pom.xml
+++ b/gerrit-reviewdb/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-reviewdb</artifactId>
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/ReviewDB.gwt.xml b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml
similarity index 95%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/ReviewDB.gwt.xml
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml
index c5f8912..4402826 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/ReviewDB.gwt.xml
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDB.gwt.xml
@@ -15,5 +15,4 @@
 -->
 <module>
   <inherits name='com.google.gwtorm.GWTORM'/>
-  <source path='reviewdb' />
 </module>
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AbstractAgreement.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AbstractAgreement.java
similarity index 96%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AbstractAgreement.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AbstractAgreement.java
index 987fc4b..0ed7410 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AbstractAgreement.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AbstractAgreement.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import java.sql.Timestamp;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
index be2cb20..b23aa86 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
@@ -146,7 +146,8 @@
   /**
    * Create a new account.
    *
-   * @param newId unique id, see {@link ReviewDb#nextAccountId()}.
+   * @param newId unique id, see
+   *        {@link com.google.gerrit.reviewdb.server.ReviewDb#nextAccountId()}.
    */
   public Account(final Account.Id newId) {
     accountId = newId;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreement.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountAgreement.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreement.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountAgreement.java
index 57b9340..baa9b5c 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreement.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountAgreement.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreference.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountDiffPreference.java
similarity index 94%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreference.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountDiffPreference.java
index c362f26..3b04725 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreference.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountDiffPreference.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 
@@ -65,6 +65,7 @@
     p.setIntralineDifference(true);
     p.setShowTabs(true);
     p.setContext(DEFAULT_CONTEXT);
+    p.setManualReview(false);
     return p;
   }
 
@@ -108,6 +109,9 @@
   @Column(id = 13)
   protected boolean retainHeader;
 
+  @Column(id = 14)
+  protected boolean manualReview;
+
   protected AccountDiffPreference() {
   }
 
@@ -129,6 +133,7 @@
     this.expandAllComments = p.expandAllComments;
     this.context = p.context;
     this.retainHeader = p.retainHeader;
+    this.manualReview = p.manualReview;
   }
 
   public Account.Id getAccountId() {
@@ -233,4 +238,12 @@
   public void setRetainHeader(boolean retain) {
     retainHeader = retain;
   }
+
+  public boolean isManualReview() {
+    return manualReview;
+  }
+
+  public void setManualReview(boolean manual) {
+    manualReview = manual;
+  }
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalId.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountExternalId.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalId.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountExternalId.java
index 853ebd5..0705284 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalId.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountExternalId.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGeneralPreferences.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
similarity index 99%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGeneralPreferences.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
index ebaf0c8..b9ff4fb 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGeneralPreferences.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroup.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroup.java
similarity index 94%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroup.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroup.java
index 5d8a4b9..8e2541a 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroup.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroup.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
@@ -216,11 +216,6 @@
   @Column(id = 7)
   protected boolean visibleToAll;
 
-  /** Comment and action email notifications by users in this group are only
-   *  sent to change authors. */
-  @Column(id = 8)
-  protected boolean emailOnlyAuthors;
-
   /** Globally unique identifier name for this group. */
   @Column(id = 9)
   protected UUID groupUUID;
@@ -294,14 +289,6 @@
     return visibleToAll;
   }
 
-  public boolean isEmailOnlyAuthors() {
-    return emailOnlyAuthors;
-  }
-
-  public void setEmailOnlyAuthors(boolean emailOnlyAuthors) {
-    this.emailOnlyAuthors = emailOnlyAuthors;
-  }
-
   public AccountGroup.UUID getGroupUUID() {
     return groupUUID;
   }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreement.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupAgreement.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreement.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupAgreement.java
index fd5d58b..c712b3d 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreement.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupAgreement.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupInclude.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupInclude.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupInclude.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupInclude.java
index 86b0966..4b58689 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupInclude.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupInclude.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAudit.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupIncludeAudit.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAudit.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupIncludeAudit.java
index 326dfd3..275c3c3 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAudit.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupIncludeAudit.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMember.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMember.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMember.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMember.java
index 1ca9123..4869cf8 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMember.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMember.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAudit.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMemberAudit.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAudit.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMemberAudit.java
index 7547efb..8ba8912 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAudit.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupMemberAudit.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupName.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupName.java
similarity index 96%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupName.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupName.java
index 3b31dc6..701f2c3 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupName.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGroupName.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReview.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountPatchReview.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReview.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountPatchReview.java
index 4d16bb6..a1c3c3c 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReview.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountPatchReview.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatch.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountProjectWatch.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatch.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountProjectWatch.java
index 6c62e12..93e6fb3 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatch.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountProjectWatch.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKey.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountSshKey.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKey.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountSshKey.java
index 7a79980..8c4ac82 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKey.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountSshKey.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategory.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategory.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategory.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategory.java
index d7e5024..bb25265 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategory.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategory.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.Key;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValue.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategoryValue.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValue.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategoryValue.java
index 84f0a17..b7761c5 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValue.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ApprovalCategoryValue.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.ShortKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AuthType.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AuthType.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
index 843f41b..962426b 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AuthType.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 public enum AuthType {
   /** Login relies upon the OpenID standard: {@link "http://openid.net/"} */
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Branch.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Branch.java
index 27716a8..e1a15e5 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Branch.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Branch.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
index fc544fa..61e6a97 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Change.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
@@ -182,16 +182,16 @@
   /** Minimum database status constant for an open change. */
   private static final char MIN_OPEN = 'a';
   /** Database constant for {@link Status#NEW}. */
-  protected static final char STATUS_NEW = 'n';
+  public static final char STATUS_NEW = 'n';
   /** Database constant for {@link Status#SUBMITTED}. */
-  protected static final char STATUS_SUBMITTED = 's';
+  public static final char STATUS_SUBMITTED = 's';
   /** Database constant for {@link Status#DRAFT}. */
-  protected static final char STATUS_DRAFT = 'd';
+  public static final char STATUS_DRAFT = 'd';
   /** Maximum database status constant for an open change. */
   private static final char MAX_OPEN = 'z';
 
   /** Database constant for {@link Status#MERGED}. */
-  protected static final char STATUS_MERGED = 'M';
+  public static final char STATUS_MERGED = 'M';
 
   /**
    * Current state within the basic workflow of the change.
@@ -432,6 +432,10 @@
     lastUpdatedOn = new Timestamp(System.currentTimeMillis());
   }
 
+  public int getNumberOfPatchSets() {
+    return nbrPatchSets;
+  }
+
   public String getSortKey() {
     return sortKey;
   }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessage.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ChangeMessage.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessage.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ChangeMessage.java
index d8f1dd4..e05f5e7 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessage.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ChangeMessage.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CodedEnum.java
similarity index 94%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CodedEnum.java
index 5900292..11e7efa 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CodedEnum.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 /** Extension of Enum which provides distinct character code values. */
 public interface CodedEnum {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContactInformation.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContactInformation.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContactInformation.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContactInformation.java
index d28467c..195387c 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContactInformation.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContactInformation.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreement.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContributorAgreement.java
similarity index 95%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreement.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContributorAgreement.java
index 9e285b8..12e7459 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreement.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/ContributorAgreement.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
@@ -80,7 +80,8 @@
   /**
    * Create a new agreement.
    *
-   * @param newId unique id, see {@link ReviewDb#nextAccountId()}.
+   * @param newId unique id, see
+   *        {@link com.google.gerrit.reviewdb.server.ReviewDb#nextAccountId()}.
    * @param name a short title/name for the agreement.
    */
   public ContributorAgreement(final ContributorAgreement.Id newId,
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CurrentSchemaVersion.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CurrentSchemaVersion.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CurrentSchemaVersion.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CurrentSchemaVersion.java
index 8878225..183bb1e 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CurrentSchemaVersion.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/CurrentSchemaVersion.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Patch.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Patch.java
similarity index 99%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Patch.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Patch.java
index 0153755..0d0ea88 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Patch.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Patch.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineComment.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchLineComment.java
similarity index 96%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineComment.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchLineComment.java
index 0828c95..c8a970d 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineComment.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchLineComment.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
@@ -55,8 +55,8 @@
     }
   }
 
-  protected static final char STATUS_DRAFT = 'd';
-  protected static final char STATUS_PUBLISHED = 'P';
+  public static final char STATUS_DRAFT = 'd';
+  public static final char STATUS_PUBLISHED = 'P';
 
   public static enum Status {
     DRAFT(STATUS_DRAFT),
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSet.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSet.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSet.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSet.java
index 1e7643f..83ce828 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSet.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSet.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestor.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetAncestor.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestor.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetAncestor.java
index 8310e4d..8412788 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestor.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetAncestor.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.IntKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApproval.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetApproval.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApproval.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetApproval.java
index a3698f4..04b2b6f 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApproval.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetApproval.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetInfo.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetInfo.java
index f96a5b3..1a00fae 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/PatchSetInfo.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import java.util.List;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
similarity index 83%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
index 33c6d31..a2fc46f 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
@@ -184,10 +184,36 @@
     state = update.state;
   }
 
+  /**
+   * Returns the name key of the parent project.
+   *
+   * @return name key of the parent project, <code>null</code> if this project
+   *         is the wild project, <code>null</code> or the name key of the wild
+   *         project if this project is a direct child of the wild project
+   */
   public Project.NameKey getParent() {
     return parent;
   }
 
+  /**
+   * Returns the name key of the parent project.
+   *
+   * @param allProjectsName name key of the wild project
+   * @return name key of the parent project, <code>null</code> if this project
+   *         is the wild project
+   */
+  public Project.NameKey getParent(final Project.NameKey allProjectsName) {
+    if (parent != null) {
+      return parent;
+    }
+
+    if (name.equals(allProjectsName)) {
+      return null;
+    }
+
+    return allProjectsName;
+  }
+
   public String getParentName() {
     return parent != null ? parent.get() : null;
   }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/RevId.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RevId.java
similarity index 96%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/RevId.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RevId.java
index 7077312..d90a81c 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/RevId.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/RevId.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChange.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/StarredChange.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChange.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/StarredChange.java
index 426bd11..d427b09 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChange.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/StarredChange.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscription.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SubmoduleSubscription.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscription.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SubmoduleSubscription.java
index 026348a..32a9131 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscription.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SubmoduleSubscription.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfig.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SystemConfig.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfig.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SystemConfig.java
index e366a47..0f8d005 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfig.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/SystemConfig.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.StringKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingId.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/TrackingId.java
similarity index 98%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingId.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/TrackingId.java
index 1548807..e73dd73 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingId.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/TrackingId.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import com.google.gwtorm.client.Column;
 import com.google.gwtorm.client.CompoundKey;
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/UserIdentity.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/UserIdentity.java
similarity index 97%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/UserIdentity.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/UserIdentity.java
index 6eabbda..c7b4cfe 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/UserIdentity.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/UserIdentity.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.client;
 
 import java.sql.Timestamp;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAccess.java
similarity index 82%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAccess.java
index d7a784a..2b23b7a 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAccess.java
@@ -12,13 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 /** Access interface for {@link Account}. */
 public interface AccountAccess extends Access<Account, Account.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAgreementAccess.java
similarity index 66%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAgreementAccess.java
index f65af5e..86ea372 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAgreementAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountAgreementAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.reviewdb.client.AccountAgreement.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountAgreementAccess extends
     Access<AccountAgreement, AccountAgreement.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreferenceAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountDiffPreferenceAccess.java
similarity index 70%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreferenceAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountDiffPreferenceAccess.java
index d1d134b..8574758 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountDiffPreferenceAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountDiffPreferenceAccess.java
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
 
 public interface AccountDiffPreferenceAccess extends Access<AccountDiffPreference, Account.Id> {
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalIdAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountExternalIdAccess.java
similarity index 77%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalIdAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountExternalIdAccess.java
index 4c78139..b263552 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountExternalIdAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountExternalIdAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.reviewdb.client.AccountExternalId.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountExternalIdAccess extends
     Access<AccountExternalId, AccountExternalId.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAccess.java
similarity index 77%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAccess.java
index 7eb7ed2..9e88244 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAccess.java
@@ -12,13 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupAccess extends
     Access<AccountGroup, AccountGroup.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAgreementAccess.java
similarity index 66%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAgreementAccess.java
index d4a1fcd..ecab70d 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupAgreementAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupAgreementAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupAgreementAccess extends
     Access<AccountGroupAgreement, AccountGroupAgreement.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAccess.java
similarity index 68%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAccess.java
index 4881635..c8c7b40 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupIncludeAccess extends
     Access<AccountGroupInclude, AccountGroupInclude.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAuditAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAuditAccess.java
similarity index 67%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAuditAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAuditAccess.java
index 55b50e8..3cf24f3 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupIncludeAuditAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupIncludeAuditAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupIncludeAudit;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroupIncludeAudit.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupIncludeAuditAccess extends
     Access<AccountGroupIncludeAudit, AccountGroupIncludeAudit.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAccess.java
similarity index 65%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAccess.java
index 48a20e3..53ecaae 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAccess.java
@@ -12,13 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroupMember.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupMemberAccess extends
     Access<AccountGroupMember, AccountGroupMember.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAuditAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAuditAccess.java
similarity index 65%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAuditAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAuditAccess.java
index b112059..f26996d 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupMemberAuditAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupMemberAuditAccess.java
@@ -12,13 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.client.AccountGroup.Id;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountGroupMemberAuditAccess extends
     Access<AccountGroupMemberAudit, AccountGroupMemberAudit.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupNameAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupNameAccess.java
similarity index 71%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupNameAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupNameAccess.java
index 12db5ce..d0bc419 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountGroupNameAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountGroupNameAccess.java
@@ -12,13 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.client.AccountGroup.NameKey;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 
 public interface AccountGroupNameAccess extends
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReviewAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountPatchReviewAccess.java
similarity index 67%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReviewAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountPatchReviewAccess.java
index e1fa4d4..ef8133b 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountPatchReviewAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountPatchReviewAccess.java
@@ -12,13 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountPatchReview;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.reviewdb.client.AccountPatchReview.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountPatchReviewAccess
     extends Access<AccountPatchReview, AccountPatchReview.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatchAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountProjectWatchAccess.java
similarity index 64%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatchAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountProjectWatchAccess.java
index 254aac9..046d5a5 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountProjectWatchAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountProjectWatchAccess.java
@@ -12,13 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch.Key;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountProjectWatchAccess extends
     Access<AccountProjectWatch, AccountProjectWatch.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKeyAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountSshKeyAccess.java
similarity index 68%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKeyAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountSshKeyAccess.java
index 5c511b1..d756a44 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountSshKeyAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/AccountSshKeyAccess.java
@@ -12,13 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface AccountSshKeyAccess extends
     Access<AccountSshKey, AccountSshKey.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryAccess.java
similarity index 70%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryAccess.java
index d3601f2..31e6c62 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryAccess.java
@@ -12,13 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategory.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface ApprovalCategoryAccess extends
     Access<ApprovalCategory, ApprovalCategory.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValueAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryValueAccess.java
similarity index 69%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValueAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryValueAccess.java
index e86d652..acdda5e8 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ApprovalCategoryValueAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ApprovalCategoryValueAccess.java
@@ -12,13 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.ApprovalCategory.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface ApprovalCategoryValueAccess extends
     Access<ApprovalCategoryValue, ApprovalCategoryValue.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeAccess.java
similarity index 78%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeAccess.java
index 9c4605e..4660291 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeAccess.java
@@ -12,13 +12,20 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.Change.Key;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface ChangeAccess extends Access<Change, Change.Id> {
   @PrimaryKey("changeId")
@@ -94,6 +101,16 @@
   ResultSet<Change> allClosedNext(char status, String sortKey, int limit)
       throws OrmException;
 
+  @Query("WHERE open = false AND status = ? AND dest = ? AND sortKey > ?"
+      + " ORDER BY sortKey LIMIT ?")
+  ResultSet<Change> byBranchClosedPrev(char status, Branch.NameKey p,
+      String sortKey, int limit) throws OrmException;
+
+  @Query("WHERE open = false AND status = ? AND dest = ? AND sortKey < ?"
+      + " ORDER BY sortKey DESC LIMIT ?")
+  ResultSet<Change> byBranchClosedNext(char status, Branch.NameKey p,
+      String sortKey, int limit) throws OrmException;
+
   @Query
   ResultSet<Change> all() throws OrmException;
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessageAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeMessageAccess.java
similarity index 67%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessageAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeMessageAccess.java
index 725c49f..6db2675 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ChangeMessageAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ChangeMessageAccess.java
@@ -12,13 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.ChangeMessage.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface ChangeMessageAccess extends
     Access<ChangeMessage, ChangeMessage.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreementAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ContributorAgreementAccess.java
similarity index 72%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreementAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ContributorAgreementAccess.java
index ae7b41d..3c7f47a 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ContributorAgreementAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ContributorAgreementAccess.java
@@ -12,13 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.ContributorAgreement.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 /** Access interface for {@link ContributorAgreement}. */
 public interface ContributorAgreementAccess extends
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineCommentAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchLineCommentAccess.java
similarity index 80%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineCommentAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchLineCommentAccess.java
index 29588e1..3be8563 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchLineCommentAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchLineCommentAccess.java
@@ -12,13 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.PatchLineComment.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface PatchLineCommentAccess extends
     Access<PatchLineComment, PatchLineComment.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAccess.java
similarity index 71%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAccess.java
index c9d4b4f..c04fa06 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface PatchSetAccess extends Access<PatchSet, PatchSet.Id> {
   @PrimaryKey("id")
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestorAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAncestorAccess.java
similarity index 71%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestorAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAncestorAccess.java
index 838af5d..e163bc4 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetAncestorAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetAncestorAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor.Id;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface PatchSetAncestorAccess extends
     Access<PatchSetAncestor, PatchSetAncestor.Id> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApprovalAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetApprovalAccess.java
similarity index 74%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApprovalAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetApprovalAccess.java
index 417d264..b30c5bfa 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetApprovalAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/PatchSetApprovalAccess.java
@@ -12,13 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.PatchSetApproval.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface PatchSetApprovalAccess extends
     Access<PatchSetApproval, PatchSetApproval.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDb.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ReviewDb.java
similarity index 88%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDb.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ReviewDb.java
index cd4414e..616a656 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/ReviewDb.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/ReviewDb.java
@@ -12,12 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.Relation;
-import com.google.gwtorm.client.Schema;
-import com.google.gwtorm.client.Sequence;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.Relation;
+import com.google.gwtorm.server.Schema;
+import com.google.gwtorm.server.Sequence;
 
 /**
  * The review service database schema.
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SchemaVersionAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SchemaVersionAccess.java
similarity index 74%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SchemaVersionAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SchemaVersionAccess.java
index eec1643..07f255c 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SchemaVersionAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SchemaVersionAccess.java
@@ -12,11 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
 
 /** Access interface for {@link CurrentSchemaVersion}. */
 public interface SchemaVersionAccess extends
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChangeAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/StarredChangeAccess.java
similarity index 65%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChangeAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/StarredChangeAccess.java
index 9e31dbf..88e703a 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/StarredChangeAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/StarredChangeAccess.java
@@ -12,13 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.StarredChange;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.StarredChange.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface StarredChangeAccess extends
     Access<StarredChange, StarredChange.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscriptionAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SubmoduleSubscriptionAccess.java
similarity index 69%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscriptionAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SubmoduleSubscriptionAccess.java
index 909bd57..e1aa907 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SubmoduleSubscriptionAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SubmoduleSubscriptionAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.client.Branch.NameKey;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface SubmoduleSubscriptionAccess extends
     Access<SubmoduleSubscription, SubmoduleSubscription.Key> {
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfigAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SystemConfigAccess.java
similarity index 71%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfigAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SystemConfigAccess.java
index dfca1ca..3bb07cb 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/SystemConfigAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/SystemConfigAccess.java
@@ -12,13 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.client.SystemConfig.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 /** Access interface for {@link SystemConfig}. */
 public interface SystemConfigAccess extends
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingIdAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/TrackingIdAccess.java
similarity index 68%
rename from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingIdAccess.java
rename to gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/TrackingIdAccess.java
index ad851a4..51babb3 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/TrackingIdAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/server/TrackingIdAccess.java
@@ -12,13 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.reviewdb.server;
 
-import com.google.gwtorm.client.Access;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.PrimaryKey;
-import com.google.gwtorm.client.Query;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.TrackingId;
+import com.google.gerrit.reviewdb.client.Change.Id;
+import com.google.gerrit.reviewdb.client.TrackingId.Key;
+import com.google.gwtorm.server.Access;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.PrimaryKey;
+import com.google.gwtorm.server.Query;
+import com.google.gwtorm.server.ResultSet;
 
 public interface TrackingIdAccess extends Access<TrackingId, TrackingId.Key> {
   @PrimaryKey("key")
diff --git a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_generic.sql b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_generic.sql
similarity index 96%
rename from gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_generic.sql
rename to gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_generic.sql
index 83f7d15..5d0e15c 100644
--- a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_generic.sql
+++ b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_generic.sql
@@ -109,6 +109,10 @@
 CREATE INDEX changes_allClosed
 ON changes (open, status, sort_key);
 
+--    covers:             byBranchClosedPrev, byBranchClosedNext
+CREATE INDEX changes_byBranchClosed
+ON changes (status, dest_project_name, dest_branch_name, sort_key);
+
 CREATE INDEX changes_key
 ON changes (change_key);
 
diff --git a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_postgres.sql
similarity index 97%
rename from gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql
rename to gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_postgres.sql
index 3afa7ef..97ad126 100644
--- a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql
+++ b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/index_postgres.sql
@@ -187,6 +187,11 @@
 CREATE INDEX changes_byProject
 ON changes (dest_project_name);
 
+--    covers:             byBranchClosedPrev, byBranchClosedNext
+CREATE INDEX changes_byBranchClosed
+ON changes (status, dest_project_name, dest_branch_name, sort_key)
+WHERE open = 'N';
+
 CREATE INDEX changes_key
 ON changes (change_key);
 
diff --git a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/mysql_nextval.sql b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/mysql_nextval.sql
similarity index 100%
rename from gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/mysql_nextval.sql
rename to gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/server/mysql_nextval.sql
diff --git a/gerrit-server/pom.xml b/gerrit-server/pom.xml
index 20a7286..58e43cf 100644
--- a/gerrit-server/pom.xml
+++ b/gerrit-server/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-server</artifactId>
@@ -90,17 +90,17 @@
     </dependency>
 
     <dependency>
-      <groupId>com.google.code.guice</groupId>
+      <groupId>com.google.inject</groupId>
       <artifactId>guice</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>com.google.code.guice</groupId>
+      <groupId>com.google.inject.extensions</groupId>
       <artifactId>guice-servlet</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>com.google.code.guice</groupId>
+      <groupId>com.google.inject.extensions</groupId>
       <artifactId>guice-assistedinject</artifactId>
     </dependency>
 
@@ -123,6 +123,12 @@
 
     <dependency>
       <groupId>com.google.gerrit</groupId>
+      <artifactId>gerrit-util-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.gerrit</groupId>
       <artifactId>gerrit-util-ssl</artifactId>
       <version>${project.version}</version>
     </dependency>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
index 6ecf19b..31837b0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHookRunner.java
@@ -16,15 +16,15 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
@@ -45,7 +45,7 @@
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.ProjectState;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -242,7 +242,7 @@
         addArg(args, "--commit", event.patchSet.revision);
         addArg(args, "--patchset", event.patchSet.number);
 
-        runHook(openRepository(change), patchsetCreatedHook, args);
+        runHook(change.getProject(), patchsetCreatedHook, args);
     }
 
     public void doCommentAddedHook(final Change change, final Account account,
@@ -277,7 +277,7 @@
             addArg(args, "--" + approval.getKey().get(), Short.toString(approval.getValue().get()));
         }
 
-        runHook(openRepository(change), commentAddedHook, args);
+        runHook(change.getProject(), commentAddedHook, args);
     }
 
     public void doChangeMergedHook(final Change change, final Account account,
@@ -297,7 +297,7 @@
         addArg(args, "--submitter", getDisplayName(account));
         addArg(args, "--commit", event.patchSet.revision);
 
-        runHook(openRepository(change), changeMergedHook, args);
+        runHook(change.getProject(), changeMergedHook, args);
     }
 
     public void doChangeAbandonedHook(final Change change, final Account account,
@@ -317,7 +317,7 @@
         addArg(args, "--abandoner", getDisplayName(account));
         addArg(args, "--reason", reason == null ? "" : reason);
 
-        runHook(openRepository(change), changeAbandonedHook, args);
+        runHook(change.getProject(), changeAbandonedHook, args);
     }
 
     public void doChangeRestoreHook(final Change change, final Account account,
@@ -337,7 +337,7 @@
         addArg(args, "--restorer", getDisplayName(account));
         addArg(args, "--reason", reason == null ? "" : reason);
 
-        runHook(openRepository(change), changeRestoredHook, args);
+        runHook(change.getProject(), changeRestoredHook, args);
     }
 
     public void doRefUpdatedHook(final Branch.NameKey refName, final RefUpdate refUpdate, final Account account) {
@@ -362,7 +362,7 @@
         addArg(args, "--submitter", getDisplayName(account));
       }
 
-      runHook(openRepository(refName.getParentKey()), refUpdatedHook, args);
+      runHook(refName.getParentKey(), refUpdatedHook, args);
     }
 
     public void doClaSignupHook(Account account, ContributorAgreement cla) {
@@ -448,18 +448,14 @@
   /**
    * Run a hook.
    *
-   * @param repo repository to run the hook for.
+   * @param project used to open repository to run the hook for.
    * @param hook the hook to execute.
    * @param args Arguments to use to run the hook.
    */
-  private synchronized void runHook(Repository repo, File hook,
+  private synchronized void runHook(Project.NameKey project, File hook,
       List<String> args) {
-    if (repo != null) {
-      if (hook.exists()) {
-        hookQueue.execute(new HookTask(repo, hook, args));
-      } else {
-        repo.close();
-      }
+    if (project != null && hook.exists()) {
+      hookQueue.execute(new HookTask(project, hook, args));
     }
   }
 
@@ -470,18 +466,19 @@
   }
 
   private final class HookTask implements Runnable {
-    private final Repository repo;
+    private final Project.NameKey project;
     private final File hook;
     private final List<String> args;
 
-    private HookTask(Repository repo, File hook, List<String> args) {
-      this.repo = repo;
+    private HookTask(Project.NameKey project, File hook, List<String> args) {
+      this.project = project;
       this.hook = hook;
       this.args = args;
     }
 
     @Override
     public void run() {
+      Repository repo = null;
       try {
         final List<String> argv = new ArrayList<String>(1 + args.size());
         argv.add(hook.getAbsolutePath());
@@ -489,6 +486,11 @@
 
         final ProcessBuilder pb = new ProcessBuilder(argv);
         pb.redirectErrorStream(true);
+
+        if (project != null) {
+          repo = openRepository(project);
+        }
+
         if (repo != null) {
           pb.directory(repo.getDirectory());
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHooks.java b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHooks.java
index 3447c1f..c424a26 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHooks.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/common/ChangeHooks.java
@@ -14,16 +14,16 @@
 
 package com.google.gerrit.common;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.RefUpdate;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/common/DisabledChangeHooks.java b/gerrit-server/src/main/java/com/google/gerrit/common/DisabledChangeHooks.java
index 7f61f62..5544216 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/common/DisabledChangeHooks.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/common/DisabledChangeHooks.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.common;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.Branch.NameKey;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Branch.NameKey;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java
index 8d9633f..fd72e0c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/rules/RulesCache.java
@@ -16,7 +16,7 @@
 
 import static com.googlecode.prolog_cafe.lang.PrologMachineCopy.save;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.git.GitRepositoryManager;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/rules/StoredValues.java b/gerrit-server/src/main/java/com/google/gerrit/rules/StoredValues.java
index de85742..8ab9471 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/rules/StoredValues.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/rules/StoredValues.java
@@ -16,12 +16,12 @@
 
 import static com.google.gerrit.rules.StoredValue.create;
 
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
index c1263ef..5d36b33 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/AnonymousUser.java
@@ -14,10 +14,12 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.ListGroupMembership;
 import com.google.inject.Inject;
 
 import java.util.Collection;
@@ -32,8 +34,8 @@
   }
 
   @Override
-  public Set<AccountGroup.UUID> getEffectiveGroups() {
-    return Collections.singleton(AccountGroup.ANONYMOUS_USERS);
+  public GroupMembership getEffectiveGroups() {
+    return new ListGroupMembership(Collections.singleton(AccountGroup.ANONYMOUS_USERS));
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
index 6997d47..3417111 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -14,11 +14,17 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.common.data.ApprovalType;
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
 
+import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
 
 public class ApprovalsUtil {
@@ -33,4 +39,36 @@
     }
     db.patchSetApprovals().update(approvals);
   }
+
+  /**
+   * Moves the PatchSetApprovals to the last PatchSet on the change while
+   * keeping the vetos.
+   *
+   * @param db The review database
+   * @param change Change to update
+   * @param approvalTypes The approval types
+   * @throws OrmException
+   * @throws IOException
+   */
+  public static void copyVetosToLatestPatchSet(final ReviewDb db, Change change,
+      ApprovalTypes approvalTypes) throws OrmException, IOException {
+    PatchSet.Id source;
+    if (change.getNumberOfPatchSets() > 1) {
+      source = new PatchSet.Id(change.getId(), change.getNumberOfPatchSets() - 1);
+    } else {
+      throw new IOException("Previous patch set could not be found");
+    }
+
+    PatchSet.Id dest = change.currPatchSetId();
+    for (PatchSetApproval a : db.patchSetApprovals().byPatchSet(source)) {
+      // ApprovalCategory.SUBMIT is still in db but not relevant in git-store
+      if (!ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
+        final ApprovalType type = approvalTypes.byId(a.getCategoryId());
+        if (type.getCategory().isCopyMinScore() && type.isMaxNegative(a)) {
+          db.patchSetApprovals().insert(
+              Collections.singleton(new PatchSetApproval(dest, a)));
+        }
+      }
+    }
+  }
 }
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 55de507..9dc572d 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
@@ -14,29 +14,38 @@
 
 package com.google.gerrit.server;
 
+import com.google.gerrit.common.ChangeHookRunner;
 import com.google.gerrit.common.ChangeHooks;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.TrackingId;
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Change.Status;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.client.TrackingId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.TrackingFooter;
 import com.google.gerrit.server.config.TrackingFooters;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MergeOp;
 import com.google.gerrit.server.git.ReplicationQueue;
 import com.google.gerrit.server.mail.EmailException;
+import com.google.gerrit.server.mail.RebasedPatchSetSender;
+import com.google.gerrit.server.mail.ReplacePatchSetSender;
 import com.google.gerrit.server.mail.ReplyToChangeSender;
 import com.google.gerrit.server.mail.RevertedSender;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.OrmConcurrencyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmConcurrencyException;
+import com.google.gwtorm.server.OrmException;
 
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -45,9 +54,11 @@
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.merge.MergeStrategy;
+import org.eclipse.jgit.merge.ThreeWayMerger;
 import org.eclipse.jgit.revwalk.FooterLine;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
@@ -55,6 +66,8 @@
 import org.eclipse.jgit.util.NB;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -161,6 +174,252 @@
     opFactory.create(change.getDest()).verifyMergeability(change);
   }
 
+  public static void insertAncestors(ReviewDb db, PatchSet.Id id, RevCommit src)
+      throws OrmException {
+    final int cnt = src.getParentCount();
+    List<PatchSetAncestor> toInsert = new ArrayList<PatchSetAncestor>(cnt);
+    for (int p = 0; p < cnt; p++) {
+      PatchSetAncestor a =
+          new PatchSetAncestor(new PatchSetAncestor.Id(id, p + 1));
+      a.setAncestorRevision(new RevId(src.getParent(p).getId().getName()));
+      toInsert.add(a);
+    }
+    db.patchSetAncestors().insert(toInsert);
+  }
+
+  /**
+   * Rebases a commit
+   *
+   * @param git Repository to find commits in
+   * @param original The commit to rebase
+   * @param base Base to rebase against
+   * @return CommitBuilder the newly rebased commit
+   * @throws IOException Merged failed
+   */
+  public static CommitBuilder rebaseCommit(Repository git, RevCommit original,
+      RevCommit base, PersonIdent committerIdent) throws IOException {
+
+    if (original.getParentCount() == 0) {
+      throw new IOException(
+          "Commits with no parents cannot be rebased (is this the initial commit?).");
+    }
+
+    if (original.getParentCount() > 1) {
+      throw new IOException(
+          "Patch sets with multiple parents cannot be rebased (merge commits)."
+              + " Parents: " + Arrays.toString(original.getParents()));
+    }
+
+    final RevCommit parentCommit = original.getParent(0);
+
+    if (base.equals(parentCommit)) {
+      throw new IOException("Change is already up to date.");
+    }
+
+    final ThreeWayMerger merger = MergeStrategy.RESOLVE.newMerger(git, true);
+    merger.setBase(parentCommit);
+    merger.merge(original, base);
+
+    if (merger.getResultTreeId() == null) {
+      throw new IOException(
+          "The rebase failed since conflicts occured during the merge.");
+    }
+
+    final CommitBuilder rebasedCommitBuilder = new CommitBuilder();
+
+    rebasedCommitBuilder.setTreeId(merger.getResultTreeId());
+    rebasedCommitBuilder.setParentId(base);
+    rebasedCommitBuilder.setAuthor(original.getAuthorIdent());
+    rebasedCommitBuilder.setMessage(original.getFullMessage());
+    rebasedCommitBuilder.setCommitter(committerIdent);
+
+    return rebasedCommitBuilder;
+  }
+
+  public static void rebaseChange(final PatchSet.Id patchSetId,
+      final IdentifiedUser user, final ReviewDb db,
+      RebasedPatchSetSender.Factory rebasedPatchSetSenderFactory,
+      final ChangeHookRunner hooks, GitRepositoryManager gitManager,
+      final PatchSetInfoFactory patchSetInfoFactory,
+      final ReplicationQueue replication, PersonIdent myIdent,
+      final ChangeControl.Factory changeControlFactory,
+      final ApprovalTypes approvalTypes) throws NoSuchChangeException,
+      EmailException, OrmException, MissingObjectException,
+      IncorrectObjectTypeException, IOException,
+      PatchSetInfoNotAvailableException, InvalidChangeOperationException {
+
+    final Change.Id changeId = patchSetId.getParentKey();
+    final ChangeControl changeControl =
+        changeControlFactory.validateFor(changeId);
+
+    if (!changeControl.canRebase()) {
+      throw new InvalidChangeOperationException(
+          "Cannot rebase: New patch sets are not allowed to be added to change: "
+              + changeId.toString());
+    }
+
+    Change change = changeControl.getChange();
+    final Repository git = gitManager.openRepository(change.getProject());
+    try {
+      final RevWalk revWalk = new RevWalk(git);
+      try {
+        final PatchSet originalPatchSet = db.patchSets().get(patchSetId);
+        RevCommit branchTipCommit = null;
+
+        List<PatchSetAncestor> patchSetAncestors =
+            db.patchSetAncestors().ancestorsOf(patchSetId).toList();
+        if (patchSetAncestors.size() > 1) {
+          throw new IOException(
+              "The patch set you are trying to rebase is dependent on several other patch sets: "
+                  + patchSetAncestors.toString());
+        }
+        if (patchSetAncestors.size() == 1) {
+          List<PatchSet> depPatchSetList = db.patchSets()
+                  .byRevision(patchSetAncestors.get(0).getAncestorRevision())
+                  .toList();
+          if (!depPatchSetList.isEmpty()) {
+            PatchSet depPatchSet = depPatchSetList.get(0);
+
+            Change.Id depChangeId = depPatchSet.getId().getParentKey();
+            Change depChange = db.changes().get(depChangeId);
+
+            if (depChange.getStatus() == Status.ABANDONED) {
+              throw new IOException("Cannot rebase against an abandoned change: "
+                  + depChange.getKey().toString());
+            }
+            if (depChange.getStatus().isOpen()) {
+              PatchSet latestDepPatchSet =
+                  db.patchSets().get(depChange.currentPatchSetId());
+              if (!depPatchSet.getId().equals(depChange.currentPatchSetId())) {
+                branchTipCommit =
+                    revWalk.parseCommit(ObjectId
+                        .fromString(latestDepPatchSet.getRevision().get()));
+              } else {
+                throw new IOException(
+                    "Change is already based on the latest patch set of the dependent change.");
+              }
+            }
+          }
+        }
+
+        if (branchTipCommit == null) {
+          // We are dependent on a merged PatchSet or have no PatchSet
+          // dependencies at all.
+          Ref destRef = git.getRef(change.getDest().get());
+          if (destRef == null) {
+            throw new IOException(
+                "The destination branch does not exist: "
+                    + change.getDest().get());
+          }
+          branchTipCommit = revWalk.parseCommit(destRef.getObjectId());
+        }
+
+        final RevCommit originalCommit =
+            revWalk.parseCommit(ObjectId.fromString(originalPatchSet
+                .getRevision().get()));
+
+        CommitBuilder rebasedCommitBuilder =
+            rebaseCommit(git, originalCommit, branchTipCommit, myIdent);
+
+        final ObjectInserter oi = git.newObjectInserter();
+        final ObjectId rebasedCommitId;
+        try {
+          rebasedCommitId = oi.insert(rebasedCommitBuilder);
+          oi.flush();
+        } finally {
+          oi.release();
+        }
+
+        Change updatedChange =
+            db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() {
+              @Override
+              public Change update(Change change) {
+                if (change.getStatus().isOpen()) {
+                  change.nextPatchSetId();
+                  return change;
+                } else {
+                  return null;
+                }
+              }
+            });
+
+        if (updatedChange == null) {
+          throw new InvalidChangeOperationException("Change is closed: "
+              + change.toString());
+        } else {
+          change = updatedChange;
+        }
+
+        final PatchSet rebasedPatchSet = new PatchSet(change.currPatchSetId());
+        rebasedPatchSet.setCreatedOn(change.getCreatedOn());
+        rebasedPatchSet.setUploader(user.getAccountId());
+        rebasedPatchSet.setRevision(new RevId(rebasedCommitId.getName()));
+
+        insertAncestors(db, rebasedPatchSet.getId(),
+            revWalk.parseCommit(rebasedCommitId));
+
+        db.patchSets().insert(Collections.singleton(rebasedPatchSet));
+        final PatchSetInfo info =
+            patchSetInfoFactory.get(db, rebasedPatchSet.getId());
+
+        change =
+            db.changes().atomicUpdate(change.getId(),
+                new AtomicUpdate<Change>() {
+                  @Override
+                  public Change update(Change change) {
+                    change.setCurrentPatchSet(info);
+                    ChangeUtil.updated(change);
+                    return change;
+                  }
+                });
+
+        final RefUpdate ru = git.updateRef(rebasedPatchSet.getRefName());
+        ru.setNewObjectId(rebasedCommitId);
+        ru.disableRefLog();
+        if (ru.update(revWalk) != RefUpdate.Result.NEW) {
+          throw new IOException("Failed to create ref "
+              + rebasedPatchSet.getRefName() + " in " + git.getDirectory()
+              + ": " + ru.getResult());
+        }
+
+        replication.scheduleUpdate(change.getProject(), ru.getName());
+
+        ApprovalsUtil.copyVetosToLatestPatchSet(db, change, approvalTypes);
+
+        final ChangeMessage cmsg =
+            new ChangeMessage(new ChangeMessage.Key(changeId,
+                ChangeUtil.messageUUID(db)), user.getAccountId(), patchSetId);
+        cmsg.setMessage("Patch Set " + patchSetId.get() + ": Rebased");
+        db.changeMessages().insert(Collections.singleton(cmsg));
+
+        final Set<Account.Id> oldReviewers = new HashSet<Account.Id>();
+        final Set<Account.Id> oldCC = new HashSet<Account.Id>();
+
+        for (PatchSetApproval a : db.patchSetApprovals().byChange(change.getId())) {
+          if (a.getValue() != 0) {
+            oldReviewers.add(a.getAccountId());
+          } else {
+            oldCC.add(a.getAccountId());
+          }
+        }
+
+        final ReplacePatchSetSender cm =
+            rebasedPatchSetSenderFactory.create(change);
+        cm.setFrom(user.getAccountId());
+        cm.setPatchSet(rebasedPatchSet);
+        cm.addReviewers(oldReviewers);
+        cm.addExtraCC(oldCC);
+        cm.send();
+
+        hooks.doPatchsetCreatedHook(change, rebasedPatchSet, db);
+      } finally {
+        revWalk.release();
+      }
+    } finally {
+      git.close();
+    }
+  }
+
   public static Change.Id revert(final PatchSet.Id patchSetId,
       final IdentifiedUser user, final String message, final ReviewDb db,
       final RevertedSender.Factory revertedSenderFactory,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
index b9404b0..f057c3a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.account.GroupMembership;
 import com.google.inject.servlet.RequestScoped;
 
 import java.util.Collection;
@@ -60,7 +60,7 @@
    *
    * @return active groups for this user.
    */
-  public abstract Set<AccountGroup.UUID> getEffectiveGroups();
+  public abstract GroupMembership getEffectiveGroups();
 
   /** Set of changes starred by this user. */
   public abstract Set<Change.Id> getStarredChanges();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
index 6828e18..6e519c4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
@@ -14,22 +14,23 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountDiffPreference;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.StarredChange;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.StarredChange;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.CapabilityControl;
-import com.google.gerrit.server.account.GroupIncludeCache;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.MaterializedGroupMembership;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.CanonicalWebUrl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.OutOfScopeException;
 import com.google.inject.Provider;
@@ -51,10 +52,8 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Queue;
 import java.util.Set;
 import java.util.TimeZone;
 
@@ -71,7 +70,7 @@
     private final Provider<String> canonicalUrl;
     private final Realm realm;
     private final AccountCache accountCache;
-    private final GroupIncludeCache groupIncludeCache;
+    private final MaterializedGroupMembership.Factory groupMembershipFactory;
 
     @Inject
     GenericFactory(
@@ -80,14 +79,14 @@
         final @AnonymousCowardName String anonymousCowardName,
         final @CanonicalWebUrl Provider<String> canonicalUrl,
         final Realm realm, final AccountCache accountCache,
-        final GroupIncludeCache groupIncludeCache) {
+        final MaterializedGroupMembership.Factory groupMembershipFactory) {
       this.capabilityControlFactory = capabilityControlFactory;
       this.authConfig = authConfig;
       this.anonymousCowardName = anonymousCowardName;
       this.canonicalUrl = canonicalUrl;
       this.realm = realm;
       this.accountCache = accountCache;
-      this.groupIncludeCache = groupIncludeCache;
+      this.groupMembershipFactory = groupMembershipFactory;
     }
 
     public IdentifiedUser create(final Account.Id id) {
@@ -97,14 +96,14 @@
     public IdentifiedUser create(Provider<ReviewDb> db, Account.Id id) {
       return new IdentifiedUser(capabilityControlFactory, AccessPath.UNKNOWN,
           authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
-          groupIncludeCache, null, db, id);
+          groupMembershipFactory, null, db, id);
     }
 
     public IdentifiedUser create(AccessPath accessPath,
         Provider<SocketAddress> remotePeerProvider, Account.Id id) {
       return new IdentifiedUser(capabilityControlFactory, accessPath,
           authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
-          groupIncludeCache, remotePeerProvider, null, id);
+          groupMembershipFactory, remotePeerProvider, null, id);
     }
   }
 
@@ -122,7 +121,7 @@
     private final Provider<String> canonicalUrl;
     private final Realm realm;
     private final AccountCache accountCache;
-    private final GroupIncludeCache groupIncludeCache;
+    private final MaterializedGroupMembership.Factory groupMembershipFactory;
 
     private final Provider<SocketAddress> remotePeerProvider;
     private final Provider<ReviewDb> dbProvider;
@@ -134,7 +133,7 @@
         final @AnonymousCowardName String anonymousCowardName,
         final @CanonicalWebUrl Provider<String> canonicalUrl,
         final Realm realm, final AccountCache accountCache,
-        final GroupIncludeCache groupIncludeCache,
+        final MaterializedGroupMembership.Factory groupMembershipFactory,
 
         final @RemotePeer Provider<SocketAddress> remotePeerProvider,
         final Provider<ReviewDb> dbProvider) {
@@ -144,7 +143,7 @@
       this.canonicalUrl = canonicalUrl;
       this.realm = realm;
       this.accountCache = accountCache;
-      this.groupIncludeCache = groupIncludeCache;
+      this.groupMembershipFactory = groupMembershipFactory;
 
       this.remotePeerProvider = remotePeerProvider;
       this.dbProvider = dbProvider;
@@ -154,7 +153,7 @@
         final Account.Id id) {
       return new IdentifiedUser(capabilityControlFactory, accessPath,
           authConfig, anonymousCowardName, canonicalUrl, realm, accountCache,
-          groupIncludeCache, remotePeerProvider, dbProvider, id);
+          groupMembershipFactory, remotePeerProvider, dbProvider, id);
     }
   }
 
@@ -186,7 +185,7 @@
   private final Provider<String> canonicalUrl;
   private final Realm realm;
   private final AccountCache accountCache;
-  private final GroupIncludeCache groupIncludeCache;
+  private final MaterializedGroupMembership.Factory groupMembershipFactory;
   private final AuthConfig authConfig;
   private final String anonymousCowardName;
 
@@ -200,7 +199,7 @@
 
   private AccountState state;
   private Set<String> emailAddresses;
-  private Set<AccountGroup.UUID> effectiveGroups;
+  private GroupMembership effectiveGroups;
   private Set<Change.Id> starredChanges;
   private Collection<AccountProjectWatch> notificationFilters;
 
@@ -211,14 +210,14 @@
       final String anonymousCowardName,
       final Provider<String> canonicalUrl,
       final Realm realm, final AccountCache accountCache,
-      final GroupIncludeCache groupIncludeCache,
+      final MaterializedGroupMembership.Factory groupMembershipFactory,
       @Nullable final Provider<SocketAddress> remotePeerProvider,
       @Nullable final Provider<ReviewDb> dbProvider, final Account.Id id) {
     super(capabilityControlFactory, accessPath);
     this.canonicalUrl = canonicalUrl;
     this.realm = realm;
     this.accountCache = accountCache;
-    this.groupIncludeCache = groupIncludeCache;
+    this.groupMembershipFactory = groupMembershipFactory;
     this.authConfig = authConfig;
     this.anonymousCowardName = anonymousCowardName;
     this.remotePeerProvider = remotePeerProvider;
@@ -270,39 +269,18 @@
   }
 
   @Override
-  public Set<AccountGroup.UUID> getEffectiveGroups() {
+  public GroupMembership getEffectiveGroups() {
     if (effectiveGroups == null) {
-      Set<AccountGroup.UUID> seedGroups;
-
       if (authConfig.isIdentityTrustable(state().getExternalIds())) {
-        seedGroups = realm.groups(state());
+        effectiveGroups = realm.groups(state());
       } else {
-        seedGroups = registeredGroups;
+        effectiveGroups = groupMembershipFactory.create(registeredGroups);
       }
-
-      effectiveGroups = getIncludedGroups(seedGroups);
     }
 
     return effectiveGroups;
   }
 
-  private Set<AccountGroup.UUID> getIncludedGroups(Set<AccountGroup.UUID> seedGroups) {
-    Set<AccountGroup.UUID> includes = new HashSet<AccountGroup.UUID> (seedGroups);
-    Queue<AccountGroup.UUID> groupQueue = new LinkedList<AccountGroup.UUID> (seedGroups);
-
-    while (groupQueue.size() > 0) {
-      AccountGroup.UUID id = groupQueue.remove();
-
-      for (final AccountGroup.UUID groupId : groupIncludeCache.getByInclude(id)) {
-        if (includes.add(groupId)) {
-          groupQueue.add(groupId);
-        }
-      }
-    }
-
-    return Collections.unmodifiableSet(includes);
-  }
-
   @Override
   public Set<Change.Id> getStarredChanges() {
     if (starredChanges == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
index a58f7b0..352f540 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
@@ -14,10 +14,11 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.account.GroupMembership;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -45,8 +46,8 @@
   }
 
   @Override
-  public Set<AccountGroup.UUID> getEffectiveGroups() {
-    return Collections.emptySet();
+  public GroupMembership getEffectiveGroups() {
+    return GroupMembership.EMPTY;
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
index ae7f5ac..fc6ac9c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ReplicationUser.java
@@ -14,51 +14,39 @@
 
 package com.google.gerrit.server;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.ListGroupMembership;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Set;
 
 public class ReplicationUser extends CurrentUser {
   /** Magic set of groups enabling read of any project and reference. */
-  public static final Set<AccountGroup.UUID> EVERYTHING_VISIBLE =
-      Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(0));
+  public static final GroupMembership EVERYTHING_VISIBLE =
+      new ListGroupMembership(Collections.<AccountGroup.UUID>emptySet());
 
   public interface Factory {
-    ReplicationUser create(@Assisted Set<AccountGroup.UUID> authGroups);
+    ReplicationUser create(@Assisted GroupMembership authGroups);
   }
 
-  private final Set<AccountGroup.UUID> effectiveGroups;
+  private final GroupMembership effectiveGroups;
 
   @Inject
   protected ReplicationUser(CapabilityControl.Factory capabilityControlFactory,
-      @Assisted Set<AccountGroup.UUID> authGroups) {
+      @Assisted GroupMembership authGroups) {
     super(capabilityControlFactory, AccessPath.REPLICATION);
-
-    if (authGroups == EVERYTHING_VISIBLE) {
-      effectiveGroups = EVERYTHING_VISIBLE;
-
-    } else if (authGroups.isEmpty()) {
-      effectiveGroups = Collections.emptySet();
-
-    } else {
-      effectiveGroups = copy(authGroups);
-    }
-  }
-
-  private static Set<AccountGroup.UUID> copy(Set<AccountGroup.UUID> groups) {
-    return Collections.unmodifiableSet(new HashSet<AccountGroup.UUID>(groups));
+    effectiveGroups = authGroups;
   }
 
   @Override
-  public Set<AccountGroup.UUID> getEffectiveGroups() {
+  public GroupMembership getEffectiveGroups() {
     return effectiveGroups;
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCache.java
index 1eb1a4f..406ab52 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 import java.util.Set;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCacheImpl.java
index 64046fa..72fb2e8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountByEmailCacheImpl.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
index 1b3626b..056babd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 /** Caches important (but small) account state to avoid database hits. */
 public interface AccountCache {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
index aea13c7..819ec31 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
@@ -14,16 +14,16 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountControl.java
new file mode 100644
index 0000000..b297ed8
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountControl.java
@@ -0,0 +1,121 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+import com.google.gerrit.common.errors.NoSuchGroupException;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import java.util.Set;
+
+/** Access control management for one account's access to other accounts. */
+public class AccountControl {
+  public static class Factory {
+    private final GroupControl.Factory groupControlFactory;
+    private final Provider<CurrentUser> user;
+    private final IdentifiedUser.GenericFactory userFactory;
+    private final AccountVisibility accountVisibility;
+
+    @Inject
+    Factory(final GroupControl.Factory groupControlFactory,
+        final Provider<CurrentUser> user,
+        final IdentifiedUser.GenericFactory userFactory,
+        final AccountVisibility accountVisibility) {
+      this.groupControlFactory = groupControlFactory;
+      this.user = user;
+      this.userFactory = userFactory;
+      this.accountVisibility = accountVisibility;
+    }
+
+    public AccountControl get() {
+      return new AccountControl(groupControlFactory, user.get(), userFactory,
+          accountVisibility);
+    }
+  }
+
+  private final GroupControl.Factory groupControlFactory;
+  private final CurrentUser currentUser;
+  private final IdentifiedUser.GenericFactory userFactory;
+  private final AccountVisibility accountVisibility;
+
+  AccountControl(final GroupControl.Factory groupControlFactory,
+        final CurrentUser currentUser,
+        final IdentifiedUser.GenericFactory userFactory,
+        final AccountVisibility accountVisibility) {
+    this.groupControlFactory = groupControlFactory;
+    this.currentUser = currentUser;
+    this.userFactory = userFactory;
+    this.accountVisibility = accountVisibility;
+  }
+
+  /**
+   * Returns true if the otherUser is allowed to see the current user, based
+   * on the account visibility policy. Depending on the group membership
+   * realms supported, this may not be able to determine SAME_GROUP or
+   * VISIBLE_GROUP correctly (defaulting to not being visible). This is because
+   * {@link GroupMembership#getKnownGroups()} may only return a subset of the
+   * effective groups.
+   */
+  public boolean canSee(final Account otherUser) {
+    // Special case: I can always see myself.
+    if (currentUser instanceof IdentifiedUser
+        && ((IdentifiedUser) currentUser).getAccountId()
+            .equals(otherUser.getId())) {
+      return true;
+    }
+
+    switch (accountVisibility) {
+      case ALL:
+        return true;
+      case SAME_GROUP: {
+        Set<AccountGroup.UUID> usersGroups = groupsOf(otherUser);
+        usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
+        usersGroups.remove(AccountGroup.REGISTERED_USERS);
+        if (currentUser.getEffectiveGroups().containsAnyOf(usersGroups)) {
+          return true;
+        }
+        break;
+      }
+      case VISIBLE_GROUP: {
+        Set<AccountGroup.UUID> usersGroups = groupsOf(otherUser);
+        usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
+        usersGroups.remove(AccountGroup.REGISTERED_USERS);
+        for (AccountGroup.UUID usersGroup : usersGroups) {
+          try {
+            if (groupControlFactory.controlFor(usersGroup).isVisible()) {
+              return true;
+            }
+          } catch (NoSuchGroupException e) {
+            continue;
+          }
+        }
+        break;
+      }
+      case NONE:
+        break;
+      default:
+        throw new IllegalStateException("Bad AccountVisibility " + accountVisibility);
+    }
+    return false;
+  }
+
+  private Set<AccountGroup.UUID> groupsOf(Account account) {
+    return userFactory.create(account.getId()).getEffectiveGroups().getKnownGroups();
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountInfoCacheFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountInfoCacheFactory.java
index bb6e278..e3cf023 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountInfoCacheFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountInfoCacheFactory.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.data.AccountInfo;
 import com.google.gerrit.common.data.AccountInfoCache;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.inject.Inject;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
index 3f4d0d1..6c216a8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
@@ -20,17 +20,17 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.errors.InvalidUserNameException;
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.project.ProjectCache;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountResolver.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountResolver.java
index 3dce94e..3a2ac56 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountResolver.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountResolver.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountState.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountState.java
index 1b036d8..488370e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountState.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.account;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.Collection;
 import java.util.HashSet;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibility.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibility.java
new file mode 100644
index 0000000..7452da3
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibility.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+/** Visibility level of other accounts to a given user. */
+public enum AccountVisibility {
+  /** All accounts are visible to all users. */
+  ALL,
+
+  /** Accounts sharing a group with the given user. */
+  SAME_GROUP,
+
+  /** Accounts in a group that is visible to the given user. */
+  VISIBLE_GROUP,
+
+  /**
+   * Other accounts are not visible to the given user unless they are explicitly
+   * collaborating on a change.
+   */
+  NONE;
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibilityProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibilityProvider.java
new file mode 100644
index 0000000..d7f7a19
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountVisibilityProvider.java
@@ -0,0 +1,59 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.lib.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AccountVisibilityProvider implements Provider<AccountVisibility> {
+  private static final Logger log =
+      LoggerFactory.getLogger(AccountVisibilityProvider.class);
+
+  private final AccountVisibility accountVisibility;
+
+  @Inject
+  AccountVisibilityProvider(@GerritServerConfig Config cfg) {
+    AccountVisibility av;
+    if (cfg.getString("accounts", null, "visibility") != null) {
+      av = cfg.getEnum("accounts", null, "visibility", AccountVisibility.ALL);
+    } else if (cfg.getString("suggest", null, "accounts") != null) {
+      try {
+        av = cfg.getEnum("suggest", null, "accounts", AccountVisibility.ALL);
+        log.warn(String.format(
+            "Using legacy value %s for suggest.accounts;"
+            + " use accounts.visibility=%s instead",
+            av, av));
+      } catch (IllegalArgumentException err) {
+        // If suggest.accounts is a valid boolean, it's a new-style config, and
+        // we should use the default here. Invalid values are caught in
+        // SuggestServiceImpl so we don't worry about them here.
+        av = AccountVisibility.ALL;
+      }
+    } else {
+      av = AccountVisibility.ALL;
+    }
+    accountVisibility = av;
+  }
+
+  @Override
+  public AccountVisibility get() {
+    return accountVisibility;
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthRequest.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthRequest.java
index 034b176..35ab3af 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthRequest.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthRequest.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.account;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_GERRIT;
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_MAILTO;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_GERRIT;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_MAILTO;
 
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 
 /**
  * Information for {@link AccountManager#authenticate(AuthRequest)}.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthResult.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthResult.java
index df65796..b94e41a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthResult.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AuthResult.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
 
 /** Result from {@link AccountManager#authenticate(AuthRequest)}. */
 public class AuthResult {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java
index 3d03ed8..796b44e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CapabilityCollection.java
@@ -20,7 +20,7 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -34,6 +34,7 @@
   private final Map<String, List<PermissionRule>> permissions;
 
   public final List<PermissionRule> administrateServer;
+  public final List<PermissionRule> emailReviewers;
   public final List<PermissionRule> priority;
   public final List<PermissionRule> queryLimit;
 
@@ -46,14 +47,17 @@
         new HashMap<String, List<PermissionRule>>();
     for (Permission permission : section.getPermissions()) {
       for (PermissionRule rule : permission.getRules()) {
-        if (rule.getAction() != PermissionRule.Action.DENY) {
-          List<PermissionRule> r = tmp.get(permission.getName());
-          if (r == null) {
-            r = new ArrayList<PermissionRule>(2);
-            tmp.put(permission.getName(), r);
-          }
-          r.add(rule);
+        if (!permission.getName().equals(GlobalCapability.EMAIL_REVIEWERS)
+            && rule.getAction() == PermissionRule.Action.DENY) {
+          continue;
         }
+
+        List<PermissionRule> r = tmp.get(permission.getName());
+        if (r == null) {
+          r = new ArrayList<PermissionRule>(2);
+          tmp.put(permission.getName(), r);
+        }
+        r.add(rule);
       }
     }
     configureDefaults(tmp, section);
@@ -72,6 +76,7 @@
     permissions = Collections.unmodifiableMap(res);
 
     administrateServer = getPermission(GlobalCapability.ADMINISTRATE_SERVER);
+    emailReviewers = getPermission(GlobalCapability.EMAIL_REVIEWERS);
     priority = getPermission(GlobalCapability.PRIORITY);
     queryLimit = getPermission(GlobalCapability.QUERY_LIMIT);
   }
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 57d01fe..eb42921 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
@@ -14,11 +14,16 @@
 
 package com.google.gerrit.server.account;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.common.data.PermissionRule.Action;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.PeerDaemonUser;
 import com.google.gerrit.server.git.QueueProvider;
@@ -31,7 +36,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /** Access control management for server-wide capabilities. */
 public class CapabilityControl {
@@ -44,6 +48,7 @@
   private final Map<String, List<PermissionRule>> effective;
 
   private Boolean canAdministrateServer;
+  private Boolean canEmailReviewers;
 
   @Inject
   CapabilityControl(ProjectCache projectCache, @Assisted CurrentUser currentUser) {
@@ -61,7 +66,7 @@
   public boolean canAdministrateServer() {
     if (canAdministrateServer == null) {
       canAdministrateServer = user instanceof PeerDaemonUser
-          || matchAny(capabilities.administrateServer);
+          || matchAny(capabilities.administrateServer, ALLOWED_RULE);
     }
     return canAdministrateServer;
   }
@@ -84,6 +89,17 @@
       || canAdministrateServer();
   }
 
+  /** @return true if the user can email reviewers. */
+  public boolean canEmailReviewers() {
+    if (canEmailReviewers == null) {
+      canEmailReviewers =
+          matchAny(capabilities.emailReviewers, ALLOWED_RULE)
+          || !matchAny(capabilities.emailReviewers, Predicates.not(ALLOWED_RULE));
+
+    }
+    return canEmailReviewers;
+  }
+
   /** @return true if the user can kill any running task. */
   public boolean canKillTask() {
     return canPerform(GlobalCapability.KILL_TASK)
@@ -129,7 +145,7 @@
     // the 'CI Servers' actually use the BATCH queue while everyone else gets
     // to use the INTERACTIVE queue without additional grants.
     //
-    Set<AccountGroup.UUID> groups = user.getEffectiveGroups();
+    GroupMembership groups = user.getEffectiveGroups();
     boolean batch = false;
     for (PermissionRule r : capabilities.priority) {
       if (match(groups, r)) {
@@ -198,7 +214,7 @@
       return rules;
     }
 
-    Set<AccountGroup.UUID> groups = user.getEffectiveGroups();
+    GroupMembership groups = user.getEffectiveGroups();
     if (rules.size() == 1) {
       if (!match(groups, rules.get(0))) {
         rules = Collections.emptyList();
@@ -221,17 +237,26 @@
     return mine;
   }
 
-  private boolean matchAny(List<PermissionRule> rules) {
-    Set<AccountGroup.UUID> groups = user.getEffectiveGroups();
-    for (PermissionRule rule : rules) {
-      if (match(groups, rule)) {
-        return true;
-      }
+  private static final Predicate<PermissionRule> ALLOWED_RULE = new Predicate<PermissionRule>() {
+    @Override
+    public boolean apply(PermissionRule rule) {
+      return rule.getAction() == Action.ALLOW;
     }
-    return false;
+  };
+
+  private boolean matchAny(Iterable<PermissionRule> rules, Predicate<PermissionRule> predicate) {
+    Iterable<AccountGroup.UUID> ids = Iterables.transform(
+        Iterables.filter(rules, predicate),
+        new Function<PermissionRule, AccountGroup.UUID>() {
+          @Override
+          public AccountGroup.UUID apply(PermissionRule rule) {
+            return rule.getGroup().getUUID();
+          }
+        });
+    return user.getEffectiveGroups().containsAnyOf(ids);
   }
 
-  private static boolean match(Set<AccountGroup.UUID> groups,
+  private static boolean match(GroupMembership groups,
       PermissionRule rule) {
     return groups.contains(rule.getGroup().getUUID());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
index e875a19..d6f45f5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
@@ -14,18 +14,18 @@
 
 package com.google.gerrit.server.account;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
 import com.google.gerrit.common.errors.InvalidUserNameException;
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.ssh.SshKeyCache;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmDuplicateKeyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java
index 1fc87fe..255c248 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java
@@ -15,10 +15,10 @@
 package com.google.gerrit.server.account;
 
 import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/DefaultRealm.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/DefaultRealm.java
index c03aee9..56a95ba 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/DefaultRealm.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/DefaultRealm.java
@@ -14,23 +14,27 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.inject.Inject;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 public class DefaultRealm implements Realm {
   private final EmailExpander emailExpander;
   private final AccountByEmailCache byEmail;
+  private final MaterializedGroupMembership.Factory groupMembershipFactory;
 
   @Inject
   DefaultRealm(final EmailExpander emailExpander,
-      final AccountByEmailCache byEmail) {
+      final AccountByEmailCache byEmail,
+      final MaterializedGroupMembership.Factory groupMembershipFactory) {
     this.emailExpander = emailExpander;
     this.byEmail = byEmail;
+    this.groupMembershipFactory = groupMembershipFactory;
   }
 
   @Override
@@ -57,8 +61,8 @@
   }
 
   @Override
-  public Set<AccountGroup.UUID> groups(final AccountState who) {
-    return who.getInternalGroups();
+  public GroupMembership groups(final AccountState who) {
+    return groupMembershipFactory.create(who.getInternalGroups());
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneratePassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneratePassword.java
index 1b30503..bbab126 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneratePassword.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneratePassword.java
@@ -15,10 +15,10 @@
 package com.google.gerrit.server.account;
 
 import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
index 788e08e..b092ac4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.Collection;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
index 0e11d6b..d29a5e5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupCacheImpl.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java
index 9348a0c..13800b5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupComparator.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.Comparator;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
index d26a37f..f7451a8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.account;
 
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupDetailFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupDetailFactory.java
index d4c85760..7f88134 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupDetailFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupDetailFactory.java
@@ -16,12 +16,12 @@
 
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCache.java
index e5f73a3..432a8b8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import java.util.Collection;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
index 830d01c..791d0f5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupIncludeCacheImpl.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupInfoCacheFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupInfoCacheFactory.java
index a3e592f..19d953d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupInfoCacheFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupInfoCacheFactory.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.data.GroupInfo;
 import com.google.gerrit.common.data.GroupInfoCache;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.inject.Inject;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembers.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembers.java
index bf5329a..84282b5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembers.java
@@ -16,15 +16,15 @@
 
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java
new file mode 100644
index 0000000..9bb571e
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java
@@ -0,0 +1,51 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+import com.google.gerrit.reviewdb.client.AccountGroup;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Implementations of GroupMembership provide methods to test
+ * the presence of a user in a particular group.
+ */
+public interface GroupMembership {
+
+  public static final GroupMembership EMPTY =
+      new ListGroupMembership(Collections.<AccountGroup.UUID>emptySet());
+
+  /**
+   * Returns {@code true} when the user this object was created for is a member
+   * of the specified group.
+   */
+  boolean contains(AccountGroup.UUID groupId);
+
+  /**
+   * Returns {@code true} when the user this object was created for is a member
+   * of any of the specified group.
+   */
+  boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds);
+
+  /**
+   * Returns the set of groups that can be determined by the implementation.
+   * This may not return all groups the {@link #contains(AccountGroup.UUID)}
+   * would return {@code true} for, but will at least contain all top level
+   * groups. This restriction stems from the API of some group systems, which
+   * make it expensive to enumate the members of a group.
+   */
+  Set<AccountGroup.UUID> getKnownGroups();
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupUUID.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupUUID.java
index 9eec1df..b871c68 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupUUID.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupUUID.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java
new file mode 100644
index 0000000..237d381
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java
@@ -0,0 +1,52 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+
+import java.util.Set;
+
+/**
+ * GroupMembership over an explicit list.
+ */
+public class ListGroupMembership implements GroupMembership {
+
+  private final Set<AccountGroup.UUID> groups;
+
+  public ListGroupMembership(Iterable<AccountGroup.UUID> groupIds) {
+    this.groups = ImmutableSet.copyOf(groupIds);
+  }
+
+  @Override
+  public boolean contains(AccountGroup.UUID groupId) {
+    return groups.contains(groupId);
+  }
+
+  @Override
+  public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) {
+    for (AccountGroup.UUID groupId : groupIds) {
+      if (contains(groupId)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public Set<AccountGroup.UUID> getKnownGroups() {
+    return ImmutableSet.copyOf(groups);
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/MaterializedGroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/MaterializedGroupMembership.java
new file mode 100644
index 0000000..81ff656
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/MaterializedGroupMembership.java
@@ -0,0 +1,93 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.account;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import java.util.Collections;
+import java.util.Queue;
+import java.util.Set;
+
+/**
+ * Creates a GroupMembership object from materialized collection of groups.
+ */
+public class MaterializedGroupMembership implements GroupMembership {
+  public interface Factory {
+    MaterializedGroupMembership create(Iterable<AccountGroup.UUID> groupIds);
+  }
+
+  private final GroupIncludeCache groupIncludeCache;
+  private final Set<AccountGroup.UUID> includes;
+  private final Queue<AccountGroup.UUID> groupQueue;
+
+  @Inject
+  MaterializedGroupMembership(
+      GroupIncludeCache groupIncludeCache,
+      @Assisted Iterable<AccountGroup.UUID> seedGroups) {
+    this.groupIncludeCache = groupIncludeCache;
+    this.includes = Sets.newHashSet(seedGroups);
+    this.groupQueue = Lists.newLinkedList(seedGroups);
+  }
+
+  @Override
+  public boolean contains(AccountGroup.UUID id) {
+    if (id == null) {
+      return false;
+    }
+    if (includes.contains(id)) {
+      return true;
+    }
+    return findIncludedGroup(Collections.singleton(id));
+  }
+
+  @Override
+  public boolean containsAnyOf(Iterable<AccountGroup.UUID> ids) {
+    Set<AccountGroup.UUID> query = Sets.newHashSet();
+    for (AccountGroup.UUID groupId : ids) {
+      if (includes.contains(groupId)) {
+        return true;
+      }
+      query.add(groupId);
+    }
+
+    return findIncludedGroup(query);
+  }
+
+  private boolean findIncludedGroup(Set<AccountGroup.UUID> query) {
+    boolean found = false;
+    while (!found && !groupQueue.isEmpty()) {
+      AccountGroup.UUID id = groupQueue.remove();
+
+      for (final AccountGroup.UUID groupId : groupIncludeCache.getByInclude(id)) {
+        if (includes.add(groupId)) {
+          groupQueue.add(groupId);
+          found |= query.contains(groupId);
+        }
+      }
+    }
+
+    return found;
+  }
+
+  @Override
+  public Set<AccountGroup.UUID> getKnownGroups() {
+    findIncludedGroup(Collections.<AccountGroup.UUID>emptySet()); // find all
+    return Sets.newHashSet(includes);
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformCreateGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformCreateGroup.java
index 0b3555c..5f94df2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformCreateGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformCreateGroup.java
@@ -16,18 +16,18 @@
 
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
 import com.google.gerrit.common.errors.PermissionDeniedException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupInclude;
-import com.google.gerrit.reviewdb.AccountGroupIncludeAudit;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupInclude;
+import com.google.gerrit.reviewdb.client.AccountGroupIncludeAudit;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gwtorm.client.OrmDuplicateKeyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.PersonIdent;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformRenameGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformRenameGroup.java
index a57b708..6db232a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformRenameGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PerformRenameGroup.java
@@ -17,13 +17,13 @@
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.RenameGroupOp;
-import com.google.gwtorm.client.OrmDuplicateKeyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/Realm.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/Realm.java
index 58527ac..fc7c0be 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/Realm.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/Realm.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.account;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 
 import java.util.Set;
 
@@ -31,7 +31,7 @@
 
   public void onCreateAccount(AuthRequest who, Account account);
 
-  public Set<AccountGroup.UUID> groups(AccountState who);
+  public GroupMembership groups(AccountState who);
 
   /**
    * Locate an account whose local username is the given account name.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java
index 44d360e..3112ed4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/VisibleGroups.java
@@ -18,10 +18,10 @@
 import com.google.gerrit.common.data.GroupList;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -87,11 +87,18 @@
     return createGroupList(filterGroups(groups));
   }
 
+  /**
+   * Returns visible list of known groups for the user. Depending on the group
+   * membership realms supported, this may only return a subset of the effective
+   * groups.
+   * @See GroupMembership#getKnownGroups()
+   */
   public GroupList get(final IdentifiedUser user) throws OrmException,
       NoSuchGroupException {
     if (identifiedUser.get().getAccountId().equals(user.getAccountId())
         || identifiedUser.get().getCapabilities().canAdministrateServer()) {
-      final Set<AccountGroup.UUID> effective = user.getEffectiveGroups();
+      final Set<AccountGroup.UUID> effective =
+          user.getEffectiveGroups().getKnownGroups();
       final Set<AccountGroup> groups =
           new TreeSet<AccountGroup>(new GroupComparator());
       for (final AccountGroup.UUID groupId : effective) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
index 4dd4742..e81bfc2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/Helper.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.server.auth.ldap;
 
 import com.google.gerrit.common.data.ParameterizedString;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.config.ConfigUtil;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapModule.java
index d41fe82..6eb2f54 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapModule.java
@@ -16,8 +16,8 @@
 
 import static java.util.concurrent.TimeUnit.HOURS;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
index 5b19f81..e085d1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapRealm.java
@@ -14,18 +14,21 @@
 
 package com.google.gerrit.server.auth.ldap;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_GERRIT;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_GERRIT;
 
+import com.google.common.collect.Iterables;
 import com.google.gerrit.common.data.ParameterizedString;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AuthType;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AuthType;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.account.EmailExpander;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.MaterializedGroupMembership;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.auth.AuthenticationUnavailableException;
 import com.google.gerrit.server.auth.ldap.Helper.LdapSchema;
@@ -34,8 +37,8 @@
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
@@ -72,6 +75,7 @@
   private final Config config;
 
   private final Cache<String, Set<AccountGroup.UUID>> membershipCache;
+  private final MaterializedGroupMembership.Factory groupMembershipFactory;
 
   @Inject
   LdapRealm(
@@ -80,13 +84,15 @@
       final EmailExpander emailExpander,
       @Named(LdapModule.GROUP_CACHE) final Cache<String, Set<AccountGroup.UUID>> membershipCache,
       @Named(LdapModule.USERNAME_CACHE) final Cache<String, Account.Id> usernameCache,
-      @GerritServerConfig final Config config) {
+      @GerritServerConfig final Config config,
+      final MaterializedGroupMembership.Factory groupMembershipFactory) {
     this.helper = helper;
     this.authConfig = authConfig;
     this.emailExpander = emailExpander;
     this.usernameCache = usernameCache;
     this.membershipCache = membershipCache;
     this.config = config;
+    this.groupMembershipFactory = groupMembershipFactory;
 
     this.readOnlyAccountFields = new HashSet<Account.FieldName>();
 
@@ -254,14 +260,12 @@
   }
 
   @Override
-  public Set<AccountGroup.UUID> groups(final AccountState who) {
-    final HashSet<AccountGroup.UUID> r = new HashSet<AccountGroup.UUID>();
-    r.addAll(membershipCache.get(findId(who.getExternalIds())));
-    r.addAll(who.getInternalGroups());
-    return r;
+  public GroupMembership groups(final AccountState who) {
+    return groupMembershipFactory.create(Iterables.concat(
+        membershipCache.get(findId(who.getExternalIds())),
+        who.getInternalGroups()));
   }
 
-
   private static String findId(final Collection<AccountExternalId> ids) {
     for (final AccountExternalId i : ids) {
       if (i.isScheme(AccountExternalId.SCHEME_GERRIT)) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
index cc111e6..1fac8c5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/AbandonChange.java
@@ -17,19 +17,19 @@
 
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.common.data.ReviewResult;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.mail.AbandonedSender;
 import com.google.gerrit.server.mail.EmailException;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
index 761b765..268e118 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
@@ -16,17 +16,17 @@
 package com.google.gerrit.server.changedetail;
 
 import com.google.gerrit.common.data.ReviewResult;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ReplicationQueue;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
-import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/PublishDraft.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/PublishDraft.java
index c24c73c..028feac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/PublishDraft.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/PublishDraft.java
@@ -16,14 +16,14 @@
 package com.google.gerrit.server.changedetail;
 
 import com.google.gerrit.common.data.ReviewResult;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
-import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
index 5df973b..7232755 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/RestoreChange.java
@@ -17,19 +17,19 @@
 
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.common.data.ReviewResult;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.mail.RestoredSender;
 import com.google.gerrit.server.mail.EmailException;
+import com.google.gerrit.server.mail.RestoredSender;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
index 813b92a..abd3582 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/Submit.java
@@ -14,30 +14,30 @@
 
 package com.google.gerrit.server.changedetail;
 
-import static com.google.gerrit.reviewdb.ApprovalCategory.SUBMIT;
+import static com.google.gerrit.reviewdb.client.ApprovalCategory.SUBMIT;
 
 import com.google.gerrit.common.data.ReviewResult;
 import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.MergeOp;
 import com.google.gerrit.server.git.MergeQueue;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
-import java.util.concurrent.Callable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Callable;
 
 public class Submit implements Callable<ReviewResult> {
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/AllProjectsName.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/AllProjectsName.java
index bb5d9d9..198d5c5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/AllProjectsName.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/AllProjectsName.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Special name of the project that all projects derive from. */
 @SuppressWarnings("serial")
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ApprovalTypesProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ApprovalTypesProvider.java
index 0afaa05..ed9416d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ApprovalTypesProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ApprovalTypesProvider.java
@@ -16,11 +16,11 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
index fc189dd..a0f0d36 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.config;
 
 import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gwtjsonrpc.server.SignedToken;
 import com.google.gwtjsonrpc.server.XsrfException;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/CanonicalWebUrlModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/CanonicalWebUrlModule.java
index 1c70c78..8d66d33 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/CanonicalWebUrlModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/CanonicalWebUrlModule.java
@@ -14,8 +14,6 @@
 
 package com.google.gerrit.server.config;
 
-import static com.google.inject.Scopes.SINGLETON;
-
 import com.google.inject.AbstractModule;
 import com.google.inject.Provider;
 
@@ -31,7 +29,6 @@
     // running in an HTTP environment.
     //
     final Class<? extends Provider<String>> provider = provider();
-    bind(provider).in(SINGLETON);
     bind(String.class).annotatedWith(CanonicalWebUrl.class)
         .toProvider(provider);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
index 3c102ba..e76249a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
@@ -16,11 +16,15 @@
 
 import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.OrmRuntimeException;
+import com.google.gwtorm.server.SchemaFactory;
 
 import org.eclipse.jgit.lib.Config;
 import org.slf4j.Logger;
@@ -28,7 +32,9 @@
 import java.lang.reflect.InvocationTargetException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -317,25 +323,41 @@
     try {
       final ReviewDb db = dbfactory.open();
       try {
-        for (String name : groupNames) {
-          AccountGroupName group =
-              db.accountGroupNames().get(new AccountGroup.NameKey(name));
-          if (group == null) {
-            log.warn(MessageFormat.format(groupNotFoundWarning, name));
+        List<AccountGroupName> groups = db.accountGroupNames().get(
+            Iterables.transform(Arrays.asList(groupNames),
+                new Function<String, AccountGroup.NameKey>() {
+                  @Override
+                  public AccountGroup.NameKey apply(String name) {
+                    return new AccountGroup.NameKey(name);
+                  }
+            })).toList();
+
+        Iterator<AccountGroup> ags = db.accountGroups().get(
+            Iterables.transform(Iterables.filter(groups, Predicates.notNull()),
+                new Function<AccountGroupName, AccountGroup.Id>() {
+                  @Override
+                  public AccountGroup.Id apply(AccountGroupName group) {
+                    return group.getId();
+                  }
+            })).iterator();
+
+        for (int i = 0; i < groupNames.length; i++) {
+          if (groups.get(i) == null) {
+            log.warn(MessageFormat.format(groupNotFoundWarning, groupNames[i]));
             continue;
           }
-
-          AccountGroup ag = db.accountGroups().get(group.getId());
+          AccountGroup ag = ags.next();
           if (ag == null) {
-            log.warn(MessageFormat.format(groupNotFoundWarning, name));
-            continue;
+            log.warn(MessageFormat.format(groupNotFoundWarning, groupNames[i]));
+          } else {
+            result.add(ag.getGroupUUID());
           }
-
-          result.add(ag.getGroupUUID());
         }
       } finally {
         db.close();
       }
+    } catch (OrmRuntimeException e) {
+      log.error("Database error, cannot load groups", e);
     } catch (OrmException e) {
       log.error("Database error, cannot load groups", e);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java
index 6f67032..ecfe4f5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.SystemConfig;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadScheme;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/FactoryModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/FactoryModule.java
index 331f471..a0cf2ab 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/FactoryModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/FactoryModule.java
@@ -15,11 +15,7 @@
 package com.google.gerrit.server.config;
 
 import com.google.inject.AbstractModule;
-import com.google.inject.Key;
-import com.google.inject.assistedinject.FactoryProvider;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public abstract class FactoryModule extends AbstractModule {
   /**
@@ -42,63 +38,9 @@
    * Just pass {@code Foo.Factory.class} to this method. The factory will be
    * generated to return its one return type as declared in the creation method.
    *
-   * @param <F>
    * @param factory interface which specifies the bean factory method.
    */
-  protected <F> void factory(final Class<F> factory) {
-    factory(Key.get(factory), factory);
-  }
-
-  /**
-   * Register an assisted injection factory.
-   * <p>
-   * This function provides an automatic way to define a factory that creates a
-   * concrete type through assited injection. For example to configure the
-   * following assisted injection case:
-   *
-   * <pre>
-   * public class Foo {
-   *   public interface Factory {
-   *     Foo create(int a);
-   *   }
-   *   &#064;Inject
-   *   Foo(Logger log, @Assisted int a) {...}
-   * }
-   * </pre>
-   *
-   * Just pass {@code Foo.Factory.class} to this method. The factory will be
-   * generated to return its one return type as declared in the creation method.
-   *
-   * @param <F>
-   * @param key key to bind with in Guice bindings.
-   * @param factory interface which specifies the bean factory method.
-   */
-  protected <F> void factory(final Key<F> key, final Class<F> factory) {
-    final Method[] methods = factory.getDeclaredMethods();
-    switch (methods.length) {
-      case 1: {
-        final Class<?> result = methods[0].getReturnType();
-        if (isAbstract(result)) {
-          addError("Factory " + factory.getName() + " returns abstract result.");
-        } else {
-          bind(key).toProvider(FactoryProvider.newFactory(factory, result));
-        }
-        break;
-      }
-
-      case 0:
-        addError("Factory " + factory.getName() + " has no create method.");
-        break;
-
-      default:
-        addError("Factory " + factory.getName()
-            + " has more than one create method.");
-        break;
-    }
-  }
-
-  private static boolean isAbstract(final Class<?> result) {
-    return result.isInterface()
-        || (result.getModifiers() & Modifier.ABSTRACT) == Modifier.ABSTRACT;
+  protected void factory(final Class<?> factory) {
+    install(new FactoryModuleBuilder().build(factory));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 171d719..99dd54a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -17,7 +17,7 @@
 import static com.google.inject.Scopes.SINGLETON;
 
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.rules.PrologModule;
 import com.google.gerrit.rules.RulesCache;
 import com.google.gerrit.server.FileTypeRegistry;
@@ -27,12 +27,15 @@
 import com.google.gerrit.server.account.AccountByEmailCacheImpl;
 import com.google.gerrit.server.account.AccountCacheImpl;
 import com.google.gerrit.server.account.AccountInfoCacheFactory;
+import com.google.gerrit.server.account.AccountVisibility;
+import com.google.gerrit.server.account.AccountVisibilityProvider;
 import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.account.DefaultRealm;
 import com.google.gerrit.server.account.EmailExpander;
 import com.google.gerrit.server.account.GroupCacheImpl;
 import com.google.gerrit.server.account.GroupIncludeCacheImpl;
 import com.google.gerrit.server.account.GroupInfoCacheFactory;
+import com.google.gerrit.server.account.MaterializedGroupMembership;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.auth.ldap.LdapModule;
 import com.google.gerrit.server.events.EventFactory;
@@ -54,6 +57,7 @@
 import com.google.gerrit.server.project.PermissionCollection;
 import com.google.gerrit.server.project.ProjectCacheImpl;
 import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.project.ProjectNode;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.project.SectionSortCache;
 import com.google.gerrit.server.tools.ToolsCatalog;
@@ -115,8 +119,13 @@
     factory(AccountInfoCacheFactory.Factory.class);
     factory(CapabilityControl.Factory.class);
     factory(GroupInfoCacheFactory.Factory.class);
+    factory(ProjectNode.Factory.class);
     factory(ProjectState.Factory.class);
+    factory(MaterializedGroupMembership.Factory.class);
     bind(PermissionCollection.Factory.class);
+    bind(AccountVisibility.class)
+        .toProvider(AccountVisibilityProvider.class)
+        .in(SINGLETON);
 
     bind(FileTypeRegistry.class).to(MimeUtilFileTypeRegistry.class);
     bind(ToolsCatalog.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
index 54445c5..71bcc6c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
@@ -16,10 +16,11 @@
 
 import static com.google.inject.Scopes.SINGLETON;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.RequestCleanup;
+import com.google.gerrit.server.account.AccountControl;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.GroupControl;
 import com.google.gerrit.server.account.GroupDetailFactory;
@@ -32,10 +33,10 @@
 import com.google.gerrit.server.changedetail.PublishDraft;
 import com.google.gerrit.server.changedetail.RestoreChange;
 import com.google.gerrit.server.changedetail.Submit;
+import com.google.gerrit.server.git.AsyncReceiveCommits;
 import com.google.gerrit.server.git.CreateCodeReviewNotes;
 import com.google.gerrit.server.git.MergeOp;
 import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.git.ReceiveCommits;
 import com.google.gerrit.server.git.SubmoduleOp;
 import com.google.gerrit.server.mail.AbandonedSender;
 import com.google.gerrit.server.mail.AddReviewerSender;
@@ -43,6 +44,7 @@
 import com.google.gerrit.server.mail.CreateChangeSender;
 import com.google.gerrit.server.mail.MergeFailSender;
 import com.google.gerrit.server.mail.MergedSender;
+import com.google.gerrit.server.mail.RebasedPatchSetSender;
 import com.google.gerrit.server.mail.ReplacePatchSetSender;
 import com.google.gerrit.server.mail.RestoredSender;
 import com.google.gerrit.server.mail.RevertedSender;
@@ -51,6 +53,7 @@
 import com.google.gerrit.server.patch.RemoveReviewer;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.CreateProject;
+import com.google.gerrit.server.project.ListProjects;
 import com.google.gerrit.server.project.PerRequestProjectControlCache;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.SuggestParentCandidates;
@@ -69,18 +72,20 @@
     bind(MetaDataUpdate.User.class).in(RequestScoped.class);
     bind(AccountResolver.class);
     bind(ChangeQueryRewriter.class);
+    bind(ListProjects.class);
 
     bind(AnonymousUser.class).in(RequestScoped.class);
     bind(PerRequestProjectControlCache.class).in(RequestScoped.class);
     bind(ChangeControl.Factory.class).in(SINGLETON);
     bind(GroupControl.Factory.class).in(SINGLETON);
     bind(ProjectControl.Factory.class).in(SINGLETON);
+    bind(AccountControl.Factory.class).in(SINGLETON);
 
     factory(ChangeQueryBuilder.Factory.class);
-    factory(ReceiveCommits.Factory.class);
     factory(SubmoduleOp.Factory.class);
     factory(MergeOp.Factory.class);
     factory(CreateCodeReviewNotes.Factory.class);
+    install(new AsyncReceiveCommits.Module());
 
     // Not really per-request, but dammit, I don't know where else to
     // easily park this stuff.
@@ -93,6 +98,7 @@
     factory(PublishComments.Factory.class);
     factory(PublishDraft.Factory.class);
     factory(ReplacePatchSetSender.Factory.class);
+    factory(RebasedPatchSetSender.Factory.class);
     factory(AbandonedSender.Factory.class);
     factory(RemoveReviewer.Factory.class);
     factory(RestoreChange.Factory.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitReceivePackGroupsProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitReceivePackGroupsProvider.java
index 1c13b9e..9992f18 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitReceivePackGroupsProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitReceivePackGroupsProvider.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.Config;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitUploadPackGroupsProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitUploadPackGroupsProvider.java
index 65e6900..76d8844 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitUploadPackGroupsProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitUploadPackGroupsProvider.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.Config;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GroupSetProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GroupSetProvider.java
index 6ff977f..15711af 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GroupSetProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GroupSetProvider.java
@@ -17,9 +17,9 @@
 import static com.google.gerrit.server.config.ConfigUtil.groupsFor;
 import static java.util.Collections.unmodifiableSet;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroups.java
index 4ce1258..876c51f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroups.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.config;
 
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
 import com.google.inject.BindingAnnotation;
 
 import java.lang.annotation.Retention;
 
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
 /**
  * Marker on a {@code Set&lt;AccountGroup.Id>} for the configured groups which
  * should become owners of a created project.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroupsProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroupsProvider.java
index 05ea11d..b279086 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroupsProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ProjectOwnerGroupsProvider.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.Config;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/RequestScopedReviewDbProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/RequestScopedReviewDbProvider.java
index 9c3da74..4518a2e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/RequestScopedReviewDbProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/RequestScopedReviewDbProvider.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.RequestCleanup;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/TrackingFootersProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/TrackingFootersProvider.java
index 06ef0dc..c10c0eb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/TrackingFootersProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/TrackingFootersProvider.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.TrackingId;
+import com.google.gerrit.reviewdb.client.TrackingId;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStore.java
index 84c7c75..0ab21f9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStore.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.contact;
 
 import com.google.gerrit.common.errors.ContactInformationStoreException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ContactInformation;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ContactInformation;
 
 public interface ContactStore {
   boolean isEnabled();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreProvider.java
index 73dd46e..d5cd11a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/ContactStoreProvider.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.contact;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
index d391694..bc88cd2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/EncryptedContactStore.java
@@ -15,13 +15,13 @@
 package com.google.gerrit.server.contact;
 
 import com.google.gerrit.common.errors.ContactInformationStoreException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.ContactInformation;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.ContactInformation;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.UrlEncoded;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.ProvisionException;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/HttpContactStoreConnection.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/HttpContactStoreConnection.java
index 781f401..e210865 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/HttpContactStoreConnection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/HttpContactStoreConnection.java
@@ -2,15 +2,11 @@
 
 package com.google.gerrit.server.contact;
 
-import static com.google.inject.Scopes.SINGLETON;
-
-import com.google.gerrit.server.contact.ContactStoreConnection;
-import com.google.gerrit.server.contact.HttpContactStoreConnection;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.assistedinject.Assisted;
-import com.google.inject.assistedinject.FactoryProvider;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 import org.eclipse.jgit.util.IO;
 
@@ -27,11 +23,9 @@
     return new AbstractModule() {
       @Override
       protected void configure() {
-        bind(ContactStoreConnection.Factory.class)
-            .toProvider(FactoryProvider.newFactory(
-                ContactStoreConnection.Factory.class,
-                HttpContactStoreConnection.class))
-            .in(SINGLETON);
+        install(new FactoryModuleBuilder()
+            .implement(ContactStoreConnection.class, HttpContactStoreConnection.class)
+            .build(ContactStoreConnection.Factory.class));
       }
     };
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/contact/NoContactStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/contact/NoContactStore.java
index e219186..a625c0c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/contact/NoContactStore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/contact/NoContactStore.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.contact;
 
 import com.google.gerrit.common.errors.ContactInformationStoreException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ContactInformation;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ContactInformation;
 
 class NoContactStore implements ContactStore {
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/ChangeAttribute.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/ChangeAttribute.java
index 9050641..9810f59 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/ChangeAttribute.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/ChangeAttribute.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.events;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 import java.util.List;
 
@@ -39,4 +39,7 @@
     public List<TrackingIdAttribute> trackingIds;
     public PatchSetAttribute currentPatchSet;
     public List<PatchSetAttribute> patchSets;
+
+    public List<DependencyAttribute> dependsOn;
+    public List<DependencyAttribute> neededBy;
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/DependencyAttribute.java
similarity index 67%
copy from gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java
copy to gerrit-server/src/main/java/com/google/gerrit/server/events/DependencyAttribute.java
index 5900292..47fbdac 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/CodedEnum.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/DependencyAttribute.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 The Android Open Source Project
+// Copyright (C) 2012 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,9 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.reviewdb;
+package com.google.gerrit.server.events;
 
-/** Extension of Enum which provides distinct character code values. */
-public interface CodedEnum {
-  char getCode();
+public class DependencyAttribute {
+  public String id;
+  public String number;
+  public String revision;
+  public String ref;
+  public Boolean isCurrentPatchSet;
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
index cf035c8..4d34b71 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
@@ -16,19 +16,24 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.TrackingId;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.client.TrackingId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -47,16 +52,18 @@
   private final Provider<String> urlProvider;
   private final ApprovalTypes approvalTypes;
   private final PatchListCache patchListCache;
+  private final SchemaFactory<ReviewDb> schema;
 
   @Inject
   EventFactory(AccountCache accountCache,
       @CanonicalWebUrl @Nullable Provider<String> urlProvider,
       ApprovalTypes approvalTypes,
-      PatchListCache patchListCache) {
+      PatchListCache patchListCache, SchemaFactory<ReviewDb> schema) {
     this.accountCache = accountCache;
     this.urlProvider = urlProvider;
     this.approvalTypes = approvalTypes;
     this.patchListCache = patchListCache;
+    this.schema = schema;
   }
 
   /**
@@ -110,6 +117,61 @@
     a.status = change.getStatus();
   }
 
+  public void addDependencies(ChangeAttribute ca, Change change) {
+    ca.dependsOn = new ArrayList<DependencyAttribute>();
+    ca.neededBy = new ArrayList<DependencyAttribute>();
+    try {
+      final ReviewDb db = schema.open();
+      try {
+        final PatchSet.Id psId = change.currentPatchSetId();
+        for (PatchSetAncestor a : db.patchSetAncestors().ancestorsOf(psId)) {
+          for (PatchSet p :
+              db.patchSets().byRevision(a.getAncestorRevision())) {
+            Change c = db.changes().get(p.getId().getParentKey());
+            ca.dependsOn.add(newDependsOn(c, p));
+          }
+        }
+
+        final RevId revId = db.patchSets().get(psId).getRevision();
+        for (PatchSetAncestor a : db.patchSetAncestors().descendantsOf(revId)) {
+          final PatchSet p = db.patchSets().get(a.getPatchSet());
+          final Change c = db.changes().get(p.getId().getParentKey());
+          ca.neededBy.add(newNeededBy(c, p));
+        }
+      } finally {
+        db.close();
+      }
+    } catch (OrmException e) {
+      // Squash DB exceptions and leave dependency lists partially filled.
+    }
+    // Remove empty lists so a confusing label won't be displayed in the output.
+    if (ca.dependsOn.isEmpty()) {
+      ca.dependsOn = null;
+    }
+    if (ca.neededBy.isEmpty()) {
+      ca.neededBy = null;
+    }
+  }
+
+  private DependencyAttribute newDependsOn(Change c, PatchSet ps) {
+    DependencyAttribute d = newDependencyAttribute(c, ps);
+    d.isCurrentPatchSet = c.currPatchSetId().equals(ps.getId());
+    return d;
+  }
+
+  private DependencyAttribute newNeededBy(Change c, PatchSet ps) {
+    return newDependencyAttribute(c, ps);
+  }
+
+  private DependencyAttribute newDependencyAttribute(Change c, PatchSet ps) {
+    DependencyAttribute d = new DependencyAttribute();
+    d.number = c.getId().toString();
+    d.id = c.getKey().toString();
+    d.revision = ps.getRevision().get();
+    d.ref = ps.getRefName();
+    return d;
+  }
+
   public void addTrackingIds(ChangeAttribute a, Collection<TrackingId> ids) {
     if (!ids.isEmpty()) {
       a.trackingIds = new ArrayList<TrackingIdAttribute>(ids.size());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
index 2b08fa7..3802fdd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.events;
 
-import com.google.gerrit.reviewdb.Patch.ChangeType;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
 
 public class PatchAttribute {
     public String file;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java
new file mode 100644
index 0000000..c8d741b
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/AsyncReceiveCommits.java
@@ -0,0 +1,184 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.git.WorkQueue.Executor;
+import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.util.RequestScopePropagator;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+import com.google.inject.Inject;
+
+import com.google.inject.name.Named;
+import com.google.inject.PrivateModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.PreReceiveHook;
+import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.transport.ReceiveCommand.Result;
+import org.eclipse.jgit.transport.ReceivePack;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/** Hook that delegates to {@link ReceiveCommits} in a worker thread. */
+public class AsyncReceiveCommits implements PreReceiveHook {
+  private static final Logger log =
+      LoggerFactory.getLogger(AsyncReceiveCommits.class);
+
+  private static final String TIMEOUT_NAME = "ReceiveCommitsOverallTimeout";
+
+  public interface Factory {
+    AsyncReceiveCommits create(ProjectControl projectControl,
+        Repository repository);
+  }
+
+  public static class Module extends PrivateModule {
+    @Override
+    public void configure() {
+      install(new FactoryModuleBuilder()
+          .build(AsyncReceiveCommits.Factory.class));
+      expose(AsyncReceiveCommits.Factory.class);
+      // Don't expose the binding for ReceiveCommits.Factory. All callers should
+      // be using AsyncReceiveCommits.Factory instead.
+      install(new FactoryModuleBuilder()
+          .build(ReceiveCommits.Factory.class));
+    }
+
+    @Provides
+    @Singleton
+    @Named(TIMEOUT_NAME)
+    long getTimeoutMillis(@GerritServerConfig final Config cfg) {
+      return ConfigUtil.getTimeUnit(
+          cfg, "receive", null, "timeout",
+          TimeUnit.MINUTES.toMillis(2),
+          TimeUnit.MILLISECONDS);
+    }
+  }
+
+  private class Worker implements ProjectRunnable {
+    private final Collection<ReceiveCommand> commands;
+
+    private Worker(final Collection<ReceiveCommand> commands) {
+      this.commands = commands;
+    }
+
+    @Override
+    public void run() {
+      rc.processCommands(commands, progress);
+    }
+
+    @Override
+    public Project.NameKey getProjectNameKey() {
+      return rc.getProject().getNameKey();
+    }
+
+    @Override
+    public String getRemoteName() {
+      return null;
+    }
+
+    @Override
+    public boolean hasCustomizedPrint() {
+      return true;
+    }
+
+    @Override
+    public String toString() {
+      return "receive-commits";
+    }
+  }
+
+  private class MessageSenderOutputStream extends OutputStream {
+    @Override
+    public void write(int b) {
+      rc.getMessageSender().sendBytes(new byte[]{(byte)b});
+    }
+
+    @Override
+    public void write(byte[] what, int off, int len) {
+      rc.getMessageSender().sendBytes(what, off, len);
+    }
+
+    @Override
+    public void write(byte[] what) {
+      rc.getMessageSender().sendBytes(what);
+    }
+
+    @Override
+    public void flush() {
+      rc.getMessageSender().flush();
+    }
+  }
+
+  private final ReceiveCommits rc;
+  private final Executor executor;
+  private final RequestScopePropagator scopePropagator;
+  private final MultiProgressMonitor progress;
+  private final long timeoutMillis;
+
+  @Inject
+  AsyncReceiveCommits(final ReceiveCommits.Factory factory,
+      @ReceiveCommitsExecutor final Executor executor,
+      final RequestScopePropagator scopePropagator,
+      @Named(TIMEOUT_NAME) final long timeoutMillis,
+      @Assisted final ProjectControl projectControl,
+      @Assisted final Repository repo) {
+    this.executor = executor;
+    this.scopePropagator = scopePropagator;
+    rc = factory.create(projectControl, repo);
+    rc.getReceivePack().setPreReceiveHook(this);
+
+    progress = new MultiProgressMonitor(
+        new MessageSenderOutputStream(), "Processing changes");
+    this.timeoutMillis = timeoutMillis;
+  }
+
+  @Override
+  public void onPreReceive(final ReceivePack rp,
+      final Collection<ReceiveCommand> commands) {
+    try {
+      progress.waitFor(
+          executor.submit(scopePropagator.wrap(new Worker(commands))),
+          timeoutMillis, TimeUnit.MILLISECONDS);
+    } catch (ExecutionException e) {
+      log.warn("Error in ReceiveCommits", e);
+      rc.addError("internal error while processing changes");
+      // ReceiveCommits has tried its best to catch errors, so anything at this
+      // point is very bad.
+      for (final ReceiveCommand c : commands) {
+        if (c.getResult() == Result.NOT_ATTEMPTED) {
+          c.setResult(Result.REJECTED_OTHER_REASON, "internal error");
+        }
+      }
+    } finally {
+      rc.sendMessages();
+    }
+  }
+
+  public ReceiveCommits getReceiveCommits() {
+    return rc;
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ChangeMergeQueue.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ChangeMergeQueue.java
index 0bcd37b..86e0740 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ChangeMergeQueue.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ChangeMergeQueue.java
@@ -17,13 +17,14 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.RemotePeer;
 import com.google.gerrit.server.config.GerritRequestModule;
 import com.google.gerrit.server.ssh.SshInfo;
+import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -65,6 +66,8 @@
       @Override
       protected void configure() {
         bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST);
+        bind(RequestScopePropagator.class)
+            .to(PerThreadRequestScope.Propagator.class);
         install(new GerritRequestModule());
 
         bind(CurrentUser.class).to(IdentifiedUser.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewCommit.java
index 863c0bd..86d79e0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewCommit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewCommit.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
index 129dfa9..6fea8f1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
@@ -18,16 +18,16 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.config.CanonicalWebUrl;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/GitRepositoryManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/GitRepositoryManager.java
index e0c7425..a2b0495 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/GitRepositoryManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/GitRepositoryManager.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.inject.Singleton;
 
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
index d9f95a1..9fa45e1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/LocalDiskRepositoryManager.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.lifecycle.LifecycleListener;
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.inject.AbstractModule;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index c0f5f182..f862ff0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -21,17 +21,17 @@
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.Capable;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetAncestor;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
@@ -46,12 +46,13 @@
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
+import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.gerrit.server.workflow.CategoryFunction;
 import com.google.gerrit.server.workflow.FunctionState;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmConcurrencyException;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmConcurrencyException;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
@@ -150,8 +151,8 @@
   private final List<CodeReviewCommit> toMerge;
   private List<Change> submitted;
   private final Map<Change.Id, CodeReviewCommit> commits;
-  private ReviewDb schema;
-  private Repository db;
+  private ReviewDb db;
+  private Repository repo;
   private RevWalk rw;
   private RevFlag CAN_MERGE;
   private CodeReviewCommit branchTip;
@@ -164,6 +165,8 @@
   private final TagCache tagCache;
   private final CreateCodeReviewNotes.Factory codeReviewNotesFactory;
   private final SubmoduleOp.Factory subOpFactory;
+  private final WorkQueue workQueue;
+  private final RequestScopePropagator requestScopePropagator;
 
   @Inject
   MergeOp(final GitRepositoryManager grm, final SchemaFactory<ReviewDb> sf,
@@ -178,7 +181,9 @@
       final MergeQueue mergeQueue, @Assisted final Branch.NameKey branch,
       final ChangeHooks hooks, final AccountCache accountCache,
       final TagCache tagCache, final CreateCodeReviewNotes.Factory crnf,
-      final SubmoduleOp.Factory subOpFactory) {
+      final SubmoduleOp.Factory subOpFactory,
+      final WorkQueue workQueue,
+      final RequestScopePropagator requestScopePropagator) {
     repoManager = grm;
     schemaFactory = sf;
     functionState = fs;
@@ -197,7 +202,8 @@
     this.tagCache = tagCache;
     codeReviewNotesFactory = crnf;
     this.subOpFactory = subOpFactory;
-
+    this.workQueue = workQueue;
+    this.requestScopePropagator = requestScopePropagator;
     this.myIdent = myIdent;
     destBranch = branch;
     toMerge = new ArrayList<CodeReviewCommit>();
@@ -208,7 +214,7 @@
     try {
       setDestProject();
       openRepository();
-      final Ref destBranchRef = db.getRef(destBranch.get());
+      final Ref destBranchRef = repo.getRef(destBranch.get());
       submitted = new ArrayList<Change>();
       submitted.add(change);
 
@@ -230,7 +236,7 @@
           change.setLastSha1MergeTested(new RevId(""));
         }
         change.setMergeable(isMergeable(change));
-        schema.changes().update(Collections.singleton(change));
+        db.changes().update(Collections.singleton(change));
       }
     } catch (MergeException e) {
       log.error("Test merge attempt for change: " + change.getId()
@@ -242,10 +248,10 @@
       log.error("Test merge attempt for change: " + change.getId()
           + " failed", e);
     } finally {
-      if (schema != null) {
-        schema.close();
+      if (db != null) {
+        db.close();
       }
-      schema = null;
+      db = null;
     }
   }
 
@@ -258,8 +264,8 @@
   }
 
   private void openSchema() throws OrmException {
-    if (schema == null) {
-      schema = schemaFactory.open();
+    if (db == null) {
+      db = schemaFactory.open();
     }
   }
 
@@ -268,7 +274,7 @@
     try {
       openSchema();
       openRepository();
-      submitted = schema.changes().submitted(destBranch).toList();
+      submitted = db.changes().submitted(destBranch).toList();
       preMerge();
       updateBranch();
       updateChangeStatus();
@@ -279,11 +285,11 @@
       if (rw != null) {
         rw.release();
       }
-      if (db != null) {
-        db.close();
+      if (repo != null) {
+        repo.close();
       }
-      schema.close();
-      schema = null;
+      db.close();
+      db = null;
     }
   }
 
@@ -310,13 +316,13 @@
   private void openRepository() throws MergeException {
     final Project.NameKey name = destBranch.getParentKey();
     try {
-      db = repoManager.openRepository(name);
+      repo = repoManager.openRepository(name);
     } catch (RepositoryNotFoundException notGit) {
       final String m = "Repository \"" + name.get() + "\" unknown.";
       throw new MergeException(m, notGit);
     }
 
-    rw = new RevWalk(db) {
+    rw = new RevWalk(repo) {
       @Override
       protected RevCommit createCommit(final AnyObjectId id) {
         return new CodeReviewCommit(id);
@@ -331,7 +337,7 @@
     alreadyAccepted = new HashSet<RevCommit>();
 
     try {
-      branchUpdate = db.updateRef(destBranch.get());
+      branchUpdate = repo.updateRef(destBranch.get());
       if (branchUpdate.getOldObjectId() != null) {
         branchTip =
             (CodeReviewCommit) rw.parseCommit(branchUpdate.getOldObjectId());
@@ -340,7 +346,7 @@
         branchTip = null;
       }
 
-      for (final Ref r : db.getAllRefs().values()) {
+      for (final Ref r : repo.getAllRefs().values()) {
         if (r.getName().startsWith(Constants.R_HEADS)
             || r.getName().startsWith(Constants.R_TAGS)) {
           try {
@@ -357,7 +363,7 @@
 
   private void validateChangeList() throws MergeException {
     final Set<ObjectId> tips = new HashSet<ObjectId>();
-    for (final Ref r : db.getAllRefs().values()) {
+    for (final Ref r : repo.getAllRefs().values()) {
       tips.add(r.getObjectId());
     }
 
@@ -372,7 +378,7 @@
 
       final PatchSet ps;
       try {
-        ps = schema.patchSets().get(chg.currentPatchSetId());
+        ps = db.patchSets().get(chg.currentPatchSetId());
       } catch (OrmException e) {
         throw new MergeException("Cannot query the database", e);
       }
@@ -501,11 +507,11 @@
       // Settings for this project allow us to try and
       // automatically resolve conflicts within files if needed.
       // Use ResolveMerge and instruct to operate in core.
-      m = MergeStrategy.RESOLVE.newMerger(db, true);
+      m = MergeStrategy.RESOLVE.newMerger(repo, true);
     } else {
       // No auto conflict resolving allowed. If any of the
       // affected files was modified, merge will fail.
-      m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
+      m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
     }
 
     try {
@@ -603,7 +609,7 @@
       final List<CodeReviewCommit> codeReviewCommits) {
     PatchSetApproval submitter = null;
     for (final CodeReviewCommit c : codeReviewCommits) {
-      PatchSetApproval s = getSubmitter(c.patchsetId);
+      PatchSetApproval s = getSubmitter(db, c.patchsetId);
       if (submitter == null
           || (s != null && s.getGranted().compareTo(submitter.getGranted()) > 0)) {
         submitter = s;
@@ -663,7 +669,7 @@
         if (c.patchsetId != null) {
           c.statusCode = CommitMergeStatus.CLEAN_MERGE;
           if (branchUpdate.getRefLogIdent() == null) {
-            setRefLogIdent(getSubmitter(c.patchsetId));
+            setRefLogIdent(getSubmitter(db, c.patchsetId));
           }
         }
       }
@@ -688,11 +694,11 @@
         // Settings for this project allow us to try and
         // automatically resolve conflicts within files if needed.
         // Use ResolveMerge and instruct to operate in core.
-        m = MergeStrategy.RESOLVE.newMerger(db, true);
+        m = MergeStrategy.RESOLVE.newMerger(repo, true);
       } else {
         // No auto conflict resolving allowed. If any of the
         // affected files was modified, merge will fail.
-        m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db);
+        m = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(repo);
       }
 
       try {
@@ -807,7 +813,7 @@
     List<PatchSetApproval> approvalList = null;
     try {
       approvalList =
-          schema.patchSetApprovals().byPatchSet(n.patchsetId).toList();
+          db.patchSetApprovals().byPatchSet(n.patchsetId).toList();
       Collections.sort(approvalList, new Comparator<PatchSetApproval>() {
         public int compare(final PatchSetApproval a, final PatchSetApproval b) {
           return a.getGranted().compareTo(b.getGranted());
@@ -893,7 +899,7 @@
     final CodeReviewCommit newCommit = (CodeReviewCommit) rw.parseCommit(id);
 
     n.change =
-        schema.changes().atomicUpdate(n.change.getId(),
+        db.changes().atomicUpdate(n.change.getId(),
             new AtomicUpdate<Change>() {
               @Override
               public Change update(Change change) {
@@ -907,10 +913,10 @@
     ps.setUploader(submitAudit.getAccountId());
     ps.setRevision(new RevId(id.getName()));
     insertAncestors(ps.getId(), newCommit);
-    schema.patchSets().insert(Collections.singleton(ps));
+    db.patchSets().insert(Collections.singleton(ps));
 
     n.change =
-        schema.changes().atomicUpdate(n.change.getId(),
+        db.changes().atomicUpdate(n.change.getId(),
             new AtomicUpdate<Change>() {
               @Override
               public Change update(Change change) {
@@ -922,7 +928,7 @@
 
     if (approvalList != null) {
       for (PatchSetApproval a : approvalList) {
-        schema.patchSetApprovals().insert(
+        db.patchSetApprovals().insert(
             Collections.singleton(new PatchSetApproval(ps.getId(), a)));
       }
     }
@@ -945,7 +951,7 @@
       a.setAncestorRevision(new RevId(src.getParent(p).getId().name()));
       toInsert.add(a);
     }
-    schema.patchSetAncestors().insert(toInsert);
+    db.patchSetAncestors().insert(toInsert);
   }
 
   private ObjectId commit(final Merger m, final CommitBuilder mergeCommit)
@@ -992,7 +998,7 @@
       if (GitRepositoryManager.REF_CONFIG.equals(branchUpdate.getName())) {
         try {
           ProjectConfig cfg = new ProjectConfig(destProject.getNameKey());
-          cfg.load(db, mergeTip);
+          cfg.load(repo, mergeTip);
         } catch (Exception e) {
           throw new MergeException("Submit would store invalid"
               + " project configuration " + mergeTip.name() + " for "
@@ -1025,7 +1031,7 @@
                 .getName());
 
             Account account = null;
-            final PatchSetApproval submitter = getSubmitter(mergeTip.patchsetId);
+            final PatchSetApproval submitter = getSubmitter(db, mergeTip.patchsetId);
             if (submitter != null) {
               account = accountCache.get(submitter.getAccountId()).getAccount();
             }
@@ -1111,7 +1117,7 @@
     }
 
     CreateCodeReviewNotes codeReviewNotes =
-        codeReviewNotesFactory.create(schema, db);
+        codeReviewNotesFactory.create(db, repo);
     try {
       codeReviewNotes.create(merged, computeAuthor(merged));
     } catch (CodeReviewNoteCreationException e) {
@@ -1124,7 +1130,7 @@
   private void updateSubscriptions() throws MergeException {
     if (mergeTip != null && (branchTip == null || branchTip != mergeTip)) {
       SubmoduleOp subOp =
-          subOpFactory.create(destBranch, mergeTip, rw, db, destProject,
+          subOpFactory.create(destBranch, mergeTip, rw, repo, destProject,
               submitted, commits);
       try {
         subOp.update();
@@ -1236,11 +1242,11 @@
     if (commit.patchsetId == null) {
       try {
         List<PatchSet> matches =
-            schema.patchSets().byRevision(new RevId(commit.name())).toList();
+            db.patchSets().byRevision(new RevId(commit.name())).toList();
         if (matches.size() == 1) {
           final PatchSet ps = matches.get(0);
           commit.patchsetId = ps.getId();
-          commit.change = schema.changes().get(ps.getId().getParentKey());
+          commit.change = db.changes().get(ps.getId().getParentKey());
         }
       } catch (OrmException e) {
       }
@@ -1250,7 +1256,7 @@
   private boolean isAlreadySent(final Change c, final String prefix) {
     try {
       final List<ChangeMessage> msgList =
-          schema.changeMessages().byChange(c.getId()).toList();
+          db.changeMessages().byChange(c.getId()).toList();
       if (msgList.size() > 0) {
         final ChangeMessage last = msgList.get(msgList.size() - 1);
         if (last.getAuthor() == null && last.getMessage().startsWith(prefix)) {
@@ -1274,7 +1280,7 @@
   private ChangeMessage message(final Change c, final String body) {
     final String uuid;
     try {
-      uuid = ChangeUtil.messageUUID(schema);
+      uuid = ChangeUtil.messageUUID(db);
     } catch (OrmException e) {
       return null;
     }
@@ -1285,14 +1291,15 @@
     return m;
   }
 
-  private PatchSetApproval getSubmitter(PatchSet.Id c) {
+  private static PatchSetApproval getSubmitter(ReviewDb reviewDb,
+      PatchSet.Id c) {
     if (c == null) {
       return null;
     }
     PatchSetApproval submitter = null;
     try {
       final List<PatchSetApproval> approvals =
-          schema.patchSetApprovals().byPatchSet(c).toList();
+          reviewDb.patchSetApprovals().byPatchSet(c).toList();
       for (PatchSetApproval a : approvals) {
         if (a.getValue() > 0
             && ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
@@ -1307,7 +1314,7 @@
     return submitter;
   }
 
-  private void setMerged(Change c, ChangeMessage msg) {
+  private void setMerged(final Change c, final ChangeMessage msg) {
     final Change.Id changeId = c.getId();
     // We must pull the patchset out of commits, because the patchset ID is
     // modified when using the cherry-pick merge strategy.
@@ -1315,7 +1322,7 @@
     final PatchSet.Id merged = commit.change.currentPatchSetId();
 
     try {
-      schema.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() {
+      db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() {
         @Override
         public Change update(Change c) {
           c.setStatus(Change.Status.MERGED);
@@ -1328,7 +1335,7 @@
             // Go back to the patch set that was actually merged.
             //
             try {
-              c.setCurrentPatchSet(patchSetInfoFactory.get(schema, merged));
+              c.setCurrentPatchSet(patchSetInfoFactory.get(db, merged));
             } catch (PatchSetInfoNotAvailableException e1) {
               log.error("Cannot read merged patch set " + merged, e1);
             }
@@ -1352,7 +1359,7 @@
     try {
       c.setStatus(Change.Status.MERGED);
       final List<PatchSetApproval> approvals =
-          schema.patchSetApprovals().byChange(changeId).toList();
+          db.patchSetApprovals().byChange(changeId).toList();
       final FunctionState fs = functionState.create(
           changeControlFactory.controlFor(
               c,
@@ -1372,7 +1379,7 @@
         }
         a.cache(c);
       }
-      schema.patchSetApprovals().update(approvals);
+      db.patchSetApprovals().update(approvals);
     } catch (NoSuchChangeException err) {
       log.warn("Cannot normalize approvals for change " + changeId, err);
     } catch (OrmException err) {
@@ -1384,29 +1391,53 @@
         msg.setAuthor(submitter.getAccountId());
       }
       try {
-        schema.changeMessages().insert(Collections.singleton(msg));
+        db.changeMessages().insert(Collections.singleton(msg));
       } catch (OrmException err) {
         log.warn("Cannot store message on change", err);
       }
     }
 
-    try {
-      final MergedSender cm = mergedSenderFactory.create(c);
-      if (submitter != null) {
-        cm.setFrom(submitter.getAccountId());
+    final PatchSetApproval from = submitter;
+    workQueue.getDefaultQueue()
+        .submit(requestScopePropagator.wrap(new Runnable() {
+      @Override
+      public void run() {
+        PatchSet patchSet;
+        try {
+          ReviewDb reviewDb = schemaFactory.open();
+          try {
+            patchSet = reviewDb.patchSets().get(c.currentPatchSetId());
+          } finally {
+            reviewDb.close();
+          }
+        } catch (OrmException e) {
+          log.error("Cannot send email for submitted patch set " + c.getId(), e);
+          return;
+        }
+
+        try {
+          final MergedSender cm = mergedSenderFactory.create(c);
+          if (from != null) {
+            cm.setFrom(from.getAccountId());
+          }
+          cm.setPatchSet(patchSet);
+          cm.send();
+        } catch (EmailException e) {
+          log.error("Cannot send email for submitted patch set " + c.getId(), e);
+        }
       }
-      cm.setPatchSet(schema.patchSets().get(c.currentPatchSetId()));
-      cm.send();
-    } catch (OrmException e) {
-      log.error("Cannot send email for submitted patch set " + c.getId(), e);
-    } catch (EmailException e) {
-      log.error("Cannot send email for submitted patch set " + c.getId(), e);
-    }
+
+      @Override
+      public String toString() {
+        return "send-email merged";
+      }
+    }));
+
 
     try {
       hooks.doChangeMergedHook(c, //
           accountCache.get(submitter.getAccountId()).getAccount(), //
-          schema.patchSets().get(c.currentPatchSetId()), schema);
+          db.patchSets().get(c.currentPatchSetId()), db);
     } catch (OrmException ex) {
       log.error("Cannot run hook for submitted patch set " + c.getId(), ex);
     }
@@ -1416,16 +1447,17 @@
     sendMergeFail(c, msg, true);
   }
 
-  private void sendMergeFail(Change c, ChangeMessage msg, final boolean makeNew) {
+  private void sendMergeFail(final Change c, final ChangeMessage msg,
+      final boolean makeNew) {
     try {
-      schema.changeMessages().insert(Collections.singleton(msg));
+      db.changeMessages().insert(Collections.singleton(msg));
     } catch (OrmException err) {
       log.warn("Cannot record merge failure message", err);
     }
 
     if (makeNew) {
       try {
-        schema.changes().atomicUpdate(c.getId(), new AtomicUpdate<Change>() {
+        db.changes().atomicUpdate(c.getId(), new AtomicUpdate<Change>() {
           @Override
           public Change update(Change c) {
             if (c.getStatus().isOpen()) {
@@ -1441,25 +1473,48 @@
       }
     } else {
       try {
-        ChangeUtil.touch(c, schema);
+        ChangeUtil.touch(c, db);
       } catch (OrmException err) {
         log.warn("Cannot update change timestamp", err);
       }
     }
 
-    try {
-      final MergeFailSender cm = mergeFailSenderFactory.create(c);
-      final PatchSetApproval submitter = getSubmitter(c.currentPatchSetId());
-      if (submitter != null) {
-        cm.setFrom(submitter.getAccountId());
+    workQueue.getDefaultQueue()
+        .submit(requestScopePropagator.wrap(new Runnable() {
+      @Override
+      public void run() {
+        PatchSet patchSet;
+        PatchSetApproval submitter;
+        try {
+          ReviewDb reviewDb = schemaFactory.open();
+          try {
+            patchSet = reviewDb.patchSets().get(c.currentPatchSetId());
+            submitter = getSubmitter(reviewDb, c.currentPatchSetId());
+          } finally {
+            reviewDb.close();
+          }
+        } catch (OrmException e) {
+          log.error("Cannot send email notifications about merge failure", e);
+          return;
+        }
+
+        try {
+          final MergeFailSender cm = mergeFailSenderFactory.create(c);
+          if (submitter != null) {
+            cm.setFrom(submitter.getAccountId());
+          }
+          cm.setPatchSet(patchSet);
+          cm.setChangeMessage(msg);
+          cm.send();
+        } catch (EmailException e) {
+          log.error("Cannot send email notifications about merge failure", e);
+        }
       }
-      cm.setPatchSet(schema.patchSets().get(c.currentPatchSetId()));
-      cm.setChangeMessage(msg);
-      cm.send();
-    } catch (OrmException e) {
-      log.error("Cannot send email notifications about merge failure", e);
-    } catch (EmailException e) {
-      log.error("Cannot send email notifications about merge failure", e);
-    }
+
+      @Override
+      public String toString() {
+        return "send-email merge-failed";
+      }
+    }));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeQueue.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeQueue.java
index 39017eb..1071768 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeQueue.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeQueue.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Branch;
+import com.google.gerrit.reviewdb.client.Branch;
 
 import java.util.concurrent.TimeUnit;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
index 568c8cf9..fbe9d16 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MultiProgressMonitor.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MultiProgressMonitor.java
new file mode 100644
index 0000000..dbb849c
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MultiProgressMonitor.java
@@ -0,0 +1,325 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import org.eclipse.jgit.lib.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.List;
+
+/**
+ * Progress reporting interface that multiplexes multiple sub-tasks.
+ * <p>
+ * Output is of the format:
+ * <pre>
+ *   Task: subA: 1, subB: 75% (3/4) (-)\r
+ *   Task: subA: 2, subB: 75% (3/4), subC: 1 (\)\r
+ *   Task: subA: 2, subB: 100% (4/4), subC: 1 (|)\r
+ *   Task: subA: 4, subB: 100% (4/4), subC: 4, done    \n
+ * </pre>
+ * <p>
+ * Callers should try to keep task and sub-task descriptions short, since the
+ * output should fit on one terminal line. (Note that git clients do not accept
+ * terminal control characters, so true multi-line progress messages would be
+ * impossible.)
+ */
+public class MultiProgressMonitor {
+  private static final Logger log =
+      LoggerFactory.getLogger(MultiProgressMonitor.class);
+
+  /** Constant indicating the total work units cannot be predicted. */
+  public static final int UNKNOWN = 0;
+
+  private static final char[] SPINNER_STATES = new char[]{'-', '\\', '|', '/'};
+  private static final char NO_SPINNER = ' ';
+
+  /** Handle for a sub-task. */
+  public class Task {
+    private final String name;
+    private final int total;
+    private volatile int count;
+    private int lastPercent;
+
+    Task(final String subTaskName, final int totalWork) {
+      this.name = subTaskName;
+      this.total = totalWork;
+    }
+
+    /**
+     * Indicate that work has been completed on this sub-task.
+     * <p>
+     * Must be called from the worker thread.
+     *
+     * @param completed number of work units completed.
+     */
+    public void update(final int completed) {
+      count += completed;
+      if (total != UNKNOWN) {
+        int percent = count * 100 / total;
+        if (percent > lastPercent) {
+          lastPercent = percent;
+          wakeUp();
+        }
+      }
+    }
+
+    /**
+     * Indicate that this sub-task is finished.
+     * <p>
+     * Must be called from the worker thread.
+     */
+    public void end() {
+      if (total == UNKNOWN && count > 0) {
+        wakeUp();
+      }
+    }
+  }
+
+  private final OutputStream out;
+  private final String taskName;
+  private final List<Task> tasks = new CopyOnWriteArrayList<Task>();
+  private int spinnerIndex;
+  private char spinnerState = NO_SPINNER;
+  private boolean done;
+  private boolean write = true;
+
+  private final long maxIntervalNanos;
+
+  /**
+   * Create a new progress monitor for multiple sub-tasks.
+   *
+   * @param out stream for writing progress messages.
+   * @param taskName name of the overall task.
+   */
+  public MultiProgressMonitor(final OutputStream out, final String taskName) {
+    this(out, taskName, 500, TimeUnit.MILLISECONDS);
+  }
+
+  /**
+   * Create a new progress monitor for multiple sub-tasks.
+   *
+   * @param out stream for writing progress messages.
+   * @param taskName name of the overall task.
+   * @param maxIntervalTime maximum interval between progress messages.
+   * @param maxIntervalUnit time unit for progress interval.
+   */
+  public MultiProgressMonitor(final OutputStream out, final String taskName,
+      long maxIntervalTime, TimeUnit maxIntervalUnit) {
+    this.out = out;
+    this.taskName = taskName;
+    maxIntervalNanos = NANOSECONDS.convert(maxIntervalTime, maxIntervalUnit);
+  }
+
+  /**
+   * Wait for a task managed by a {@link Future}, with no timeout.
+   *
+   * @see #waitFor(Future, long, TimeUnit)
+   */
+  public void waitFor(final Future<?> workerFuture) throws ExecutionException {
+    waitFor(workerFuture, 0, null);
+  }
+
+  /**
+   * Wait for a task managed by a {@link Future}.
+   * <p>
+   * Must be called from the main thread, <em>not</em> the worker thread. Once
+   * the worker thread calls {@link #end()}, the future has an additional
+   * <code>maxInterval</code> to finish before it is forcefully cancelled and
+   * {@link ExecutionException} is thrown.
+   *
+   * @param workerFuture a future that returns when the worker thread is
+   *     finished.
+   * @param timeoutTime overall timeout for the task; the future is forcefully
+   *     cancelled if the task exceeds the timeout. Non-positive values indicate
+   *     no timeout.
+   * @param timeoutUnit unit for overall task timeout.
+   * @throws ExecutionException if this thread or the worker thread was
+   *     interrupted, the worker was cancelled, or the worker timed out.
+   */
+  public void waitFor(final Future<?> workerFuture, final long timeoutTime,
+      final TimeUnit timeoutUnit) throws ExecutionException {
+    long overallStart = System.nanoTime();
+    long deadline;
+    if (timeoutTime > 0) {
+      deadline = overallStart + NANOSECONDS.convert(timeoutTime, timeoutUnit);
+    } else {
+      deadline = 0;
+    }
+
+    synchronized (this) {
+      long left = maxIntervalNanos;
+      while (!done) {
+        long start = System.nanoTime();
+        try {
+          NANOSECONDS.timedWait(this, left);
+        } catch (InterruptedException e) {
+          throw new ExecutionException(e);
+        }
+
+        // Send an update on every wakeup (manual or spurious), but only move
+        // the spinner every maxInterval.
+        long now = System.nanoTime();
+
+        if (deadline > 0 && now > deadline) {
+          log.warn(String.format(
+              "MultiProgressMonitor worker killed after %sms",
+              TimeUnit.MILLISECONDS.convert(now - overallStart, NANOSECONDS)));
+          workerFuture.cancel(true);
+          break;
+        }
+
+        left -= now - start;
+        if (left <= 0) {
+          moveSpinner();
+          left = maxIntervalNanos;
+        }
+        sendUpdate();
+        if (!done && workerFuture.isDone()) {
+          // The worker may not have called end() explicitly, which is likely a
+          // programming error.
+          log.warn("MultiProgressMonitor worker did not call end()"
+              + " before returning");
+          end();
+        }
+      }
+      sendDone();
+    }
+
+    // The loop exits as soon as the worker calls end(), but we give it another
+    // maxInterval to finish up and return.
+    try {
+      workerFuture.get(maxIntervalNanos, NANOSECONDS);
+    } catch (InterruptedException e) {
+      throw new ExecutionException(e);
+    } catch (CancellationException e) {
+      throw new ExecutionException(e);
+    } catch (TimeoutException e) {
+      workerFuture.cancel(true);
+      throw new ExecutionException(e);
+    }
+  }
+
+  private synchronized void wakeUp() {
+    notifyAll();
+  }
+
+  /**
+   * Begin a sub-task.
+   *
+   * @param subTask sub-task name.
+   * @param subTaskWork total work units in sub-task, or {@link #UNKNOWN}.
+   * @return sub-task handle.
+   */
+  public Task beginSubTask(final String subTask, final int subTaskWork) {
+    Task task = new Task(subTask, subTaskWork);
+    tasks.add(task);
+    return task;
+  }
+
+  /**
+   * End the overall task.
+   * <p>
+   * Must be called from the worker thread.
+   */
+  public synchronized void end() {
+    done = true;
+    wakeUp();
+  }
+
+  private void sendDone() {
+    spinnerState = NO_SPINNER;
+    StringBuilder s = format();
+    boolean any = false;
+    for (Task t : tasks) {
+      if (t.count != 0) {
+        any = true;
+        break;
+      }
+    }
+    if (any) {
+      s.append(",");
+    }
+    s.append(" done    \n");
+    send(s);
+  }
+
+  private void moveSpinner() {
+    spinnerIndex = (spinnerIndex + 1) % SPINNER_STATES.length;
+    spinnerState = SPINNER_STATES[spinnerIndex];
+  }
+
+  private void sendUpdate() {
+    send(format());
+  }
+
+  private StringBuilder format() {
+    StringBuilder s = new StringBuilder().append("\r").append(taskName)
+        .append(':');
+
+    if (!tasks.isEmpty()) {
+      boolean first = true;
+      for (Task t : tasks) {
+        int count = t.count;
+        if (count == 0) {
+          continue;
+        }
+
+        if (!first) {
+          s.append(',');
+        } else {
+          first = false;
+        }
+
+        s.append(' ').append(t.name).append(": ");
+        if (t.total == UNKNOWN) {
+          s.append(count);
+        } else {
+          s.append(String.format("%d%% (%d/%d)",
+              count * 100 / t.total,
+              count, t.total));
+        }
+      }
+    }
+
+    if (spinnerState != NO_SPINNER) {
+      // Don't output a spinner until the alarm fires for the first time.
+      s.append(" (").append(spinnerState).append(')');
+    }
+    return s;
+  }
+
+  private void send(StringBuilder s) {
+    if (write) {
+      try {
+        out.write(Constants.encode(s.toString()));
+        out.flush();
+      } catch (IOException e) {
+        write = false;
+      }
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/NoReplication.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/NoReplication.java
index ceb70d2..c5ee262 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/NoReplication.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/NoReplication.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** A disabled {@link ReplicationQueue}. */
 public final class NoReplication implements ReplicationQueue {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PerThreadRequestScope.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PerThreadRequestScope.java
index 592f44f..057e80d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PerThreadRequestScope.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PerThreadRequestScope.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.git;
 
 import com.google.gerrit.server.RequestCleanup;
+import com.google.gerrit.server.util.ThreadLocalRequestScopePropagator;
 import com.google.inject.Key;
 import com.google.inject.OutOfScopeException;
 import com.google.inject.Provider;
@@ -24,10 +25,23 @@
 import java.util.Map;
 
 class PerThreadRequestScope {
+  static class Propagator
+      extends ThreadLocalRequestScopePropagator<PerThreadRequestScope> {
+    Propagator() {
+      super(REQUEST, current);
+    }
+
+    @Override
+    protected PerThreadRequestScope continuingContext(
+        PerThreadRequestScope ctx) {
+      return new PerThreadRequestScope();
+    }
+  }
+
   private static final ThreadLocal<PerThreadRequestScope> current =
       new ThreadLocal<PerThreadRequestScope>();
 
-  private static PerThreadRequestScope getContext() {
+  private static PerThreadRequestScope requireContext() {
     final PerThreadRequestScope ctx = current.get();
     if (ctx == null) {
       throw new OutOfScopeException("Not in command/request");
@@ -45,7 +59,7 @@
     public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
       return new Provider<T>() {
         public T get() {
-          return getContext().get(key, creator);
+          return requireContext().get(key, creator);
         }
 
         @Override
@@ -82,4 +96,4 @@
     }
     return t;
   }
-}
\ No newline at end of file
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index 7131012..d15095b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -14,7 +14,6 @@
 
 package com.google.gerrit.server.git;
 
-import static com.google.gerrit.common.data.AccessSection.isAccessSection;
 import static com.google.gerrit.common.data.Permission.isPermission;
 
 import com.google.gerrit.common.data.AccessSection;
@@ -22,11 +21,12 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.State;
-import com.google.gerrit.reviewdb.Project.SubmitType;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.State;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
 import com.google.gerrit.server.account.GroupCache;
+import com.google.gerrit.common.data.RefConfigSection;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.CommitBuilder;
@@ -225,7 +225,7 @@
 
     accessSections = new HashMap<String, AccessSection>();
     for (String refName : rc.getSubsections(ACCESS)) {
-      if (isAccessSection(refName)) {
+      if (RefConfigSection.isValid(refName)) {
         AccessSection as = getAccessSection(refName, true);
 
         for (String varName : rc.getStringList(ACCESS, refName, KEY_GROUP_PERMISSIONS)) {
@@ -421,7 +421,7 @@
     }
 
     for (String name : rc.getSubsections(ACCESS)) {
-      if (isAccessSection(name) && !accessSections.containsKey(name)) {
+      if (RefConfigSection.isValid(name) && !accessSections.containsKey(name)) {
         rc.unsetSection(ACCESS, name);
       }
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectRunnable.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectRunnable.java
index a94ba39..32f157d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectRunnable.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectRunnable.java
@@ -13,7 +13,7 @@
 // limitations under the License.
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Used to retrieve the project name from an operation **/
 public interface ProjectRunnable extends Runnable {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushAllProjectsOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushAllProjectsOp.java
index b5f991c..845d037 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushAllProjectsOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushAllProjectsOp.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
index cf2db15..0868749 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.NameKey;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
index 154c609..5cf5f7a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
@@ -14,22 +14,23 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.ReplicationUser;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.ListGroupMembership;
 import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.PerRequestProjectControlCache;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.Singleton;
-import com.google.inject.assistedinject.FactoryProvider;
 import com.google.inject.servlet.RequestScoped;
 
 import com.jcraft.jsch.Session;
@@ -66,7 +67,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /** Manages automatic replication to remote repositories. */
@@ -353,7 +353,7 @@
       }
 
       @Override
-      public synchronized void write(final int b) throws IOException {
+      public synchronized void write(final int b) {
         if (b == '\r') {
           return;
         }
@@ -404,10 +404,10 @@
 
       String[] authGroupNames =
           cfg.getStringList("remote", rc.getName(), "authGroup");
-      final Set<AccountGroup.UUID> authGroups;
+      final GroupMembership authGroups;
       if (authGroupNames.length > 0) {
-        authGroups = ConfigUtil.groupsFor(db, authGroupNames, //
-            log, "Group \"{0}\" not in database, removing from authGroup");
+        authGroups = new ListGroupMembership(ConfigUtil.groupsFor(db, authGroupNames, //
+            log, "Group \"{0}\" not in database, removing from authGroup"));
       } else {
         authGroups = ReplicationUser.EVERYTHING_VISIBLE;
       }
@@ -430,14 +430,12 @@
             }
           }).getInstance(ProjectControl.Factory.class);
 
-      opFactory = injector.createChildInjector(new AbstractModule() {
+      opFactory = injector.createChildInjector(new FactoryModule() {
         @Override
         protected void configure() {
-          bind(PushReplication.ReplicationConfig.class).toInstance(
-              ReplicationConfig.this);
+          bind(PushReplication.ReplicationConfig.class).toInstance(ReplicationConfig.this);
           bind(RemoteConfig.class).toInstance(remote);
-          bind(PushOp.Factory.class).toProvider(
-              FactoryProvider.newFactory(PushOp.Factory.class, PushOp.class));
+          factory(PushOp.Factory.class);
         }
       }).getInstance(PushOp.Factory.class);
     }
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 8450dc5..b8d133e 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
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.server.git;
 
+import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN;
+
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.ApprovalType;
@@ -21,18 +23,18 @@
 import com.google.gerrit.common.data.Capable;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetAncestor;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetAncestor;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ApprovalsUtil;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.GerritPersonIdent;
@@ -40,6 +42,7 @@
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.TrackingFooters;
+import com.google.gerrit.server.git.MultiProgressMonitor.Task;
 import com.google.gerrit.server.mail.CreateChangeSender;
 import com.google.gerrit.server.mail.EmailException;
 import com.google.gerrit.server.mail.MergedSender;
@@ -51,8 +54,9 @@
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.project.RefControl;
 import com.google.gerrit.server.util.MagicBranch;
-import com.google.gwtorm.client.AtomicUpdate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.server.util.RequestScopePropagator;
+import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -74,8 +78,8 @@
 import org.eclipse.jgit.revwalk.RevSort;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.revwalk.filter.RevFilter;
-import org.eclipse.jgit.transport.PostReceiveHook;
-import org.eclipse.jgit.transport.PreReceiveHook;
+import org.eclipse.jgit.transport.AdvertiseRefsHook;
+import org.eclipse.jgit.transport.AdvertiseRefsHookChain;
 import org.eclipse.jgit.transport.ReceiveCommand;
 import org.eclipse.jgit.transport.ReceiveCommand.Result;
 import org.eclipse.jgit.transport.ReceivePack;
@@ -98,7 +102,7 @@
 import javax.annotation.Nullable;
 
 /** Receives change upload using the Git receive-pack protocol. */
-public class ReceiveCommits implements PreReceiveHook, PostReceiveHook {
+public class ReceiveCommits {
   private static final Logger log =
       LoggerFactory.getLogger(ReceiveCommits.class);
 
@@ -109,10 +113,63 @@
   private static final FooterKey TESTED_BY = new FooterKey("Tested-by");
   private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
 
-  public interface Factory {
+  interface Factory {
     ReceiveCommits create(ProjectControl projectControl, Repository repository);
   }
 
+  public interface MessageSender {
+    void sendMessage(String what);
+    void sendError(String what);
+    void sendBytes(byte[] what);
+    void sendBytes(byte[] what, int off, int len);
+    void flush();
+  }
+
+  private class ReceivePackMessageSender implements MessageSender {
+    @Override
+    public void sendMessage(String what) {
+      rp.sendMessage(what);
+    }
+
+    @Override
+    public void sendError(String what) {
+      rp.sendError(what);
+    }
+
+    @Override
+    public void sendBytes(byte[] what) {
+      sendBytes(what, 0, what.length);
+    }
+
+    @Override
+    public void sendBytes(byte[] what, int off, int len) {
+      try {
+        rp.getMessageOutputStream().write(what, off, len);
+      } catch (IOException e) {
+        // Ignore write failures (matching JGit behavior).
+      }
+    }
+
+    @Override
+    public void flush() {
+      try {
+        rp.getMessageOutputStream().flush();
+      } catch (IOException e) {
+        // Ignore write failures (matching JGit behavior).
+      }
+    }
+  }
+
+  private static class Message {
+    private final String message;
+    private final boolean isError;
+
+    private Message(final String message, final boolean isError) {
+      this.message = message;
+      this.isError = isError;
+    }
+  }
+
   private final Set<Account.Id> reviewerId = new HashSet<Account.Id>();
   private final Set<Account.Id> ccId = new HashSet<Account.Id>();
 
@@ -132,13 +189,14 @@
   private final PersonIdent gerritIdent;
   private final TrackingFooters trackingFooters;
   private final TagCache tagCache;
+  private final WorkQueue workQueue;
+  private final RequestScopePropagator requestScopePropagator;
 
   private final ProjectControl projectControl;
   private final Project project;
   private final Repository repo;
   private final ReceivePack rp;
   private final NoteMap rejectCommits;
-
   private ReceiveCommand newChange;
   private Branch.NameKey destBranch;
   private RefControl destBranchCtl;
@@ -156,6 +214,13 @@
 
   private final SubmoduleOp.Factory subOpFactory;
 
+  private final List<Message> messages = new ArrayList<Message>();
+  private Task newProgress;
+  private Task replaceProgress;
+  private Task closeProgress;
+  private Task commandProgress;
+  private MessageSender messageSender;
+
   @Inject
   ReceiveCommits(final ReviewDb db, final ApprovalTypes approvalTypes,
       final AccountResolver accountResolver,
@@ -171,6 +236,8 @@
       @CanonicalWebUrl @Nullable final String canonicalWebUrl,
       @GerritPersonIdent final PersonIdent gerritIdent,
       final TrackingFooters trackingFooters,
+      final WorkQueue workQueue,
+      final RequestScopePropagator requestScopePropagator,
 
       @Assisted final ProjectControl projectControl,
       @Assisted final Repository repo,
@@ -191,6 +258,8 @@
     this.gerritIdent = gerritIdent;
     this.trackingFooters = trackingFooters;
     this.tagCache = tagCache;
+    this.workQueue = workQueue;
+    this.requestScopePropagator = requestScopePropagator;
 
     this.projectControl = projectControl;
     this.project = projectControl.getProject();
@@ -200,6 +269,8 @@
 
     this.subOpFactory = subOpFactory;
 
+    this.messageSender = new ReceivePackMessageSender();
+
     rp.setAllowCreates(true);
     rp.setAllowDeletes(true);
     rp.setAllowNonFastForwards(true);
@@ -207,12 +278,12 @@
 
     if (!projectControl.allRefsAreVisible()) {
       rp.setCheckReferencedObjectsAreReachable(true);
-      rp.setRefFilter(new VisibleRefFilter(tagCache, repo, projectControl, db, false));
+      rp.setAdvertiseRefsHook(new VisibleRefFilter(tagCache, repo, projectControl, db, false));
     }
-    rp.setRefFilter(new ReceiveCommitsRefFilter(rp.getRefFilter()));
-
-    rp.setPreReceiveHook(this);
-    rp.setPostReceiveHook(this);
+    List<AdvertiseRefsHook> advHooks = new ArrayList<AdvertiseRefsHook>(2);
+    advHooks.add(rp.getAdvertiseRefsHook());
+    advHooks.add(new ReceiveCommitsAdvertiseRefsHook());
+    rp.setAdvertiseRefsHook(AdvertiseRefsHookChain.newChain(advHooks));
   }
 
   /** Add reviewers for new (or updated) changes. */
@@ -225,6 +296,22 @@
     ccId.addAll(who);
   }
 
+  /** Set a message sender for this operation. */
+  public void setMessageSender(final MessageSender ms) {
+    messageSender = ms != null ? ms : new ReceivePackMessageSender();
+  }
+
+  MessageSender getMessageSender() {
+    if (messageSender == null) {
+      setMessageSender(null);
+    }
+    return messageSender;
+  }
+
+  Project getProject() {
+    return project;
+  }
+
   /** @return the ReceivePack instance to speak the native Git protocol. */
   public ReceivePack getReceivePack() {
     return rp;
@@ -314,20 +401,41 @@
     return MagicBranch.checkMagicBranchRefs(repo, project);
   }
 
-  @Override
-  public void onPreReceive(final ReceivePack arg0,
-      final Collection<ReceiveCommand> commands) {
+  private void addMessage(String message) {
+    messages.add(new Message(message, false));
+  }
+
+  void addError(String error) {
+    messages.add(new Message(error, true));
+  }
+
+  void sendMessages() {
+    for (Message m : messages) {
+      if (m.isError) {
+        messageSender.sendError(m.message);
+      } else {
+        messageSender.sendMessage(m.message);
+      }
+    }
+  }
+
+  void processCommands(final Collection<ReceiveCommand> commands,
+      final MultiProgressMonitor progress) {
+    newProgress = progress.beginSubTask("new", UNKNOWN);
+    replaceProgress = progress.beginSubTask("updated", UNKNOWN);
+    closeProgress = progress.beginSubTask("closed", UNKNOWN);
+    commandProgress = progress.beginSubTask("refs", UNKNOWN);
+
     parseCommands(commands);
     if (newChange != null
         && newChange.getResult() == ReceiveCommand.Result.NOT_ATTEMPTED) {
       createNewChanges();
     }
-    doReplaces();
-  }
+    newProgress.end();
 
-  @Override
-  public void onPostReceive(final ReceivePack arg0,
-      final Collection<ReceiveCommand> commands) {
+    doReplaces();
+    replaceProgress.end();
+
     for (final ReceiveCommand c : commands) {
       if (c.getResult() == Result.OK) {
         switch (c.getType()) {
@@ -368,23 +476,27 @@
           replication.scheduleUpdate(project.getNameKey(), c.getRefName());
           Branch.NameKey destBranch = new Branch.NameKey(project.getNameKey(), c.getRefName());
           hooks.doRefUpdatedHook(destBranch, c.getOldId(), c.getNewId(), currentUser.getAccount());
+          commandProgress.update(1);
         }
       }
     }
+    closeProgress.end();
+    commandProgress.end();
+    progress.end();
 
     if (!allNewChanges.isEmpty() && canonicalWebUrl != null) {
       final String url = canonicalWebUrl;
-      rp.sendMessage("");
-      rp.sendMessage("New Changes:");
+      addMessage("");
+      addMessage("New Changes:");
       for (final Change c : allNewChanges) {
         if (c.getStatus() == Change.Status.DRAFT) {
-          rp.sendMessage("  " + url + c.getChangeId() + " [DRAFT]");
+          addMessage("  " + url + c.getChangeId() + " [DRAFT]");
         }
         else {
-          rp.sendMessage("  " + url + c.getChangeId());
+          addMessage("  " + url + c.getChangeId());
         }
       }
-      rp.sendMessage("");
+      addMessage("");
     }
   }
 
@@ -448,7 +560,7 @@
           continue;
       }
 
-      if (cmd.getResult() != ReceiveCommand.Result.NOT_ATTEMPTED){
+      if (cmd.getResult() != ReceiveCommand.Result.NOT_ATTEMPTED) {
         continue;
       }
 
@@ -466,9 +578,9 @@
               ProjectConfig cfg = new ProjectConfig(project.getNameKey());
               cfg.load(repo, cmd.getNewId());
               if (!cfg.getValidationErrors().isEmpty()) {
-                rp.sendError("Invalid project configuration:");
+                addError("Invalid project configuration:");
                 for (ValidationError err : cfg.getValidationErrors()) {
-                  rp.sendError("  " + err.getMessage());
+                  addError("  " + err.getMessage());
                 }
                 reject(cmd, "invalid project configuration");
                 log.error("User " + currentUser.getUserName()
@@ -514,8 +626,7 @@
     RefControl ctl = projectControl.controlForRef(cmd.getRefName());
     if (ctl.canCreate(rp.getRevWalk(), obj)) {
       validateNewCommits(ctl, cmd);
-
-      // Let the core receive process handle it
+      cmd.execute(rp);
     } else {
       reject(cmd, "can not create new references");
     }
@@ -529,7 +640,7 @@
       }
 
       validateNewCommits(ctl, cmd);
-      // Let the core receive process handle it
+      cmd.execute(rp);
     } else {
       reject(cmd, "can not update the reference as a fast forward");
     }
@@ -557,7 +668,7 @@
   private void parseDelete(final ReceiveCommand cmd) {
     RefControl ctl = projectControl.controlForRef(cmd.getRefName());
     if (ctl.canDelete()) {
-      // Let the core receive process handle it
+      cmd.execute(rp);
     } else {
       reject(cmd, "can not delete references");
     }
@@ -585,7 +696,7 @@
     }
 
     if (ctl.canForceUpdate()) {
-      // Let the core receive process handle it
+      cmd.execute(rp);
     } else {
       cmd.setResult(ReceiveCommand.Result.REJECTED_NONFASTFORWARD, " need '"
           + PermissionRule.FORCE_PUSH + "' privilege.");
@@ -894,6 +1005,7 @@
         reject(newChange, "database error");
         return;
       }
+      newProgress.update(1);
     }
     newChange.setResult(ReceiveCommand.Result.OK);
   }
@@ -998,17 +1110,28 @@
 
     allNewChanges.add(change);
 
-    try {
-      final CreateChangeSender cm;
-      cm = createChangeSenderFactory.create(change);
-      cm.setFrom(me);
-      cm.setPatchSet(ps, info);
-      cm.addReviewers(reviewers);
-      cm.addExtraCC(cc);
-      cm.send();
-    } catch (EmailException e) {
-      log.error("Cannot send email for new change " + change.getId(), e);
-    }
+    workQueue.getDefaultQueue()
+        .submit(requestScopePropagator.wrap(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          final CreateChangeSender cm;
+          cm = createChangeSenderFactory.create(change);
+          cm.setFrom(me);
+          cm.setPatchSet(ps, info);
+          cm.addReviewers(reviewers);
+          cm.addExtraCC(cc);
+          cm.send();
+        } catch (EmailException e) {
+          log.error("Cannot send email for new change " + change.getId(), e);
+        }
+      }
+
+      @Override
+      public String toString() {
+        return "send-email newchange";
+      }
+    }));
 
     hooks.doPatchsetCreatedHook(change, ps, db);
   }
@@ -1023,7 +1146,8 @@
   private void doReplaces() {
     for (final ReplaceRequest request : replaceByChange.values()) {
       try {
-        doReplace(request);
+        doReplace(request, false);
+        replaceProgress.update(1);
       } catch (IOException err) {
         log.error("Error computing replacement patch for change "
             + request.ontoChange + ", commit " + request.newCommit.name(), err);
@@ -1042,7 +1166,7 @@
     }
   }
 
-  private PatchSet.Id doReplace(final ReplaceRequest request)
+  private PatchSet.Id doReplace(final ReplaceRequest request, boolean ignoreNoChanges)
       throws IOException, OrmException {
     final RevCommit c = request.newCommit;
     rp.getRevWalk().parseBody(c);
@@ -1138,7 +1262,7 @@
           final boolean parentsEq = parentsEqual(c, prior);
           final boolean authorEq = authorEqual(c, prior);
 
-          if (messageEq && parentsEq && authorEq) {
+          if (messageEq && parentsEq && authorEq && !ignoreNoChanges) {
             reject(request.cmd, "no changes made");
             return null;
           } else {
@@ -1157,7 +1281,7 @@
             if (!parentsEq) {
               msg.append(", was rebased");
             }
-            rp.sendMessage(msg.toString());
+            addMessage(msg.toString());
           }
         }
       } catch (IOException e) {
@@ -1334,20 +1458,31 @@
     hooks.doPatchsetCreatedHook(result.change, ps, db);
     request.cmd.setResult(ReceiveCommand.Result.OK);
 
-    try {
-      final ReplacePatchSetSender cm;
-      cm = replacePatchSetFactory.create(result.change);
-      cm.setFrom(me);
-      cm.setPatchSet(ps, result.info);
-      cm.setChangeMessage(result.msg);
-      cm.addReviewers(reviewers);
-      cm.addExtraCC(cc);
-      cm.addReviewers(oldReviewers);
-      cm.addExtraCC(oldCC);
-      cm.send();
-    } catch (EmailException e) {
-      log.error("Cannot send email for new patch set " + ps.getId(), e);
-    }
+    workQueue.getDefaultQueue()
+        .submit(requestScopePropagator.wrap(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          final ReplacePatchSetSender cm;
+          cm = replacePatchSetFactory.create(result.change);
+          cm.setFrom(me);
+          cm.setPatchSet(ps, result.info);
+          cm.setChangeMessage(result.msg);
+          cm.addReviewers(reviewers);
+          cm.addExtraCC(cc);
+          cm.addReviewers(oldReviewers);
+          cm.addExtraCC(oldCC);
+          cm.send();
+        } catch (EmailException e) {
+          log.error("Cannot send email for new patch set " + ps.getId(), e);
+        }
+      }
+
+      @Override
+      public String toString() {
+        return "send-email newpatchset";
+      }
+    }));
 
     sendMergedEmail(result);
     return result != null ? result.info.getKey() : null;
@@ -1562,7 +1697,7 @@
         if (project.isRequireChangeID()) {
           String errMsg = "missing Change-Id in commit message";
           reject(cmd, errMsg);
-          rp.sendMessage(getFixedCommitMsgWithChangeId(errMsg, c));
+          addMessage(getFixedCommitMsgWithChangeId(errMsg, c));
           return false;
         }
       } else if (idList.size() > 1) {
@@ -1574,7 +1709,7 @@
           final String errMsg =
               "missing or invalid Change-Id line format in commit message";
           reject(cmd, errMsg);
-          rp.sendMessage(getFixedCommitMsgWithChangeId(errMsg, c));
+          addMessage(getFixedCommitMsgWithChangeId(errMsg, c));
           return false;
         }
       }
@@ -1592,9 +1727,9 @@
         ProjectConfig cfg = new ProjectConfig(project.getNameKey());
         cfg.load(repo, cmd.getNewId());
         if (!cfg.getValidationErrors().isEmpty()) {
-          rp.sendError("Invalid project configuration:");
+          addError("Invalid project configuration:");
           for (ValidationError err : cfg.getValidationErrors()) {
-            rp.sendError("  " + err.getMessage());
+            addError("  " + err.getMessage());
           }
           reject(cmd, "invalid project configuration");
           log.error("User " + currentUser.getUserName()
@@ -1673,7 +1808,7 @@
       sb.append("ERROR:  " + canonicalWebUrl + "#" + PageLinks.SETTINGS_CONTACT + "\n");
     }
     sb.append("\n");
-    getReceivePack().sendMessage(sb.toString());
+    addMessage(sb.toString());
   }
 
   private void warnMalformedMessage(RevCommit c) {
@@ -1685,7 +1820,7 @@
       } catch (IOException err) {
         id = c.abbreviate(6);
       }
-      rp.sendMessage("(W) " + id.name() //
+      addMessage("(W) " + id.name() //
           + ": commit subject >65 characters; use shorter first paragraph");
     }
 
@@ -1706,7 +1841,7 @@
       } catch (IOException err) {
         id = c.abbreviate(6);
       }
-      rp.sendMessage("(W) " + id.name() //
+      addMessage("(W) " + id.name() //
           + ": commit message lines >70 characters; manually wrap lines");
     }
   }
@@ -1730,7 +1865,7 @@
         if (ref != null) {
           rw.parseBody(c);
           closeChange(cmd, PatchSet.Id.fromRef(ref.getName()), c);
-          continue;
+          closeProgress.update(1);
         }
 
         rw.parseBody(c);
@@ -1744,9 +1879,10 @@
       }
 
       for (final ReplaceRequest req : toClose) {
-        final PatchSet.Id psi = doReplace(req);
+        final PatchSet.Id psi = doReplace(req, true);
         if (psi != null) {
           closeChange(req.cmd, psi, req.newCommit);
+          closeProgress.update(1);
         }
       }
 
@@ -1867,15 +2003,26 @@
 
   private void sendMergedEmail(final ReplaceResult result) {
     if (result != null && result.mergedIntoRef != null) {
-      try {
-        final MergedSender cm = mergedSenderFactory.create(result.change);
-        cm.setFrom(currentUser.getAccountId());
-        cm.setPatchSet(result.patchSet, result.info);
-        cm.send();
-      } catch (EmailException e) {
-        final PatchSet.Id psi = result.patchSet.getId();
-        log.error("Cannot send email for submitted patch set " + psi, e);
-      }
+      workQueue.getDefaultQueue()
+          .submit(requestScopePropagator.wrap(new Runnable() {
+        @Override
+        public void run() {
+          try {
+            final MergedSender cm = mergedSenderFactory.create(result.change);
+            cm.setFrom(currentUser.getAccountId());
+            cm.setPatchSet(result.patchSet, result.info);
+            cm.send();
+          } catch (EmailException e) {
+            final PatchSet.Id psi = result.patchSet.getId();
+            log.error("Cannot send email for submitted patch set " + psi, e);
+          }
+        }
+
+        @Override
+        public String toString() {
+          return "send-email merged";
+        }
+      }));
 
       try {
         hooks.doChangeMergedHook(result.change, currentUser.getAccount(),
@@ -1904,12 +2051,13 @@
     return new RevId(src.getId().name());
   }
 
-  private static void reject(final ReceiveCommand cmd) {
+  private void reject(final ReceiveCommand cmd) {
     reject(cmd, "prohibited by Gerrit");
   }
 
-  private static void reject(final ReceiveCommand cmd, final String why) {
+  private void reject(final ReceiveCommand cmd, final String why) {
     cmd.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, why);
+    commandProgress.update(1);
   }
 
   private static boolean isHead(final Ref ref) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java
new file mode 100644
index 0000000..e87fe2b
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsAdvertiseRefsHook.java
@@ -0,0 +1,47 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.AdvertiseRefsHook;
+import org.eclipse.jgit.transport.ReceivePack;
+import org.eclipse.jgit.transport.UploadPack;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Exposes only the non refs/changes/ reference names. */
+public class ReceiveCommitsAdvertiseRefsHook implements AdvertiseRefsHook {
+  @Override
+  public void advertiseRefs(UploadPack us) {
+    throw new UnsupportedOperationException(
+        "ReceiveCommitsAdvertiseRefsHook cannot be used for UploadPack");
+  }
+
+  @Override
+  public void advertiseRefs(ReceivePack rp) {
+    Map<String, Ref> oldRefs = rp.getAdvertisedRefs();
+    if (oldRefs == null) {
+      oldRefs = rp.getRepository().getAllRefs();
+    }
+    HashMap<String, Ref> r = new HashMap<String, Ref>();
+    for (Map.Entry<String, Ref> e : oldRefs.entrySet()) {
+      if (!e.getKey().startsWith("refs/changes/")) {
+        r.put(e.getKey(), e.getValue());
+      }
+    }
+    rp.setAdvertisedRefs(r, rp.getAdvertisedObjects());
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutor.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutor.java
new file mode 100644
index 0000000..2049cea
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutor.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Retention;
+
+/**
+ * Marker on the global {@link WorkQueue.Executor} used by
+ * {@link ReceiveCommits}.
+ */
+@Retention(RUNTIME)
+@BindingAnnotation
+public @interface ReceiveCommitsExecutor {
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java
new file mode 100644
index 0000000..063db2d
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsExecutorModule.java
@@ -0,0 +1,41 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.git.WorkQueue;
+import com.google.gerrit.server.git.WorkQueue.Executor;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.lib.Config;
+
+/** Module providing the {@link ReceiveCommitsExecutor}. */
+public class ReceiveCommitsExecutorModule extends AbstractModule {
+  @Override
+  protected void configure() {
+  }
+
+  @Provides
+  @Singleton
+  @ReceiveCommitsExecutor
+  public Executor getReceiveCommitsExecutor(@GerritServerConfig Config config,
+      WorkQueue queues) {
+    int poolSize = config.getInt("receive", null, "threadPoolSize",
+        Runtime.getRuntime().availableProcessors());
+    return queues.createQueue(poolSize, "ReceiveCommits");
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsRefFilter.java
deleted file mode 100644
index 730305c..0000000
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommitsRefFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2010 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.git;
-
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.transport.RefFilter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** Exposes only the non refs/changes/ reference names. */
-class ReceiveCommitsRefFilter implements RefFilter {
-  private final RefFilter base;
-
-  public ReceiveCommitsRefFilter(RefFilter base) {
-    this.base = base != null ? base : RefFilter.DEFAULT;
-  }
-
-  @Override
-  public Map<String, Ref> filter(Map<String, Ref> refs) {
-    HashMap<String, Ref> r = new HashMap<String, Ref>();
-    for (Map.Entry<String, Ref> e : refs.entrySet()) {
-      if (!e.getKey().startsWith("refs/changes/")) {
-        r.put(e.getKey(), e.getValue());
-      }
-    }
-    return base.filter(r);
-  }
-}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReloadSubmitQueueOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReloadSubmitQueueOp.java
index 356981d..bcc2107 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReloadSubmitQueueOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReloadSubmitQueueOp.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 
 import org.slf4j.Logger;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
index cedcb0b..f5e8fa8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
@@ -15,9 +15,9 @@
 package com.google.gerrit.server.git;
 
 import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.NameKey;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplicationQueue.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplicationQueue.java
index d1c518d..f7bb9f8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplicationQueue.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplicationQueue.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Manages replication to other nodes. */
 public interface ReplicationQueue {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/RepositoryCaseMismatchException.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/RepositoryCaseMismatchException.java
index 3c90798..64ba6e8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/RepositoryCaseMismatchException.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/RepositoryCaseMismatchException.java
@@ -14,7 +14,8 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
 
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java
index 39ae9b3..7b669b2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java
index a7a43b1..706ba7d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/SubmoduleOp.java
@@ -14,16 +14,16 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.util.SubmoduleSectionParser;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
@@ -31,8 +31,8 @@
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheBuilder;
 import org.eclipse.jgit.dircache.DirCacheEditor;
-import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
+import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagCache.java
index 053fda8..ac4882f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java
index cfa5420..8830580 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSet.java
@@ -17,8 +17,8 @@
 import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
 
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
 
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.lib.AnyObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSetHolder.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSetHolder.java
index c6667c5..91c8a5c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSetHolder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/TagSetHolder.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
index 655daa3..c34cc54 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
@@ -17,9 +17,9 @@
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheBuilder;
 import org.eclipse.jgit.dircache.DirCacheEditor;
-import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
+import org.eclipse.jgit.dircache.DirCacheEntry;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
index feadaf1..fc47f10 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
@@ -14,17 +14,18 @@
 
 package com.google.gerrit.server.git;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.transport.RefFilter;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.AbstractAdvertiseRefsHook;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,7 +37,7 @@
 import java.util.Map;
 import java.util.Set;
 
-public class VisibleRefFilter implements RefFilter {
+public class VisibleRefFilter extends AbstractAdvertiseRefsHook {
   private static final Logger log =
       LoggerFactory.getLogger(VisibleRefFilter.class);
 
@@ -58,11 +59,6 @@
     this.showChanges = showChanges;
   }
 
-  @Override
-  public Map<String, Ref> filter(Map<String, Ref> refs) {
-    return filter(refs, false);
-  }
-
   public Map<String, Ref> filter(Map<String, Ref> refs, boolean filterTagsSeperately) {
     final Set<Change.Id> visibleChanges = visibleChanges();
     final Map<String, Ref> result = new HashMap<String, Ref>();
@@ -108,6 +104,16 @@
     return result;
   }
 
+  @Override
+  protected Map<String, Ref> getAdvertisedRefs(
+      Repository repository, RevWalk revWalk) {
+    return filter(repository.getAllRefs());
+  }
+
+  private Map<String, Ref> filter(Map<String, Ref> refs) {
+    return filter(refs, false);
+  }
+
   private Set<Change.Id> visibleChanges() {
     if (!showChanges) {
       return Collections.emptySet();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
index 87e6880..987ab7c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/WorkQueue.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.lifecycle.LifecycleListener;
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.Project.NameKey;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.server.util.IdGenerator;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ioutil/BasicSerialization.java b/gerrit-server/src/main/java/com/google/gerrit/server/ioutil/BasicSerialization.java
index 2971906..4210363 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ioutil/BasicSerialization.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ioutil/BasicSerialization.java
@@ -29,7 +29,7 @@
 
 package com.google.gerrit.server.ioutil;
 
-import com.google.gerrit.reviewdb.CodedEnum;
+import com.google.gerrit.reviewdb.client.CodedEnum;
 
 import org.eclipse.jgit.util.IO;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java
index ac62bd0..7fabcfe1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java
index 02f8fb7..f7ace27 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.ssh.SshInfo;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
index 822bd51..ff0bb578 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
@@ -14,17 +14,17 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.StarredChange;
-import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.StarredChange;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListEntry;
@@ -34,7 +34,7 @@
 import com.google.gerrit.server.query.QueryParseException;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.ChangeQueryBuilder;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -70,14 +70,7 @@
 
     /** Is the from user in an email squelching group? */
     final IdentifiedUser user =  args.identifiedUserFactory.create(id);
-    final Set<AccountGroup.UUID> gids = user.getEffectiveGroups();
-    for (final AccountGroup.UUID gid : gids) {
-      AccountGroup group = args.groupCache.get(gid);
-      if (group != null && group.isEmailOnlyAuthors()) {
-        emailOnlyAuthors = true;
-        break;
-      }
-    }
+    emailOnlyAuthors = !user.getCapabilities().canEmailReviewers();
   }
 
   public void setPatchSet(final PatchSet ps) {
@@ -296,7 +289,7 @@
       //
       for (StarredChange w : args.db.get().starredChanges().byChange(
           change.getId())) {
-        add(RecipientType.BCC, w.getAccountId());
+        super.add(RecipientType.BCC, w.getAccountId());
       }
     } catch (OrmException err) {
       // Just don't BCC everyone. Better to send a partial message to those
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
index e887221..f054ee8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.patch.PatchFile;
 import com.google.gerrit.server.patch.PatchList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
index dabb6f3..c6f716d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java
@@ -14,16 +14,16 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.ssh.SshInfo;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
index 15f6846..68f78d0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.IdentifiedUser.GenericFactory;
 import com.google.gerrit.server.account.AccountCache;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailHeader.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailHeader.java
index 16f9062..ce8c8f9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailHeader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailHeader.java
@@ -19,8 +19,8 @@
 import java.io.Writer;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
index 374ae34..4307854 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailTokenVerifier.java
@@ -1,8 +1,20 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.account.AuthRequest;
 
 /** Verifies the token sent by {@link RegisterNewEmailSender}. */
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGenerator.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGenerator.java
index aa948f1..dec3d2c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGenerator.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGenerator.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 
 /** Constructs an address to send email from. */
 public interface FromAddressGenerator {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
index 0abf96f..bb50374 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.server.mail;
 
 import com.google.gerrit.common.data.ParameterizedString;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.config.AnonymousCowardName;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java
index f11b7c4..b695fb4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
index 54efb02..3590b8a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
@@ -16,15 +16,15 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
 import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
index fb9ba60..2e459d4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.ssh.SshInfo;
 
 import com.jcraft.jsch.HostKey;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
index d208c84..de8628f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.UserIdentity;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.mail.EmailHeader.AddressList;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.velocity.Template;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RebasedPatchSetSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RebasedPatchSetSender.java
new file mode 100644
index 0000000..8fc8238
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RebasedPatchSetSender.java
@@ -0,0 +1,40 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.mail;
+
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.server.config.AnonymousCowardName;
+import com.google.gerrit.server.ssh.SshInfo;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+/** Send notice to reviewers that a change has been rebased. */
+public class RebasedPatchSetSender extends ReplacePatchSetSender {
+  public static interface Factory {
+    RebasedPatchSetSender create(Change change);
+  }
+
+  @Inject
+  public RebasedPatchSetSender(EmailArguments ea,
+      @AnonymousCowardName String anonymousCowardName, SshInfo si,
+      @Assisted Change c) {
+    super(ea, anonymousCowardName, si, c);
+  }
+
+  @Override
+  protected void formatChange() throws EmailException {
+    appendText(velocifyFile("RebasedPatchSet.vm"));
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
index b09cb27..9705b8a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.ssh.SshInfo;
 import com.google.inject.Inject;
@@ -67,6 +67,7 @@
     add(RecipientType.TO, reviewers);
     add(RecipientType.CC, extraCC);
     rcptToAuthors(RecipientType.CC);
+    bccStarredBy();
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java
index 6b0ed4d..2a77d39 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 /** Alert a user to a reply to a change, usually commentary made during review. */
 public abstract class ReplyToChangeSender extends ChangeEmail {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RestoredSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RestoredSender.java
index b9df397..c9afdde 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RestoredSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RestoredSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RevertedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RevertedSender.java
index e6f88ea..964bfed 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RevertedSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RevertedSender.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
index aad2f76..4d6eb8e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/SignedTokenEmailTokenVerifier.java
@@ -1,8 +1,20 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
 package com.google.gerrit.server.mail;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gwtjsonrpc.server.SignedToken;
 import com.google.gwtjsonrpc.server.ValidToken;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/AddReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/AddReviewer.java
index 9fdc899..df93852 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/AddReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/AddReviewer.java
@@ -18,13 +18,13 @@
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.ReviewerResult;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.GroupCache;
@@ -32,7 +32,7 @@
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.mail.AddReviewerSender;
 import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiff.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiff.java
index 3805f8f..46def59 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiff.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiff.java
@@ -19,7 +19,7 @@
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeEnum;
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeVarInt32;
 
-import com.google.gerrit.reviewdb.CodedEnum;
+import com.google.gerrit.reviewdb.client.CodedEnum;
 
 import org.eclipse.jgit.diff.Edit;
 import org.eclipse.jgit.diff.ReplaceEdit;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiffKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiffKey.java
index a8d62fc..c5c5925 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiffKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineDiffKey.java
@@ -17,7 +17,7 @@
 import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import org.eclipse.jgit.diff.Edit;
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java
index 4feccd0..f120ebf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchFile.java
@@ -16,7 +16,7 @@
 
 import com.google.gerrit.common.errors.CorruptEntityException;
 import com.google.gerrit.common.errors.NoSuchEntityException;
-import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.client.Patch;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchList.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchList.java
index 7194a22..aab8e39 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchList.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchList.java
@@ -24,8 +24,8 @@
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeCanBeNull;
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
 
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCache.java
index a7cf10a..8a61d30 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCache.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.patch;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
 
 /** Provides a cached list of {@link PatchListEntry}. */
 public interface PatchListCache {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
index e1a0a40..26dbe2d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListCacheImpl.java
@@ -16,10 +16,10 @@
 package com.google.gerrit.server.patch;
 
 
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EvictionPolicy;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListEntry.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListEntry.java
index 837ec9c..33ed54e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListEntry.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListEntry.java
@@ -23,10 +23,10 @@
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeString;
 import static com.google.gerrit.server.ioutil.BasicSerialization.writeVarInt32;
 
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Patch.ChangeType;
-import com.google.gerrit.reviewdb.Patch.PatchType;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
+import com.google.gerrit.reviewdb.client.Patch.PatchType;
 
 import org.eclipse.jgit.diff.Edit;
 import org.eclipse.jgit.lib.Constants;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
index 18fa5b0..de12cc6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
@@ -21,8 +21,8 @@
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeCanBeNull;
 import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index 0bb4bcc..5bba42b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -15,8 +15,8 @@
 
 package com.google.gerrit.server.patch;
 
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 import com.google.gerrit.server.cache.EntryCreator;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
index 0c70eac..f59dcc3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
@@ -14,17 +14,17 @@
 
 package com.google.gerrit.server.patch;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.client.UserIdentity;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountByEmailCache;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PublishComments.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PublishComments.java
index 039e0f6..17c690f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PublishComments.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PublishComments.java
@@ -17,24 +17,28 @@
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.mail.CommentSender;
 import com.google.gerrit.server.mail.EmailException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.gerrit.server.workflow.FunctionState;
-import com.google.gwtjsonrpc.client.VoidResult;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtjsonrpc.common.VoidResult;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -60,6 +64,7 @@
         Set<ApprovalCategoryValue.Id> approvals, boolean forceMessage);
   }
 
+  private final SchemaFactory<ReviewDb> schemaFactory;
   private final ReviewDb db;
   private final IdentifiedUser user;
   private final ApprovalTypes types;
@@ -68,6 +73,8 @@
   private final ChangeControl.Factory changeControlFactory;
   private final FunctionState.Factory functionStateFactory;
   private final ChangeHooks hooks;
+  private final WorkQueue workQueue;
+  private final RequestScopePropagator requestScopePropagator;
 
   private final PatchSet.Id patchSetId;
   private final String messageText;
@@ -80,18 +87,22 @@
   private List<PatchLineComment> drafts;
 
   @Inject
-  PublishComments(final ReviewDb db, final IdentifiedUser user,
+  PublishComments(final SchemaFactory<ReviewDb> sf, final ReviewDb db,
+      final IdentifiedUser user,
       final ApprovalTypes approvalTypes,
       final CommentSender.Factory commentSenderFactory,
       final PatchSetInfoFactory patchSetInfoFactory,
       final ChangeControl.Factory changeControlFactory,
       final FunctionState.Factory functionStateFactory,
       final ChangeHooks hooks,
+      final WorkQueue workQueue,
+      final RequestScopePropagator requestScopePropagator,
 
       @Assisted final PatchSet.Id patchSetId,
       @Assisted final String messageText,
       @Assisted final Set<ApprovalCategoryValue.Id> approvals,
       @Assisted final boolean forceMessage) {
+    this.schemaFactory = sf;
     this.db = db;
     this.user = user;
     this.types = approvalTypes;
@@ -100,6 +111,8 @@
     this.changeControlFactory = changeControlFactory;
     this.functionStateFactory = functionStateFactory;
     this.hooks = hooks;
+    this.workQueue = workQueue;
+    this.requestScopePropagator = requestScopePropagator;
 
     this.patchSetId = patchSetId;
     this.messageText = messageText;
@@ -151,7 +164,8 @@
     db.patchComments().update(drafts);
   }
 
-  private void publishApprovals(ChangeControl ctl) throws OrmException {
+  private void publishApprovals(ChangeControl ctl)
+      throws InvalidChangeOperationException, OrmException {
     ChangeUtil.updated(change);
 
     final Set<ApprovalCategory.Id> dirty = new HashSet<ApprovalCategory.Id>();
@@ -188,6 +202,11 @@
       if (!ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
         functionState.normalize(types.byId(a.getCategoryId()), a);
       }
+      if (want.get() != a.getValue()) {
+        throw new InvalidChangeOperationException(
+            types.byId(a.getCategoryId()).getCategory().getLabelName()
+            + "=" + want.get() + " not permitted");
+      }
       if (o != a.getValue()) {
         // Value changed, ensure we update the database.
         //
@@ -294,20 +313,47 @@
   }
 
   private void email() {
-    try {
-      if (message != null) {
-        final CommentSender cm = commentSenderFactory.create(change);
-        cm.setFrom(user.getAccountId());
-        cm.setPatchSet(patchSet, patchSetInfoFactory.get(db, patchSetId));
-        cm.setChangeMessage(message);
-        cm.setPatchLineComments(drafts);
-        cm.send();
-      }
-    } catch (EmailException e) {
-      log.error("Cannot send comments by email for patch set " + patchSetId, e);
-    } catch (PatchSetInfoNotAvailableException e) {
-      log.error("Failed to obtain PatchSetInfo for patch set " + patchSetId, e);
+    if (message == null) {
+      return;
     }
+
+    workQueue.getDefaultQueue()
+        .submit(requestScopePropagator.wrap(new Runnable() {
+      @Override
+      public void run() {
+        PatchSetInfo patchSetInfo;
+        try {
+          ReviewDb reviewDb = schemaFactory.open();
+          try {
+            patchSetInfo = patchSetInfoFactory.get(reviewDb, patchSetId);
+          } finally {
+            reviewDb.close();
+          }
+        } catch (PatchSetInfoNotAvailableException e) {
+          log.error("Cannot read PatchSetInfo of " + patchSetId, e);
+          return;
+        } catch (OrmException e) {
+          log.error("Cannot email comments for " + patchSetId, e);
+          return;
+        }
+
+        try {
+          final CommentSender cm = commentSenderFactory.create(change);
+          cm.setFrom(user.getAccountId());
+          cm.setPatchSet(patchSet, patchSetInfo);
+          cm.setChangeMessage(message);
+          cm.setPatchLineComments(drafts);
+          cm.send();
+        } catch (EmailException e) {
+          log.error("Cannot email comments for " + patchSetId, e);
+        }
+      }
+
+      @Override
+      public String toString() {
+        return "send-email comments";
+      }
+    }));
   }
 
   private void fireHook() throws OrmException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/RemoveReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/RemoveReviewer.java
index 884cb54..af9bb8c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/RemoveReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/RemoveReviewer.java
@@ -16,14 +16,14 @@
 package com.google.gerrit.server.patch;
 
 import com.google.gerrit.common.data.ReviewerResult;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.project.ChangeControl;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java
index 09a2a91..3b1191c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java
@@ -16,7 +16,7 @@
 
 import static com.google.inject.Scopes.SINGLETON;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.config.GitReceivePackGroups;
 import com.google.gerrit.server.config.GitReceivePackGroupsProvider;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
index 073372c..1a50030 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ChangeControl.java
@@ -16,18 +16,18 @@
 
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.rules.PrologEnvironment;
 import com.google.gerrit.rules.StoredValues;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -199,6 +199,11 @@
     return isOwner() && isVisible(db);
   }
 
+  /** Can this user rebase this change? */
+  public boolean canRebase() {
+    return canAddPatchSet();
+  }
+
   /** Can this user restore this change? */
   public boolean canRestore() {
     return canAbandon(); // Anyone who can abandon the change can restore it back
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
index c60a8d4..65bdc1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
@@ -19,9 +19,9 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.errors.ProjectCreationFailedException;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.GroupCache;
@@ -30,6 +30,7 @@
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.ProjectConfig;
 import com.google.gerrit.server.git.ReplicationQueue;
+import com.google.gerrit.server.git.RepositoryCaseMismatchException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -41,8 +42,8 @@
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,9 +51,6 @@
 import java.util.ArrayList;
 import java.util.Set;
 
-import com.google.gerrit.server.git.RepositoryCaseMismatchException;
-import com.google.gerrit.server.project.ProjectCache;
-
 
 /** Common class that holds the code to create projects */
 public class CreateProject {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
index 63e358f..98adf85 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.SubmitType;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
 
 import java.util.List;
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
similarity index 79%
rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
index 9aafc0e..95a8b77 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
@@ -12,18 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.sshd.commands;
+package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.ProjectControl;
-import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.sshd.BaseCommand;
+import com.google.gerrit.server.util.TreeFormatter;
 import com.google.inject.Inject;
 
-import org.apache.sshd.server.Environment;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.Ref;
@@ -32,18 +28,23 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.BufferedWriter;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
 
-final class ListProjects extends BaseCommand {
+/** List projects visible to the calling user. */
+public class ListProjects {
   private static final Logger log = LoggerFactory.getLogger(ListProjects.class);
 
-  static enum FilterType {
+  public static enum FilterType {
     CODE {
       @Override
       boolean matches(Repository git) throws IOException {
@@ -69,24 +70,18 @@
     abstract boolean matches(Repository git) throws IOException;
   }
 
-  @Inject
-  private IdentifiedUser currentUser;
-
-  @Inject
-  private ProjectCache projectCache;
-
-  @Inject
-  private GitRepositoryManager repoManager;
-
-  @Inject
-  private ProjectNode.Factory projectNodeFactory;
+  private final CurrentUser currentUser;
+  private final ProjectCache projectCache;
+  private final GitRepositoryManager repoManager;
+  private final ProjectNode.Factory projectNodeFactory;
 
   @Option(name = "--show-branch", aliases = {"-b"}, multiValued = true,
       usage = "displays the sha of each project in the specified branch")
   private List<String> showBranch;
 
-  @Option(name = "--tree", aliases = {"-t"}, usage = "displays project inheritance in a tree-like format\n" +
-      "this option does not work together with the show-branch option")
+  @Option(name = "--tree", aliases = {"-t"}, usage =
+      "displays project inheritance in a tree-like format\n"
+      + "this option does not work together with the show-branch option")
   private boolean showTree;
 
   @Option(name = "--type", usage = "type of project")
@@ -98,27 +93,37 @@
   @Option(name = "--all", usage = "display all projects that are accessible by the calling user")
   private boolean all;
 
-  @Override
-  public void start(final Environment env) {
-    startThread(new CommandRunnable() {
-      @Override
-      public void run() throws Exception {
-        parseCommandLine();
-        ListProjects.this.display();
-      }
-    });
+  @Inject
+  protected ListProjects(CurrentUser currentUser, ProjectCache projectCache,
+      GitRepositoryManager repoManager,
+      ProjectNode.Factory projectNodeFactory) {
+    this.currentUser = currentUser;
+    this.projectCache = projectCache;
+    this.repoManager = repoManager;
+    this.projectNodeFactory = projectNodeFactory;
   }
 
-  private void display() throws Failure {
-    if (showTree && (showBranch != null)) {
-      throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible.");
+  public List<String> getShowBranch() {
+    return showBranch;
+  }
+
+  public boolean isShowTree() {
+    return showTree;
+  }
+
+  public boolean isShowDescription() {
+    return showDescription;
+  }
+
+  public void display(OutputStream out) {
+    final PrintWriter stdout;
+    try {
+      stdout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8")));
+    } catch (UnsupportedEncodingException e) {
+      // Our encoding is required by the specifications for the runtime.
+      throw new RuntimeException("JVM lacks UTF-8 encoding", e);
     }
 
-    if (showTree && showDescription) {
-      throw new UnloggedFailure(1, "fatal: --tree and --description options are not compatible.");
-    }
-
-    final PrintWriter stdout = toPrintWriter(out);
     final TreeMap<Project.NameKey, ProjectNode> treeMap =
         new TreeMap<Project.NameKey, ProjectNode>();
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchChangeException.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchChangeException.java
index d5a22fd..f766c7f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchChangeException.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchChangeException.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 
 /** Indicates the change does not exist. */
 public class NoSuchChangeException extends Exception {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchProjectException.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchProjectException.java
index a1448d5..2ac494d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchProjectException.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/NoSuchProjectException.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Indicates the project does not exist. */
 public class NoSuchProjectException extends Exception {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerRequestProjectControlCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerRequestProjectControlCache.java
index 1a96381..19a42ae 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerRequestProjectControlCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerRequestProjectControlCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.inject.Inject;
 import com.google.inject.servlet.RequestScoped;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java
index 02f56c5..e416ed7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PermissionCollection.java
@@ -19,7 +19,7 @@
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCache.java
index cff554c..70f4013 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCache.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 /** Cache of project information, including access rights. */
 public interface ProjectCache {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index 7a7f56e..51d8fb2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
index d08f8e3..29a6432 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
@@ -20,15 +20,15 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AbstractAgreement;
-import com.google.gerrit.reviewdb.AccountAgreement;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupAgreement;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ContributorAgreement;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AbstractAgreement;
+import com.google.gerrit.reviewdb.client.AccountAgreement;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupAgreement;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ContributorAgreement;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.ReplicationUser;
@@ -36,8 +36,8 @@
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.config.GitReceivePackGroups;
 import com.google.gerrit.server.config.GitUploadPackGroups;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
@@ -281,7 +281,7 @@
     ContributorAgreement bestCla = null;
     try {
 
-      OUTER: for (AccountGroup.UUID groupUUID : iUser.getEffectiveGroups()) {
+      OUTER: for (AccountGroup.UUID groupUUID : iUser.getEffectiveGroups().getKnownGroups()) {
         AccountGroup group = groupCache.get(groupUUID);
         if (group == null) {
           continue;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java
similarity index 83%
rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java
index 8e12571..1c4d7c4 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ProjectNode.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectNode.java
@@ -12,32 +12,31 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.sshd.commands;
+package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.sshd.commands.TreeFormatter.TreeNode;
+import com.google.gerrit.server.util.TreeFormatter.TreeNode;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+/** Node of a Project in a tree formatted by {@link ListProjects}. */
 public class ProjectNode implements TreeNode, Comparable<ProjectNode> {
-
   public interface Factory {
     ProjectNode create(final Project project, final boolean isVisible);
   }
 
   private final AllProjectsName allProjectsName;
-
   private final Project project;
   private final boolean isVisible;
 
   private final SortedSet<ProjectNode> children = new TreeSet<ProjectNode>();
 
   @Inject
-  public ProjectNode(final AllProjectsName allProjectsName,
+  protected ProjectNode(final AllProjectsName allProjectsName,
       @Assisted final Project project, @Assisted final boolean isVisible) {
     this.allProjectsName = allProjectsName;
     this.project = project;
@@ -51,15 +50,7 @@
    *         project
    */
   public Project.NameKey getParentName() {
-    if (project.getParent() != null) {
-      return project.getParent();
-    }
-
-    if (project.getNameKey().equals(allProjectsName)) {
-      return null;
-    }
-
-    return allProjectsName;
+    return project.getParent(allProjectsName);
   }
 
   public boolean isAllProjects() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
index 9f6f6e7..6b4780a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -19,12 +19,13 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.rules.PrologEnvironment;
 import com.google.gerrit.rules.RulesCache;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.CapabilityCollection;
+import com.google.gerrit.server.account.GroupMembership;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ProjectConfig;
@@ -237,13 +238,13 @@
    * @return true if any of the groups listed in {@code groups} was declared to
    *         be an owner of this project, or one of its parent projects..
    */
-  boolean isOwner(Set<AccountGroup.UUID> groups) {
+  boolean isOwner(GroupMembership groups) {
     Set<Project.NameKey> seen = new HashSet<Project.NameKey>();
     seen.add(getProject().getNameKey());
 
     ProjectState s = this;
     do {
-      if (CollectionsUtil.isAnyIncludedIn(s.localOwners, groups)) {
+      if (groups.containsAnyOf(s.localOwners)) {
         return true;
       }
 
@@ -269,10 +270,6 @@
     if (isAllProjects) {
       return null;
     }
-    Project.NameKey parentName = getProject().getParent();
-    if (parentName == null) {
-      parentName = allProjectsName;
-    }
-    return projectCache.get(parentName);
+    return projectCache.get(getProject().getParent(allProjectsName));
   }
 }
\ No newline at end of file
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index e1341da..a865603 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -18,7 +18,9 @@
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.common.errors.InvalidNameException;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
@@ -26,6 +28,7 @@
 import dk.brics.automaton.RegExp;
 
 import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTag;
@@ -400,7 +403,7 @@
     return mine;
   }
 
-  static boolean isRE(String refPattern) {
+  public static boolean isRE(String refPattern) {
     return refPattern.startsWith(AccessSection.REGEX_PREFIX);
   }
 
@@ -414,10 +417,28 @@
     }
   }
 
-  static RegExp toRegExp(String refPattern) {
+  public static RegExp toRegExp(String refPattern) {
     if (isRE(refPattern)) {
       refPattern = refPattern.substring(1);
     }
     return new RegExp(refPattern, RegExp.NONE);
   }
+
+  public static void validateRefPattern(String refPattern)
+      throws InvalidNameException {
+    if (refPattern.startsWith(RefConfigSection.REGEX_PREFIX)) {
+      if (!Repository.isValidRefName(RefControl.shortestExample(refPattern))) {
+        throw new InvalidNameException(refPattern);
+      }
+    } else if (refPattern.equals(RefConfigSection.ALL)) {
+      // This is a special case we have to allow, it fails below.
+    } else if (refPattern.endsWith("/*")) {
+      String prefix = refPattern.substring(0, refPattern.length() - 2);
+      if (!Repository.isValidRefName(prefix)) {
+        throw new InvalidNameException(refPattern);
+      }
+    } else if (!Repository.isValidRefName(refPattern)) {
+      throw new InvalidNameException(refPattern);
+    }
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java
index ce7530e..1c70b04 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionMatcher.java
@@ -33,7 +33,7 @@
 abstract class SectionMatcher {
   static SectionMatcher wrap(AccessSection section) {
     String ref = section.getName();
-    if (AccessSection.isAccessSection(ref)) {
+    if (AccessSection.isValid(ref)) {
       return wrap(ref, section);
     } else {
       return null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionSortCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionSortCache.java
index c0d2034..40d4290 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionSortCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SectionSortCache.java
@@ -14,24 +14,18 @@
 
 package com.google.gerrit.server.project;
 
-import static com.google.gerrit.server.project.RefControl.isRE;
-import static com.google.gerrit.server.project.RefControl.shortestExample;
-import static com.google.gerrit.server.project.RefControl.toRegExp;
-
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.util.MostSpecificComparator;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
 
-import org.apache.commons.lang.StringUtils;
-
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.IdentityHashMap;
 import java.util.List;
 
@@ -161,103 +155,5 @@
     }
   }
 
-  /**
-   * Order the Ref Pattern by the most specific. This sort is done by:
-   * <ul>
-   * <li>1 - The minor value of Levenshtein string distance between the branch
-   * name and the regex string shortest example. A shorter distance is a more
-   * specific match.
-   * <li>2 - Finites first, infinities after.
-   * <li>3 - Number of transitions.
-   * <li>4 - Length of the expression text.
-   * </ul>
-   *
-   * Levenshtein distance is a measure of the similarity between two strings.
-   * The distance is the number of deletions, insertions, or substitutions
-   * required to transform one string into another.
-   *
-   * For example, if given refs/heads/m* and refs/heads/*, the distances are 5
-   * and 6. It means that refs/heads/m* is more specific because it's closer to
-   * refs/heads/master than refs/heads/*.
-   *
-   * Another example could be refs/heads/* and refs/heads/[a-zA-Z]*, the
-   * distances are both 6. Both are infinite, but refs/heads/[a-zA-Z]* has more
-   * transitions, which after all turns it more specific.
-   */
-  private static final class MostSpecificComparator implements
-      Comparator<AccessSection> {
-    private final String refName;
 
-    MostSpecificComparator(String refName) {
-      this.refName = refName;
-    }
-
-    public int compare(AccessSection a, AccessSection b) {
-      return compare(a.getName(), b.getName());
-    }
-
-    private int compare(final String pattern1, final String pattern2) {
-      int cmp = distance(pattern1) - distance(pattern2);
-      if (cmp == 0) {
-        boolean p1_finite = finite(pattern1);
-        boolean p2_finite = finite(pattern2);
-
-        if (p1_finite && !p2_finite) {
-          cmp = -1;
-        } else if (!p1_finite && p2_finite) {
-          cmp = 1;
-        } else /* if (f1 == f2) */{
-          cmp = 0;
-        }
-      }
-      if (cmp == 0) {
-        cmp = transitions(pattern1) - transitions(pattern2);
-      }
-      if (cmp == 0) {
-        cmp = pattern2.length() - pattern1.length();
-      }
-      return cmp;
-    }
-
-    private int distance(String pattern) {
-      String example;
-      if (isRE(pattern)) {
-        example = shortestExample(pattern);
-
-      } else if (pattern.endsWith("/*")) {
-        example = pattern.substring(0, pattern.length() - 1) + '1';
-
-      } else if (pattern.equals(refName)) {
-        return 0;
-
-      } else {
-        return Math.max(pattern.length(), refName.length());
-      }
-      return StringUtils.getLevenshteinDistance(example, refName);
-    }
-
-    private boolean finite(String pattern) {
-      if (isRE(pattern)) {
-        return toRegExp(pattern).toAutomaton().isFinite();
-
-      } else if (pattern.endsWith("/*")) {
-        return false;
-
-      } else {
-        return true;
-      }
-    }
-
-    private int transitions(String pattern) {
-      if (isRE(pattern)) {
-        return toRegExp(pattern).toAutomaton().getNumberOfTransitions();
-
-      } else if (pattern.endsWith("/*")) {
-        return pattern.length();
-
-      } else {
-        return pattern.length();
-      }
-    }
-  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SuggestParentCandidates.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SuggestParentCandidates.java
index 9585e1e..c73de60 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SuggestParentCandidates.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SuggestParentCandidates.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.project;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/AndPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/AndPredicate.java
index f79fbac..096e12e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/AndPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/AndPredicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/NotPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/NotPredicate.java
index f039e19..f94e1f6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/NotPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/NotPredicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/ObjectIdPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/ObjectIdPredicate.java
index 0d68fea..bea4da12 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/ObjectIdPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/ObjectIdPredicate.java
@@ -14,8 +14,6 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gerrit.server.query.OperatorPredicate;
-
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.ObjectId;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/OrPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/OrPredicate.java
index a198745..57d21b1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/OrPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/OrPredicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
index 485087f..ce47d2d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java
index 5de116f..45b27e5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query;
 
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.Collection;
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AbstractResultSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AbstractResultSet.java
index 2b8d37d..e072760 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AbstractResultSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AbstractResultSet.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.ResultSet;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AgePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AgePredicate.java
index 18a0c82..d0c9e4c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AgePredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AgePredicate.java
@@ -17,11 +17,11 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.ConfigUtil;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class AgePredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AndSource.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AndSource.java
index e74b390..3a0bfa3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AndSource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/AndSource.java
@@ -16,9 +16,9 @@
 
 import com.google.gerrit.server.query.AndPredicate;
 import com.google.gerrit.server.query.Predicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BranchPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BranchPredicate.java
index 1083d6a..e5b4143 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BranchPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BranchPredicate.java
@@ -14,21 +14,20 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class BranchPredicate extends OperatorPredicate<ChangeData> {
   private final Provider<ReviewDb> dbProvider;
-  private final String shortName;
 
   BranchPredicate(Provider<ReviewDb> dbProvider, String branch) {
-    super(ChangeQueryBuilder.FIELD_BRANCH, branch);
+    super(ChangeQueryBuilder.FIELD_BRANCH, branch.startsWith(Branch.R_HEADS)
+        ? branch : Branch.R_HEADS + branch);
     this.dbProvider = dbProvider;
-    this.shortName = branch;
   }
 
   @Override
@@ -38,7 +37,7 @@
       return false;
     }
     return change.getDest().get().startsWith(Branch.R_HEADS)
-        && shortName.equals(change.getDest().getShortName());
+        && getValue().equals(change.getDest().get());
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
index 2f648a9..7a85b6f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -14,21 +14,21 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.Patch;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.TrackingId;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.TrackingId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.patch.PatchListEntry;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import org.eclipse.jgit.lib.ObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataResultSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataResultSet.java
index fc7ba59..c2eb9b9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataResultSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataResultSet.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gwtorm.server.ResultSet;
 
 import java.util.HashSet;
 import java.util.Iterator;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataSource.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataSource.java
index a770b54..ecfd48c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataSource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeDataSource.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 
 public interface ChangeDataSource {
   /** @return an estimate of the number of results from {@link #read()}. */
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeIdPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeIdPredicate.java
index 83107bb..7116aa9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeIdPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeIdPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 class ChangeIdPredicate extends OperatorPredicate<ChangeData> implements
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 64a5d07..4d8e806 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
@@ -15,12 +15,12 @@
 package com.google.gerrit.server.query.change;
 
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountResolver;
@@ -35,7 +35,7 @@
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryBuilder;
 import com.google.gerrit.server.query.QueryParseException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
index b31bf65..bf2e4cc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
@@ -14,16 +14,17 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ChangeAccess;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ChangeAccess;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.query.IntPredicate;
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryRewriter;
 import com.google.gerrit.server.query.RewritePredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.OutOfScopeException;
 import com.google.inject.Provider;
@@ -118,6 +119,102 @@
     return a.getValue().compareTo(b.getValue()) >= 0 ? a : b;
   }
 
+  @Rewrite("status:open P=(project:*) B=(branch:*) S=(sortkey_after:*) L=(limit:*)")
+  public Predicate<ChangeData> r05_byBranchOpenPrev(
+      @Named("P") final ProjectPredicate p,
+      @Named("B") final BranchPredicate b,
+      @Named("S") final SortKeyPredicate.After s,
+      @Named("L") final IntPredicate<ChangeData> l) {
+    return new PaginatedSource(500, s.getValue(), l.intValue()) {
+      @Override
+      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
+          throws OrmException {
+        return a.byBranchOpenAll(new Branch.NameKey(p.getValueKey(), b
+            .getValue()));
+      }
+
+      @Override
+      public boolean match(ChangeData cd) throws OrmException {
+        return cd.change(dbProvider).getStatus().isOpen() //
+            && p.match(cd) //
+            && b.match(cd) //
+            && s.match(cd);
+      }
+    };
+  }
+
+  @Rewrite("status:open P=(project:*) B=(branch:*) S=(sortkey_before:*) L=(limit:*)")
+  public Predicate<ChangeData> r05_byBranchOpenNext(
+      @Named("P") final ProjectPredicate p,
+      @Named("B") final BranchPredicate b,
+      @Named("S") final SortKeyPredicate.Before s,
+      @Named("L") final IntPredicate<ChangeData> l) {
+    return new PaginatedSource(500, s.getValue(), l.intValue()) {
+      @Override
+      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
+          throws OrmException {
+        return a.byBranchOpenAll(new Branch.NameKey(p.getValueKey(), b
+            .getValue()));
+      }
+
+      @Override
+      public boolean match(ChangeData cd) throws OrmException {
+        return cd.change(dbProvider).getStatus().isOpen() //
+            && p.match(cd) //
+            && b.match(cd) //
+            && s.match(cd);
+      }
+    };
+  }
+
+  @Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_after:*) L=(limit:*)")
+  public Predicate<ChangeData> r05_byBranchMergedPrev(
+      @Named("P") final ProjectPredicate p,
+      @Named("B") final BranchPredicate b,
+      @Named("S") final SortKeyPredicate.After s,
+      @Named("L") final IntPredicate<ChangeData> l) {
+    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
+      @Override
+      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
+          throws OrmException {
+        return a.byBranchClosedPrev(Change.Status.MERGED.getCode(), //
+            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
+      }
+
+      @Override
+      public boolean match(ChangeData cd) throws OrmException {
+        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
+            && p.match(cd) //
+            && b.match(cd) //
+            && s.match(cd);
+      }
+    };
+  }
+
+  @Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_before:*) L=(limit:*)")
+  public Predicate<ChangeData> r05_byBranchMergedNext(
+      @Named("P") final ProjectPredicate p,
+      @Named("B") final BranchPredicate b,
+      @Named("S") final SortKeyPredicate.Before s,
+      @Named("L") final IntPredicate<ChangeData> l) {
+    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
+      @Override
+      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
+          throws OrmException {
+        return a.byBranchClosedNext(Change.Status.MERGED.getCode(), //
+            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
+      }
+
+      @Override
+      public boolean match(ChangeData cd) throws OrmException {
+        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
+            && p.match(cd) //
+            && b.match(cd) //
+            && s.match(cd);
+      }
+    };
+  }
+
   @Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
   public Predicate<ChangeData> r10_byProjectOpenPrev(
       @Named("P") final ProjectPredicate p,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
index 4ae2278..6e9e79c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeStatusPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
 import com.google.gerrit.server.query.Predicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/CommitPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/CommitPredicate.java
index c03cddc..274b40c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/CommitPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/CommitPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.ObjectIdPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/HasDraftByPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/HasDraftByPredicate.java
index 07d4dd2..1d9a9a4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/HasDraftByPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/HasDraftByPredicate.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchLineComment;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchLineComment;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsReviewedPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsReviewedPredicate.java
index 46c7741..639be517c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsReviewedPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsReviewedPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class IsReviewedPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsStarredByPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsStarredByPredicate.java
index aaf8478..3fd9feb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsStarredByPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsStarredByPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 class IsStarredByPredicate extends OperatorPredicate<ChangeData> implements
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
index 739d9bc..413e6c4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class IsVisibleToPredicate extends OperatorPredicate<ChangeData> {
@@ -30,7 +30,7 @@
       return ((IdentifiedUser) user).getAccountId().toString();
     }
     if (user instanceof SingleGroupUser) {
-      return "group:" + ((SingleGroupUser) user).getEffectiveGroups() //
+      return "group:" + ((SingleGroupUser) user).getEffectiveGroups().getKnownGroups() //
           .iterator().next().toString();
     }
     return user.toString();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
index 69d379cf..25cfae7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsWatchedByPredicate.java
@@ -14,15 +14,15 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.query.OperatorPredicate;
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryParseException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import java.util.ArrayList;
 import java.util.HashMap;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
index 7342c4f..bf21261 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LabelPredicate.java
@@ -17,14 +17,14 @@
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import java.util.regex.Matcher;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LegacyChangeIdPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LegacyChangeIdPredicate.java
index ac544a3..4c47e73 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LegacyChangeIdPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/LegacyChangeIdPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/MessagePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/MessagePredicate.java
index 20b777d..f016c37 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/MessagePredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/MessagePredicate.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OrSource.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OrSource.java
index 617a14a..ec5195b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OrSource.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OrSource.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.query.OrPredicate;
 import com.google.gerrit.server.query.Predicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerPredicate.java
index 224dce9..7a85ef6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class OwnerPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerinPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerinPredicate.java
index 92890b7..05c4cbf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerinPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/OwnerinPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class OwnerinPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/Paginated.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/Paginated.java
index b046db6..2b3edf7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/Paginated.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/Paginated.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 
 interface Paginated {
   int limit();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ProjectPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ProjectPredicate.java
index 91203d6..cce2f2a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ProjectPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ProjectPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class ProjectPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
index 030e83f..a2fa7fe 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
@@ -15,9 +15,9 @@
 package com.google.gerrit.server.query.change;
 
 import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.events.ChangeAttribute;
 import com.google.gerrit.server.events.EventFactory;
@@ -27,7 +27,7 @@
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryParseException;
 import com.google.gson.Gson;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -77,6 +77,7 @@
   private boolean includeComments;
   private boolean includeFiles;
   private boolean includeCommitMessage;
+  private boolean includeDependencies;
 
   private OutputStream outputStream = DisabledOutputStream.INSTANCE;
   private PrintWriter out;
@@ -128,6 +129,14 @@
     return includeFiles;
   }
 
+  public void setIncludeDependencies(boolean on) {
+    includeDependencies = on;
+  }
+
+  public boolean getIncludeDependencies() {
+    return includeDependencies;
+  }
+
   public void setIncludeCommitMessage(boolean on) {
     includeCommitMessage = on;
   }
@@ -137,6 +146,51 @@
     this.outputFormat = fmt;
   }
 
+  public List<ChangeData> queryChanges(final String queryString)
+      throws OrmException, QueryParseException {
+    final Predicate<ChangeData> visibleToMe = queryBuilder.is_visible();
+    Predicate<ChangeData> s = compileQuery(queryString, visibleToMe);
+    List<ChangeData> results = new ArrayList<ChangeData>();
+    HashSet<Change.Id> want = new HashSet<Change.Id>();
+    for (ChangeData d : ((ChangeDataSource) s).read()) {
+      if (d.hasChange()) {
+        // Checking visibleToMe here should be unnecessary, the
+        // query should have already performed it. But we don't
+        // want to trust the query rewriter that much yet.
+        //
+        if (visibleToMe.match(d)) {
+          results.add(d);
+        }
+      } else {
+        want.add(d.getId());
+      }
+    }
+
+    if (!want.isEmpty()) {
+      for (Change c : db.get().changes().get(want)) {
+        ChangeData d = new ChangeData(c);
+        if (visibleToMe.match(d)) {
+          results.add(d);
+        }
+      }
+    }
+
+    Collections.sort(results, new Comparator<ChangeData>() {
+      @Override
+      public int compare(ChangeData a, ChangeData b) {
+        return b.getChange().getSortKey().compareTo(
+            a.getChange().getSortKey());
+      }
+    });
+
+    int limit = limit(s);
+    if (limit < results.size()) {
+      results = results.subList(0, limit);
+    }
+
+    return results;
+  }
+
   public void query(String queryString) throws IOException {
     out = new PrintWriter( //
         new BufferedWriter( //
@@ -153,46 +207,7 @@
         final QueryStats stats = new QueryStats();
         stats.runTimeMilliseconds = System.currentTimeMillis();
 
-        final Predicate<ChangeData> visibleToMe = queryBuilder.is_visible();
-        Predicate<ChangeData> s = compileQuery(queryString, visibleToMe);
-        List<ChangeData> results = new ArrayList<ChangeData>();
-        HashSet<Change.Id> want = new HashSet<Change.Id>();
-        for (ChangeData d : ((ChangeDataSource) s).read()) {
-          if (d.hasChange()) {
-            // Checking visibleToMe here should be unnecessary, the
-            // query should have already performed it. But we don't
-            // want to trust the query rewriter that much yet.
-            //
-            if (visibleToMe.match(d)) {
-              results.add(d);
-            }
-          } else {
-            want.add(d.getId());
-          }
-        }
-
-        if (!want.isEmpty()) {
-          for (Change c : db.get().changes().get(want)) {
-            ChangeData d = new ChangeData(c);
-            if (visibleToMe.match(d)) {
-              results.add(d);
-            }
-          }
-        }
-
-        Collections.sort(results, new Comparator<ChangeData>() {
-          @Override
-          public int compare(ChangeData a, ChangeData b) {
-            return b.getChange().getSortKey().compareTo(
-                a.getChange().getSortKey());
-          }
-        });
-
-        int limit = limit(s);
-        if (limit < results.size()) {
-          results = results.subList(0, limit);
-        }
-
+        List<ChangeData> results = queryChanges(queryString);
         for (ChangeData d : results) {
           ChangeAttribute c = eventFactory.asChangeAttribute(d.getChange());
           eventFactory.extend(c, d.getChange());
@@ -236,6 +251,10 @@
             }
           }
 
+          if (includeDependencies) {
+            eventFactory.addDependencies(c, d.getChange());
+          }
+
           show(c);
         }
 
@@ -361,7 +380,20 @@
       out.print('\n');
     } else if (value instanceof Collection) {
       out.print('\n');
+      boolean firstElement = true;
       for (Object thing : ((Collection<?>) value)) {
+        // The name of the collection was initially printed at the beginning
+        // of this routine.  Beginning at the second sub-element, reprint
+        // the collection name so humans can separate individual elements
+        // with less strain and error.
+        //
+        if (firstElement) {
+          firstElement = false;
+        } else {
+          out.print(indent);
+          out.print(field);
+          out.print(":\n");
+        }
         if (isPrimitive(thing)) {
           out.print(' ');
           out.print(value);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RefPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RefPredicate.java
index f5f83e2..4811f9a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RefPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RefPredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class RefPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexBranchPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexBranchPredicate.java
index a18d43a..6704a10 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexBranchPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexBranchPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import dk.brics.automaton.RegExp;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexFilePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexFilePredicate.java
index 6bccec1..11856e4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexFilePredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexFilePredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import dk.brics.automaton.Automaton;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexProjectPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexProjectPredicate.java
index c35b66e..b8911a4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexProjectPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexProjectPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import dk.brics.automaton.RegExp;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexRefPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexRefPredicate.java
index e9e9958..1480de6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexRefPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexRefPredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import dk.brics.automaton.RegExp;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexTopicPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexTopicPredicate.java
index e16088c..03814f8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexTopicPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/RegexTopicPredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 import dk.brics.automaton.RegExp;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerPredicate.java
index bcece94..8e910df 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerPredicate.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class ReviewerPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerinPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerinPredicate.java
index ea4d7b6..421c6c6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerinPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ReviewerinPredicate.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class ReviewerinPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
index ad28b41..cdce217 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
@@ -14,19 +14,21 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.ListGroupMembership;
 
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
 
 final class SingleGroupUser extends CurrentUser {
-  private final Set<AccountGroup.UUID> groups;
+  private final GroupMembership groups;
 
   SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
       AccountGroup.UUID groupId) {
@@ -36,11 +38,11 @@
   SingleGroupUser(CapabilityControl.Factory capabilityControlFactory,
       Set<AccountGroup.UUID> groups) {
     super(capabilityControlFactory, AccessPath.UNKNOWN);
-    this.groups = groups;
+    this.groups = new ListGroupMembership(groups);
   }
 
   @Override
-  public Set<AccountGroup.UUID> getEffectiveGroups() {
+  public GroupMembership getEffectiveGroups() {
     return groups;
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SortKeyPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SortKeyPredicate.java
index f67bee1..e7668c6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SortKeyPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SortKeyPredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 abstract class SortKeyPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TopicPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TopicPredicate.java
index 7bc972d..8d58376 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TopicPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TopicPredicate.java
@@ -14,10 +14,10 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Provider;
 
 class TopicPredicate extends OperatorPredicate<ChangeData> {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TrackingIdPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TrackingIdPredicate.java
index eef568d..e022f86 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TrackingIdPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/TrackingIdPredicate.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.TrackingId;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.TrackingId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.query.OperatorPredicate;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Provider;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
index 65f5820..2a98e96 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceProvider.java
@@ -15,7 +15,8 @@
 package com.google.gerrit.server.schema;
 
 import static com.google.gerrit.server.config.ConfigUtil.getEnum;
-import static java.util.concurrent.TimeUnit.*;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
 import com.google.gerrit.lifecycle.LifecycleListener;
 import com.google.gerrit.server.config.ConfigUtil;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DatabaseModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DatabaseModule.java
index 6b66e33..c7832d4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DatabaseModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DatabaseModule.java
@@ -16,10 +16,10 @@
 
 import static com.google.inject.Scopes.SINGLETON;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.FactoryModule;
-import com.google.gwtorm.client.SchemaFactory;
 import com.google.gwtorm.jdbc.Database;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.TypeLiteral;
 
 /** Loads the database with standard dependencies. */
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java
index 56b0379..ed77fff 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gwtorm.jdbc.Database;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java
index b8164b4..d8809da 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaCreator.java
@@ -19,14 +19,14 @@
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.account.GroupUUID;
 import com.google.gerrit.server.config.AllProjectsName;
@@ -36,13 +36,13 @@
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.NoReplication;
 import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gwtorm.client.OrmException;
 import com.google.gwtorm.jdbc.JdbcExecutor;
 import com.google.gwtorm.jdbc.JdbcSchema;
 import com.google.gwtorm.schema.sql.DialectH2;
 import com.google.gwtorm.schema.sql.DialectMySQL;
 import com.google.gwtorm.schema.sql.DialectPostgreSQL;
 import com.google.gwtorm.schema.sql.SqlDialect;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
index 3937aaa..305fb84 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaUpdater.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.SitePaths;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
index abdc0ee..f789300 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.StatementExecutor;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gwtorm.jdbc.JdbcExecutor;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.StatementExecutor;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provider;
 
@@ -32,7 +32,7 @@
 /** A version of the database schema. */
 public abstract class SchemaVersion {
   /** The current schema version. */
-  public static final Class<Schema_61> C = Schema_61.class;
+  public static final Class<Schema_64> C = Schema_64.class;
 
   public static class Module extends AbstractModule {
     @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
index 9a59567..75d8a39 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersionCheck.java
@@ -16,10 +16,10 @@
 
 import com.google.gerrit.lifecycle.LifecycleListener;
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Provider;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_52.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_52.java
index e16b95c..12a22f9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_52.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_52.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.ProvisionException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_53.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_53.java
index 89ee5cf..d49b34e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_53.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_53.java
@@ -30,19 +30,19 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.account.GroupUUID;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.NoReplication;
 import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gwtorm.client.OrmException;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java
index 8d00b73..9032bb0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.LocalDiskRepositoryManager;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java
index bbb7109..2409b12e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 import com.google.inject.Inject;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java
index 2ae1b7a..2247fdb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java
@@ -18,11 +18,11 @@
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.common.data.PermissionRule.Action;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupName;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupName;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.config.AllProjectsNameProvider;
 import com.google.gerrit.server.config.SitePaths;
@@ -30,7 +30,7 @@
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.NoReplication;
 import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_59.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_59.java
index 0b722bc..d90ecc1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_59.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_59.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_60.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_60.java
index eec7256..3f49b0c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_60.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_60.java
@@ -14,13 +14,12 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.Change;
-
-import com.google.gerrit.reviewdb.ChangeMessage;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_62.java
similarity index 72%
rename from gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_62.java
index 2ef2d44..4de8e55 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_62.java
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.httpd.rpc;
+package com.google.gerrit.server.schema;
 
-public enum SuggestAccountsEnum {
-  ALL,
-  SAME_GROUP,
-  VISIBLE_GROUP,
-  OFF;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class Schema_62 extends SchemaVersion {
+  @Inject
+  Schema_62(Provider<Schema_61> prior) {
+    super(prior);
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_63.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_63.java
new file mode 100644
index 0000000..761c36a
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_63.java
@@ -0,0 +1,48 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.schema.sql.DialectPostgreSQL;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class Schema_63 extends SchemaVersion {
+  @Inject
+  Schema_63(Provider<Schema_62> prior) {
+    super(prior);
+  }
+
+  @Override
+  protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
+    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
+    try {
+      if (((JdbcSchema) db).getDialect() instanceof DialectPostgreSQL) {
+        stmt.execute("CREATE INDEX changes_byBranchClosed"
+            + " ON changes (status, dest_project_name, dest_branch_name, sort_key)"
+            + " WHERE open = 'N'");
+      } else {
+        stmt.execute("CREATE INDEX changes_byBranchClosed"
+            + " ON changes (status, dest_project_name, dest_branch_name, sort_key)");
+      }
+    } finally {
+      stmt.close();
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_64.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_64.java
new file mode 100644
index 0000000..26890a3
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_64.java
@@ -0,0 +1,121 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.schema;
+
+import com.google.common.collect.Lists;
+import com.google.gerrit.common.data.AccessSection;
+import com.google.gerrit.common.data.GlobalCapability;
+import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.common.data.Permission;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.git.MetaDataUpdate;
+import com.google.gerrit.server.git.NoReplication;
+import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
+
+import java.io.IOException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+
+public class Schema_64 extends SchemaVersion {
+  private final AllProjectsName allProjects;
+  private final GitRepositoryManager mgr;
+  private final PersonIdent serverUser;
+
+  @Inject
+  Schema_64(Provider<Schema_63> prior,
+      AllProjectsName allProjects,
+      GitRepositoryManager mgr,
+      @GerritPersonIdent PersonIdent serverUser) {
+    super(prior);
+    this.allProjects = allProjects;
+    this.mgr = mgr;
+    this.serverUser = serverUser;
+  }
+
+  @Override
+  protected void migrateData(ReviewDb db, UpdateUI ui)
+      throws OrmException, SQLException {
+    List<GroupReference> groups = Lists.newArrayList();
+    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
+    try {
+      ResultSet rs = stmt.executeQuery(
+          "SELECT group_uuid, name FROM account_groups WHERE email_only_authors = 'Y'");
+      try {
+        while (rs.next()) {
+          AccountGroup.UUID uuid = new AccountGroup.UUID(rs.getString(1));
+          GroupReference group = new GroupReference(uuid, rs.getString(2));
+          groups.add(group);
+        }
+      } finally {
+        rs.close();
+      }
+    } finally {
+      stmt.close();
+    }
+
+    if (groups.isEmpty()) {
+      return;
+    }
+    ui.message("Moved account_groups.email_only_authors to 'Email Reviewers' capability");
+
+    Repository git;
+    try {
+      git = mgr.openRepository(allProjects);
+    } catch (RepositoryNotFoundException e) {
+      throw new OrmException(e);
+    }
+    try {
+      MetaDataUpdate md =
+          new MetaDataUpdate(new NoReplication(), allProjects, git);
+      md.getCommitBuilder().setAuthor(serverUser);
+      md.getCommitBuilder().setCommitter(serverUser);
+
+      ProjectConfig config = ProjectConfig.read(md);
+      AccessSection section =
+          config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true);
+      Permission capability =
+          section.getPermission(GlobalCapability.EMAIL_REVIEWERS, true);
+      for (GroupReference group : groups) {
+        capability.getRule(config.resolve(group), true).setDeny();
+      }
+
+      md.setMessage("Upgrade to Gerrit Code Review schema 64\n");
+      if (!config.commit(md)) {
+        throw new OrmException("Cannot update " + allProjects);
+      }
+    } catch (IOException e) {
+      throw new OrmException(e);
+    } catch (ConfigInvalidException e) {
+      throw new OrmException(e);
+    } finally {
+      git.close();
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/ScriptRunner.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/ScriptRunner.java
index 34c47a8..8cf2f26 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/ScriptRunner.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/ScriptRunner.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
 
 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/UpdateUI.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/UpdateUI.java
index ac07efd..64b3afa 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/UpdateUI.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/UpdateUI.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.StatementExecutor;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.StatementExecutor;
 
 import java.util.List;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshInfo.java
index 882181d..519b922 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshInfo.java
@@ -14,8 +14,6 @@
 
 package com.google.gerrit.server.ssh;
 
-import com.google.gerrit.server.ssh.SshInfo;
-
 import com.jcraft.jsch.HostKey;
 
 import java.util.Collections;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshKeyCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshKeyCache.java
index ad18b3f..6a07ca7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshKeyCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/NoSshKeyCache.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.server.ssh;
 
 import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 
 class NoSshKeyCache implements SshKeyCache {
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/SshKeyCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/SshKeyCache.java
index b56405a..13c5703 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ssh/SshKeyCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ssh/SshKeyCache.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.server.ssh;
 
 import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 
 /** Permits controlling the contents of the SSH key cache area. */
 public interface SshKeyCache {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/GuiceRequestScopePropagator.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/GuiceRequestScopePropagator.java
new file mode 100644
index 0000000..9befc7d
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/GuiceRequestScopePropagator.java
@@ -0,0 +1,81 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.util;
+
+import com.google.common.collect.Maps;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.RemotePeer;
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.servlet.ServletScopes;
+import com.google.inject.util.Providers;
+import com.google.inject.util.Types;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.net.SocketAddress;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Nullable;
+
+/** Propagator for Guice's built-in servlet scope. */
+public class GuiceRequestScopePropagator extends RequestScopePropagator {
+
+  private final String url;
+  private final SocketAddress peer;
+  private final CurrentUser user;
+
+  @Inject
+  GuiceRequestScopePropagator(
+      @CanonicalWebUrl @Nullable Provider<String> urlProvider,
+      @RemotePeer Provider<SocketAddress> remotePeerProvider,
+      Provider<CurrentUser> currentUserProvider) {
+    super(ServletScopes.REQUEST);
+    this.url = urlProvider != null ? urlProvider.get() : null;
+    this.peer = remotePeerProvider.get();
+    this.user = currentUserProvider.get();
+  }
+
+  /**
+   * @see RequestScopePropagator#wrap(Callable)
+   */
+  @Override
+  protected <T> Callable<T> wrapImpl(Callable<T> callable) {
+    Map<Key<?>, Object> seedMap = Maps.newHashMap();
+
+    // Request scopes appear to use specific keys in their map, instead of only
+    // providers. Add bindings for both the key to the instance directly and the
+    // provider to the instance to be safe.
+    seedMap.put(Key.get(typeOfProvider(String.class), CanonicalWebUrl.class),
+        Providers.of(url));
+    seedMap.put(Key.get(String.class, CanonicalWebUrl.class), url);
+
+    seedMap.put(Key.get(typeOfProvider(SocketAddress.class), RemotePeer.class),
+        Providers.of(peer));
+    seedMap.put(Key.get(SocketAddress.class, RemotePeer.class), peer);
+
+    seedMap.put(Key.get(typeOfProvider(CurrentUser.class)), Providers.of(user));
+    seedMap.put(Key.get(CurrentUser.class), user);
+
+    return ServletScopes.continueRequest(callable, seedMap);
+  }
+
+  private ParameterizedType typeOfProvider(Type type) {
+    return Types.newParameterizedType(Provider.class, type);
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/MagicBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/MagicBranch.java
index ef08d78..510deaa02 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/util/MagicBranch.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/MagicBranch.java
@@ -15,7 +15,7 @@
 package com.google.gerrit.server.util;
 
 import com.google.gerrit.common.data.Capable;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -108,4 +108,4 @@
 
   private MagicBranch() {
   }
-}
\ No newline at end of file
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/MostSpecificComparator.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/MostSpecificComparator.java
new file mode 100644
index 0000000..804a7ec
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/MostSpecificComparator.java
@@ -0,0 +1,124 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.util;
+
+import com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.server.project.RefControl;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Comparator;
+
+/**
+ * Order the Ref Pattern by the most specific. This sort is done by:
+ * <ul>
+ * <li>1 - The minor value of Levenshtein string distance between the branch
+ * name and the regex string shortest example. A shorter distance is a more
+ * specific match.
+ * <li>2 - Finites first, infinities after.
+ * <li>3 - Number of transitions.
+ * <li>4 - Length of the expression text.
+ * </ul>
+ *
+ * Levenshtein distance is a measure of the similarity between two strings.
+ * The distance is the number of deletions, insertions, or substitutions
+ * required to transform one string into another.
+ *
+ * For example, if given refs/heads/m* and refs/heads/*, the distances are 5
+ * and 6. It means that refs/heads/m* is more specific because it's closer to
+ * refs/heads/master than refs/heads/*.
+ *
+ * Another example could be refs/heads/* and refs/heads/[a-zA-Z]*, the
+ * distances are both 6. Both are infinite, but refs/heads/[a-zA-Z]* has more
+ * transitions, which after all turns it more specific.
+ */
+public final class MostSpecificComparator implements
+    Comparator<RefConfigSection> {
+  private final String refName;
+
+  public MostSpecificComparator(String refName) {
+    this.refName = refName;
+  }
+
+  @Override
+  public int compare(RefConfigSection a, RefConfigSection b) {
+    return compare(a.getName(), b.getName());
+  }
+
+  public int compare(final String pattern1, final String pattern2) {
+    int cmp = distance(pattern1) - distance(pattern2);
+    if (cmp == 0) {
+      boolean p1_finite = finite(pattern1);
+      boolean p2_finite = finite(pattern2);
+
+      if (p1_finite && !p2_finite) {
+        cmp = -1;
+      } else if (!p1_finite && p2_finite) {
+        cmp = 1;
+      } else /* if (f1 == f2) */{
+        cmp = 0;
+      }
+    }
+    if (cmp == 0) {
+      cmp = transitions(pattern1) - transitions(pattern2);
+    }
+    if (cmp == 0) {
+      cmp = pattern2.length() - pattern1.length();
+    }
+    return cmp;
+  }
+
+  private int distance(String pattern) {
+    String example;
+    if (RefControl.isRE(pattern)) {
+      example = RefControl.shortestExample(pattern);
+
+    } else if (pattern.endsWith("/*")) {
+      example = pattern.substring(0, pattern.length() - 1) + '1';
+
+    } else if (pattern.equals(refName)) {
+      return 0;
+
+    } else {
+      return Math.max(pattern.length(), refName.length());
+    }
+    return StringUtils.getLevenshteinDistance(example, refName);
+  }
+
+  private boolean finite(String pattern) {
+    if (RefControl.isRE(pattern)) {
+      return RefControl.toRegExp(pattern).toAutomaton().isFinite();
+
+    } else if (pattern.endsWith("/*")) {
+      return false;
+
+    } else {
+      return true;
+    }
+  }
+
+  private int transitions(String pattern) {
+    if (RefControl.isRE(pattern)) {
+      return RefControl.toRegExp(pattern).toAutomaton()
+          .getNumberOfTransitions();
+
+    } else if (pattern.endsWith("/*")) {
+      return pattern.length();
+
+    } else {
+      return pattern.length();
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java
new file mode 100644
index 0000000..3661aa2
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/RequestScopePropagator.java
@@ -0,0 +1,181 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.util;
+
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.server.RequestCleanup;
+import com.google.gerrit.server.git.ProjectRunnable;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.Scope;
+import com.google.inject.servlet.ServletScopes;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+
+/**
+ * Base class for propagating request-scoped data between threads.
+ * <p>
+ * Request scopes are typically linked to a {@link ThreadLocal}, which is only
+ * available to the current thread.  In order to allow background work involving
+ * RequestScoped data, the ThreadLocal data must be copied from the request thread to
+ * the new background thread.
+ * <p>
+ * Every type of RequestScope must provide an implementation of
+ * RequestScopePropagator. See {@link #wrap(Callable)} for details on the
+ * implementation, usage, and restrictions.
+ *
+ * @see ThreadLocalRequestScopePropagator
+ */
+public abstract class RequestScopePropagator {
+
+  private final Scope scope;
+
+  protected RequestScopePropagator(Scope scope) {
+    this.scope = scope;
+  }
+
+  /**
+   * Wraps callable in a new {@link Callable} that propagates the current
+   * request state when the callable is invoked. The method must be called in a
+   * request scope and the returned Callable may only be invoked in a thread
+   * that is not already in a request scope. The returned Callable will inherit
+   * toString() from the passed in Callable. A
+   * {@link com.google.gerrit.server.git.WorkQueue.Executor} does not accept a
+   * Callable, so there is no ProjectCallable implementation. Implementations of
+   * this method must be consistent with Guice's
+   * {@link ServletScopes#continueRequest(Callable, java.util.Map)}.
+   * <p>
+   * There are some limitations:
+   * <ul>
+   * <li>Derived objects (i.e. anything marked created in a request scope) will
+   * not be transported.</li>
+   * <li>State changes to the request scoped context after this method is called
+   * will not be seen in the continued thread.</li>
+   * </ul>
+   *
+   * @param callable the Callable to wrap.
+   * @return a new Callable which will execute in the current request scope.
+   */
+  public final <T> Callable<T> wrap(final Callable<T> callable) {
+    final Callable<T> wrapped = wrapImpl(new Callable<T>() {
+      @Override
+      public T call() throws Exception {
+        RequestCleanup cleanup = scope.scope(
+            Key.get(RequestCleanup.class),
+            new Provider<RequestCleanup>() {
+              @Override
+              public RequestCleanup get() {
+                return new RequestCleanup();
+              }
+            }).get();
+
+        try {
+          return callable.call();
+        } finally {
+          cleanup.run();
+        }
+      }
+    });
+
+    return new Callable<T>() {
+      @Override
+      public T call() throws Exception {
+        return wrapped.call();
+      }
+
+      @Override
+      public String toString() {
+        return callable.toString();
+      }
+    };
+  }
+
+  /**
+   * Wraps runnable in a new {@link Runnable} that propagates the current
+   * request state when the runnable is invoked. The method must be called in a
+   * request scope and the returned Runnable may only be invoked in a thread
+   * that is not already in a request scope. The returned Runnable will inherit
+   * toString() from the passed in Runnable. Furthermore, if the passed runnable
+   * is of type {@link ProjectRunnable}, the returned runnable will be of the
+   * same type with the methods delegated.
+   *
+   * See {@link #wrap(Callable)} for details on implementation and usage.
+   *
+   * @param runnable the Runnable to wrap.
+   * @return a new Runnable which will execute in the current request scope.
+   */
+  public final Runnable wrap(final Runnable runnable) {
+    final Callable<Object> wrapped = wrap(Executors.callable(runnable));
+
+    if (runnable instanceof ProjectRunnable) {
+      return new ProjectRunnable() {
+        @Override
+        public void run() {
+          try {
+            wrapped.call();
+          } catch (RuntimeException e) {
+            throw e;
+          } catch (Exception e) {
+            throw new RuntimeException(e); // Not possible.
+          }
+        }
+
+        @Override
+        public NameKey getProjectNameKey() {
+          return ((ProjectRunnable) runnable).getProjectNameKey();
+        }
+
+        @Override
+        public String getRemoteName() {
+          return ((ProjectRunnable) runnable).getRemoteName();
+        }
+
+        @Override
+        public boolean hasCustomizedPrint() {
+          return ((ProjectRunnable) runnable).hasCustomizedPrint();
+        }
+
+        @Override
+        public String toString() {
+          return runnable.toString();
+        }
+      };
+    } else {
+      return new Runnable() {
+        @Override
+        public void run() {
+          try {
+            wrapped.call();
+          } catch (RuntimeException e) {
+            throw e;
+          } catch (Exception e) {
+            throw new RuntimeException(e); // Not possible.
+          }
+        }
+
+        @Override
+        public String toString() {
+          return runnable.toString();
+        }
+      };
+    }
+  }
+
+  /**
+   * @see #wrap(Callable)
+   */
+  protected abstract <T> Callable<T> wrapImpl(final Callable<T> callable);
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
index 3148aaa..7310703 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.server.util;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
 import com.google.gerrit.server.git.GitRepositoryManager;
 
 import org.eclipse.jgit.lib.BlobBasedConfig;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestScopePropagator.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestScopePropagator.java
new file mode 100644
index 0000000..581ccc1
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/ThreadLocalRequestScopePropagator.java
@@ -0,0 +1,89 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.util;
+
+import com.google.inject.OutOfScopeException;
+import com.google.inject.Scope;
+
+import java.util.concurrent.Callable;
+
+/**
+ * {@link RequestScopePropagator} implementation for request scopes based on
+ * a {@link ThreadLocal} context.
+ *
+ * @param <C> "context" type stored in the {@link ThreadLocal}.
+ */
+public abstract class ThreadLocalRequestScopePropagator<C>
+    extends RequestScopePropagator {
+
+  private final ThreadLocal<C> threadLocal;
+
+  protected ThreadLocalRequestScopePropagator(Scope scope,
+      ThreadLocal<C> threadLocal) {
+    super(scope);
+    this.threadLocal = threadLocal;
+  }
+
+  /**
+   * @see RequestScopePropagator#wrap(Callable)
+   */
+  @Override
+  protected final <T> Callable<T> wrapImpl(final Callable<T> callable) {
+    final C ctx = continuingContext(requireContext());
+    return new Callable<T>() {
+      @Override
+      public T call() throws Exception {
+        if (threadLocal.get() != null) {
+          // This is consistent with the Guice ServletScopes.continueRequest()
+          // behavior.
+          throw new IllegalStateException("Cannot continue request, "
+              + "thread already has request in progress. A new thread must "
+              + "be used to propagate the request scope context.");
+        }
+
+        threadLocal.set(ctx);
+        try {
+          return callable.call();
+        } finally {
+          threadLocal.remove();
+        }
+      }
+    };
+  }
+
+  private C requireContext() {
+    C context = threadLocal.get();
+    if (context == null) {
+      throw new OutOfScopeException("Cannot access scoped object");
+    }
+    return context;
+  }
+
+  /**
+   * Returns a new context object based on the passed in context that has no
+   * request scoped objects initialized.
+   * <p>
+   * Note that some code paths expect request-scoped objects like
+   * {@code CurrentUser} to be constructible starting from just the context
+   * object returned by this method. For example, in the SSH scope, the context
+   * includes the {@code SshSession}, which is used by
+   * {@code SshCurrentUserProvider} to construct a new {@code CurrentUser} in
+   * the new thread.
+   *
+   * @param ctx the context to continue.
+   * @return a new context.
+   */
+  protected abstract C continuingContext(C ctx);
+}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java b/gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java
similarity index 98%
rename from gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java
index 3aa83c3..1c68a75 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/TreeFormatter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/util/TreeFormatter.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.gerrit.sshd.commands;
+package com.google.gerrit.server.util;
 
 import java.io.PrintWriter;
 import java.util.SortedSet;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
index e475b13..f6f1bfb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/CategoryFunction.java
@@ -15,8 +15,9 @@
 package com.google.gerrit.server.workflow;
 
 import com.google.gerrit.common.data.ApprovalType;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+
 import java.util.HashMap;
 import java.util.Map;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/FunctionState.java b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/FunctionState.java
index 2a871f7..d08bd1f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/FunctionState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/FunctionState.java
@@ -18,12 +18,12 @@
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRange;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ApprovalCategory.Id;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory.Id;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.GroupCache;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxNoBlock.java b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxNoBlock.java
index 5f10c28..3272f8a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxNoBlock.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxNoBlock.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.workflow;
 
 import com.google.gerrit.common.data.ApprovalType;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 
 /**
  * Computes an {@link ApprovalCategory} by looking at maximum values.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxWithBlock.java b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxWithBlock.java
index 7bf7e9b..ce84499 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxWithBlock.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/workflow/MaxWithBlock.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.server.workflow;
 
 import com.google.gerrit.common.data.ApprovalType;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
 
 /**
  * Computes an {@link ApprovalCategory} by looking at maximum values.
diff --git a/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java b/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
index 27bc286..ac74147 100644
--- a/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
+++ b/gerrit-server/src/main/java/gerrit/AbstractCommitUserIdentityPredicate.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.UserIdentity;
 
 import com.googlecode.prolog_cafe.lang.IntegerTerm;
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED__load_commit_labels_1.java b/gerrit-server/src/main/java/gerrit/PRED__load_commit_labels_1.java
index 8b35e12..c760426 100644
--- a/gerrit-server/src/main/java/gerrit/PRED__load_commit_labels_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED__load_commit_labels_1.java
@@ -4,12 +4,12 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.rules.PrologEnvironment;
 import com.google.gerrit.rules.StoredValues;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 
 import com.googlecode.prolog_cafe.lang.IntegerTerm;
 import com.googlecode.prolog_cafe.lang.JavaException;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_change_branch_1.java b/gerrit-server/src/main/java/gerrit/PRED_change_branch_1.java
index 59ec28b..7cc9f35 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_change_branch_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_change_branch_1.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_change_owner_1.java b/gerrit-server/src/main/java/gerrit/PRED_change_owner_1.java
index 0be151a..09be902 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_change_owner_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_change_owner_1.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.IntegerTerm;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_change_project_1.java b/gerrit-server/src/main/java/gerrit/PRED_change_project_1.java
index 19f3e61..d1cd20d 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_change_project_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_change_project_1.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_change_topic_1.java b/gerrit-server/src/main/java/gerrit/PRED_change_topic_1.java
index a7694c1..d200f7e 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_change_topic_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_change_topic_1.java
@@ -14,7 +14,7 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_commit_author_3.java b/gerrit-server/src/main/java/gerrit/PRED_commit_author_3.java
index 142e51b..a0817a1 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_commit_author_3.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_commit_author_3.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.UserIdentity;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_commit_committer_3.java b/gerrit-server/src/main/java/gerrit/PRED_commit_committer_3.java
index c0f9ec3..78e6cf7 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_commit_committer_3.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_commit_committer_3.java
@@ -14,8 +14,8 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.PatchSetInfo;
-import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.UserIdentity;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_commit_delta_4.java b/gerrit-server/src/main/java/gerrit/PRED_commit_delta_4.java
index 77bd81e..c2c2d1c 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_commit_delta_4.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_commit_delta_4.java
@@ -14,7 +14,7 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.client.Patch;
 import com.google.gerrit.rules.StoredValues;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListEntry;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_commit_message_1.java b/gerrit-server/src/main/java/gerrit/PRED_commit_message_1.java
index 8c94b34..0ed7443 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_commit_message_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_commit_message_1.java
@@ -14,7 +14,7 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.PatchSetInfo;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
 import com.google.gerrit.rules.StoredValues;
 
 import com.googlecode.prolog_cafe.lang.Operation;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_current_user_1.java b/gerrit-server/src/main/java/gerrit/PRED_current_user_1.java
index 516e873..23cedce 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_current_user_1.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_current_user_1.java
@@ -14,7 +14,7 @@
 
 package gerrit;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.rules.StoredValues;
 import com.google.gerrit.server.AnonymousUser;
 import com.google.gerrit.server.CurrentUser;
diff --git a/gerrit-server/src/main/java/gerrit/PRED_current_user_2.java b/gerrit-server/src/main/java/gerrit/PRED_current_user_2.java
index fe74f5d..0a15608 100644
--- a/gerrit-server/src/main/java/gerrit/PRED_current_user_2.java
+++ b/gerrit-server/src/main/java/gerrit/PRED_current_user_2.java
@@ -16,8 +16,8 @@
 
 import static com.googlecode.prolog_cafe.lang.SymbolTerm.intern;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.rules.PrologEnvironment;
 import com.google.gerrit.rules.StoredValues;
 import com.google.gerrit.server.AnonymousUser;
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RebasedPatchSet.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RebasedPatchSet.vm
new file mode 100644
index 0000000..e761627
--- /dev/null
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RebasedPatchSet.vm
@@ -0,0 +1,54 @@
+## Copyright (C) 2012 The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+##
+## Template Type:
+## -------------
+## This is a velocity mail template, see: http://velocity.apache.org and the
+## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates.
+##
+## Template File Names and extensions:
+## ----------------------------------
+## Gerrit will use templates ending in ".vm" but will ignore templates ending
+## in ".vm.example".  If a .vm template does not exist, the default internal
+## gerrit template which is the same as the .vm.example will be used.  If you
+## want to override the default template, copy the .vm.example file to a .vm
+## file and edit it appropriately.
+##
+## This Template:
+## --------------
+## The RebasedPatchSet.vm template will determine the contents of the email
+## related to a user rebasing a patchset for a change through the Gerrit UI.
+## It is a ChangeEmail: see ChangeSubject.vm and ChangeFooter.vm.
+##
+#if($email.reviewerNames)
+Hello $email.joinStrings($email.reviewerNames, ', '),
+
+I'd like you to reexamine a rebased change.#if($email.changeUrl)  Please visit
+
+    $email.changeUrl
+
+to look at the new rebased patch set (#$patchSet.patchSetId).
+#end
+#else
+$fromName has created a new patch set by issuing a rebase in Gerrit (#$patchSet.patchSetId).
+#end
+
+Change subject: $change.subject
+......................................................................
+
+$email.changeDetail
+#if($email.sshHost)
+  git pull ssh://$email.sshHost/$projectName $patchSet.refName
+#end
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
index a0e3554..212ffb1 100644
--- a/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/tools/root/hooks/commit-msg
@@ -36,56 +36,126 @@
 		return
 	fi
 
+	# Does Change-Id: already exist? if so, exit (no change).
 	if grep -i '^Change-Id:' "$MSG" >/dev/null
 	then
 		return
 	fi
 
 	id=`_gen_ChangeId`
-	perl -e '
-		$MSG = shift;
-		$id = shift;
-		$CHANGE_ID_AFTER = shift;
+	T="$MSG.tmp.$$"
+	AWK=awk
+	if [ -x /usr/xpg4/bin/awk ]; then
+		# Solaris AWK is just too broken
+		AWK=/usr/xpg4/bin/awk
+	fi
 
-		undef $/;
-		open(I, $MSG); $_ = <I>; close I;
-		s|^diff --git a/.*||ms;
-		s|^#.*$||mg;
-		exit unless $_;
+	# How this works:
+	# - parse the commit message as (textLine+ blankLine*)*
+	# - assume textLine+ to be a footer until proven otherwise
+	# - exception: the first block is not footer (as it is the title)
+	# - read textLine+ into a variable
+	# - then count blankLines
+	# - once the next textLine appears, print textLine+ blankLine* as these
+	#   aren't footer
+	# - in END, the last textLine+ block is available for footer parsing
+	$AWK '
+	BEGIN {
+		# while we start with the assumption that textLine+
+		# is a footer, the first block is not.
+		isFooter = 0
+		footerComment = 0
+		blankLines = 0
+	}
 
-		@message = split /\n/;
-		$haveFooter = 0;
-		$startFooter = @message;
-		for($line = @message - 1; $line >= 0; $line--) {
-			$_ = $message[$line];
+	# Skip lines starting with "#" without any spaces before it.
+	/^#/ { next }
 
-			if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
-				$haveFooter++;
-				next;
+	# Skip the line starting with the diff command and everything after it,
+	# up to the end of the file, assuming it is only patch data.
+	# If more than one line before the diff was empty, strip all but one.
+	/^diff --git a/ {
+		blankLines = 0
+		while (getline) { }
+		next
+	}
+
+	# Count blank lines outside footer comments
+	/^$/ && (footerComment == 0) {
+		blankLines++
+		next
+	}
+
+	# Catch footer comment
+	/^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
+		footerComment = 1
+	}
+
+	/]$/ && (footerComment == 1) {
+		footerComment = 2
+	}
+
+	# We have a non-blank line after blank lines. Handle this.
+	(blankLines > 0) {
+		print lines
+		for (i = 0; i < blankLines; i++) {
+			print ""
+		}
+
+		lines = ""
+		blankLines = 0
+		isFooter = 1
+		footerComment = 0
+	}
+
+	# Detect that the current block is not the footer
+	(footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
+		isFooter = 0
+	}
+
+	{
+		# We need this information about the current last comment line
+		if (footerComment == 2) {
+			footerComment = 0
+		}
+		if (lines != "") {
+			lines = lines "\n";
+		}
+		lines = lines $0
+	}
+
+	# Footer handling:
+	# If the last block is considered a footer, splice in the Change-Id at the
+	# right place.
+	# Look for the right place to inject Change-Id by considering
+	# CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
+	# then Change-Id, then everything else (eg. Signed-off-by:).
+	#
+	# Otherwise just print the last block, a new line and the Change-Id as a
+	# block of its own.
+	END {
+		unprinted = 1
+		if (isFooter == 0) {
+			print lines "\n"
+			lines = ""
+		}
+		changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
+		numlines = split(lines, footer, "\n")
+		for (line = 1; line <= numlines; line++) {
+			if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
+				unprinted = 0
+				print "Change-Id: I'"$id"'"
 			}
-			next if /^[ []/;
-			$startFooter = $line if ($haveFooter && /^\r?$/);
-			last;
+			print footer[line]
 		}
-
-		@footer = @message[$startFooter+1..@message];
-		@message = @message[0..$startFooter];
-		push(@footer, "") unless @footer;
-
-		for ($line = 0; $line < @footer; $line++) {
-			$_ = $footer[$line];
-			next if /^($CHANGE_ID_AFTER):/i;
-			last;
+		if (unprinted) {
+			print "Change-Id: I'"$id"'"
 		}
-		splice(@footer, $line, 0, "Change-Id: I$id");
-
-		$_ = join("\n", @message, @footer);
-		open(O, ">$MSG"); print O; close O;
-	' "$MSG" "$id" "$CHANGE_ID_AFTER"
+	}' "$MSG" > $T && mv $T "$MSG" || rm -f $T
 }
 _gen_ChangeIdInput() {
 	echo "tree `git write-tree`"
-	if parent=`git rev-parse HEAD^0 2>/dev/null`
+	if parent=`git rev-parse "HEAD^0" 2>/dev/null`
 	then
 		echo "parent $parent"
 	fi
diff --git a/gerrit-server/src/test/java/com/google/gerrit/rules/GerritCommonTest.java b/gerrit-server/src/test/java/com/google/gerrit/rules/GerritCommonTest.java
index 2b8dad5..9f2ccbf 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/rules/GerritCommonTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/rules/GerritCommonTest.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
 import com.google.inject.AbstractModule;
 
 import java.util.ArrayList;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/config/ConfigUtilTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/config/ConfigUtilTest.java
index 386a6d1..37197ec 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/config/ConfigUtilTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/config/ConfigUtilTest.java
@@ -15,7 +15,10 @@
 package com.google.gerrit.server.config;
 
 import static java.util.concurrent.TimeUnit.DAYS;
-import static java.util.concurrent.TimeUnit.*;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
 
 import junit.framework.TestCase;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
index c5b5164..ca2b03a 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/ProjectConfigTest.java
@@ -25,8 +25,8 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
 
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/PushReplicationTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/PushReplicationTest.java
index b95c7da..7ae705f 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/PushReplicationTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/PushReplicationTest.java
@@ -14,7 +14,9 @@
 
 package com.google.gerrit.server.git;
 
-import static com.google.gerrit.server.git.PushReplication.ReplicationConfig.*;
+import static com.google.gerrit.server.git.PushReplication.ReplicationConfig.encode;
+import static com.google.gerrit.server.git.PushReplication.ReplicationConfig.needsUrlEncoding;
+
 import junit.framework.TestCase;
 
 import org.eclipse.jgit.transport.URIish;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
index e086070..b32d54c 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/git/SubmoduleOpTest.java
@@ -19,17 +19,17 @@
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SubmoduleSubscription;
-import com.google.gerrit.reviewdb.SubmoduleSubscriptionAccess;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.reviewdb.server.SubmoduleSubscriptionAccess;
 import com.google.gwtorm.client.KeyUtil;
-import com.google.gwtorm.client.ResultSet;
-import com.google.gwtorm.client.SchemaFactory;
-import com.google.gwtorm.client.impl.ListResultSet;
+import com.google.gwtorm.server.ListResultSet;
+import com.google.gwtorm.server.ResultSet;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.gwtorm.server.StandardKeyEncoder;
 import com.google.inject.Provider;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/mail/FromAddressGeneratorProviderTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/mail/FromAddressGeneratorProviderTest.java
index 2332eb6..29e3df0 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/mail/FromAddressGeneratorProviderTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/mail/FromAddressGeneratorProviderTest.java
@@ -20,9 +20,9 @@
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountState;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/patch/PatchListEntryTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/patch/PatchListEntryTest.java
index 24f6f63..7df0696 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/patch/PatchListEntryTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/patch/PatchListEntryTest.java
@@ -15,7 +15,7 @@
 
 package com.google.gerrit.server.patch;
 
-import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.client.Patch;
 
 import junit.framework.TestCase;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
index 29b2762..77150e6 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/RefControlTest.java
@@ -20,36 +20,41 @@
 import static com.google.gerrit.common.data.Permission.READ;
 import static com.google.gerrit.common.data.Permission.SUBMIT;
 
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import com.google.gerrit.common.data.Capable;
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.data.PermissionRange;
 import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountProjectWatch;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.rules.PrologEnvironment;
 import com.google.gerrit.rules.RulesCache;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.account.GroupCache;
+import com.google.gerrit.server.account.GroupMembership;
+import com.google.gerrit.server.account.ListGroupMembership;
 import com.google.gerrit.server.cache.ConcurrentHashMapCache;
 import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gwtorm.client.SchemaFactory;
-import com.google.inject.AbstractModule;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
-import com.google.inject.assistedinject.FactoryProvider;
 
 import junit.framework.TestCase;
 
 import org.eclipse.jgit.lib.Config;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -294,18 +299,14 @@
       }
     };
 
-    Injector injector = Guice.createInjector(new AbstractModule() {
+    Injector injector = Guice.createInjector(new FactoryModule() {
       @Override
       protected void configure() {
-        bind(Config.class) //
-            .annotatedWith(GerritServerConfig.class) //
+        bind(Config.class)
+            .annotatedWith(GerritServerConfig.class)
             .toInstance(new Config());
 
-        bind(CapabilityControl.Factory.class)
-            .toProvider(FactoryProvider.newFactory(
-              CapabilityControl.Factory.class,
-              CapabilityControl.class));
-
+        factory(CapabilityControl.Factory.class);
         bind(ProjectCache.class).toInstance(projectCache);
       }
     });
@@ -405,18 +406,19 @@
 
   private class MockUser extends CurrentUser {
     private final String username;
-    private final Set<AccountGroup.UUID> groups;
+    private final GroupMembership groups;
 
     MockUser(String name, AccountGroup.UUID[] groupId) {
       super(RefControlTest.this.capabilityControlFactory, AccessPath.UNKNOWN);
       username = name;
-      groups = new HashSet<AccountGroup.UUID>(Arrays.asList(groupId));
-      groups.add(registered);
-      groups.add(anonymous);
+      ArrayList<AccountGroup.UUID> groupIds = Lists.newArrayList(groupId);
+      groupIds.add(registered);
+      groupIds.add(anonymous);
+      groups = new ListGroupMembership(groupIds);
     }
 
     @Override
-    public Set<AccountGroup.UUID> getEffectiveGroups() {
+    public GroupMembership getEffectiveGroups() {
       return groups;
     }
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/RegexFilePredicateTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/RegexFilePredicateTest.java
index 3a390b5..ce7b25c 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/RegexFilePredicateTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/RegexFilePredicateTest.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.query.change;
 
-import com.google.gerrit.reviewdb.Change;
-import com.google.gwtorm.client.OrmException;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gwtorm.server.OrmException;
 
 import junit.framework.TestCase;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
index d31bd3c..8750ee4 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaCreatorTest.java
@@ -14,12 +14,12 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.testutil.InMemoryDatabase;
-import com.google.gwtorm.client.OrmException;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
 
 import junit.framework.TestCase;
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
index 7d69672..39cbfe4 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.GerritPersonIdentProvider;
 import com.google.gerrit.server.config.AllProjectsName;
@@ -24,9 +24,9 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 import com.google.gerrit.testutil.InMemoryDatabase;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
-import com.google.gwtorm.client.StatementExecutor;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.gwtorm.server.StatementExecutor;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.TypeLiteral;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java
index 0d84a93..17fe068 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/tools/hooks/CommitMsgHookTest.java
@@ -388,6 +388,25 @@
             "git://example.com/ fixes this\n"));
   }
 
+  @Test
+  public void testWithFalseTags() throws Exception {
+    assertEquals("foo\n" + //
+	"\n" + //
+	"FakeLine:\n" + //
+	"  foo\n" + //
+	"  bar\n" + //
+	"\n" + //
+	"Change-Id: I67632a37fd2e08a35f766f52fc9a47f4ea868c55\n" + //
+	"RealTag: abc\n", //
+	call("foo\n" + //
+	    "\n" + //
+	    "FakeLine:\n" + //
+	    "  foo\n" + //
+	    "  bar\n" + //
+	    "\n" + //
+	    "RealTag: abc\n"));
+  }
+
   private void hookDoesNotModify(final String in) throws Exception {
     assertEquals(in, call(in));
   }
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
index b2c2fc9..c8e684f 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/util/SubmoduleSectionParserTest.java
@@ -20,9 +20,9 @@
 import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertEquals;
 
-import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.SubmoduleSubscription;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
 import com.google.gerrit.server.git.GitRepositoryManager;
 
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryDatabase.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryDatabase.java
index 82dcbea..a44f84f 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryDatabase.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/InMemoryDatabase.java
@@ -14,9 +14,9 @@
 
 package com.google.gerrit.testutil;
 
-import com.google.gerrit.reviewdb.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.GerritPersonIdentProvider;
 import com.google.gerrit.server.config.AllProjectsName;
@@ -27,10 +27,10 @@
 import com.google.gerrit.server.schema.Current;
 import com.google.gerrit.server.schema.SchemaCreator;
 import com.google.gerrit.server.schema.SchemaVersion;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
 import com.google.gwtorm.jdbc.Database;
 import com.google.gwtorm.jdbc.SimpleDataSource;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Key;
@@ -117,6 +117,9 @@
                   .annotatedWith(GerritPersonIdent.class) //
                   .toProvider(GerritPersonIdentProvider.class);
 
+              bind(AllProjectsName.class)
+                  .toInstance(new AllProjectsName("All-Projects"));
+
               bind(GitRepositoryManager.class) //
                   .to(LocalDiskRepositoryManager.class);
             }
diff --git a/gerrit-sshd/pom.xml b/gerrit-sshd/pom.xml
index c02e108..55e8725 100644
--- a/gerrit-sshd/pom.xml
+++ b/gerrit-sshd/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-sshd</artifactId>
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AbstractGitCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AbstractGitCommand.java
index a72b50e..eb8a5c2 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AbstractGitCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/AbstractGitCommand.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.GitRepositoryManager;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/BaseCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/BaseCommand.java
index 52a0277..a926e77 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/BaseCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/BaseCommand.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.NameKey;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.RequestCleanup;
@@ -60,9 +60,6 @@
   static final int STATUS_NOT_FOUND = PRIVATE_STATUS | 2;
   public static final int STATUS_NOT_ADMIN = PRIVATE_STATUS | 3;
 
-  @Option(name = "--help", usage = "display this help text", aliases = {"-h"})
-  private boolean help;
-
   @SuppressWarnings("unused")
   @Option(name = "--", usage = "end of options", handler = EndOfOptionsHandler.class)
   private boolean endOfOptions;
@@ -155,28 +152,37 @@
    * @see Argument
    */
   protected void parseCommandLine() throws UnloggedFailure {
-    final CmdLineParser clp = newCmdLineParser();
+    parseCommandLine(this);
+  }
+
+  /**
+   * Parses the command line argument, injecting parsed values into fields.
+   * <p>
+   * This method must be explicitly invoked to cause a parse.
+   *
+   * @param options object whose fields declare Option and Argument annotations
+   *        to describe the parameters of the command. Usually {@code this}.
+   * @throws UnloggedFailure if the command line arguments were invalid.
+   * @see Option
+   * @see Argument
+   */
+  protected void parseCommandLine(Object options) throws UnloggedFailure {
+    final CmdLineParser clp = newCmdLineParser(options);
     try {
       clp.parseArgument(argv);
     } catch (IllegalArgumentException err) {
-      if (!help) {
+      if (!clp.wasHelpRequestedByOption()) {
         throw new UnloggedFailure(1, "fatal: " + err.getMessage());
       }
     } catch (CmdLineException err) {
-      if (!help) {
+      if (!clp.wasHelpRequestedByOption()) {
         throw new UnloggedFailure(1, "fatal: " + err.getMessage());
       }
     }
 
-    if (help) {
-      final StringWriter msg = new StringWriter();
-      msg.write(commandName);
-      clp.printSingleLineUsage(msg, null);
-      msg.write('\n');
-
-      msg.write('\n');
-      clp.printUsage(msg, null);
-      msg.write('\n');
+    if (clp.wasHelpRequestedByOption()) {
+      StringWriter msg = new StringWriter();
+      clp.printDetailedUsage(commandName, msg);
       msg.write(usage());
       throw new UnloggedFailure(1, msg.toString());
     }
@@ -187,8 +193,8 @@
   }
 
   /** Construct a new parser for this command's received command line. */
-  protected CmdLineParser newCmdLineParser() {
-    return cmdLineParserFactory.create(this);
+  protected CmdLineParser newCmdLineParser(Object options) {
+    return cmdLineParserFactory.create(options);
   }
 
   /**
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
index 805549e..a96a661 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/NoShell.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/NoShell.java
index cc9d6ab..be513b3 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/NoShell.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/NoShell.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.ssh.SshInfo;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheEntry.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheEntry.java
index 81e019e..0d2f1fc 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheEntry.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheEntry.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 
 import java.security.PublicKey;
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheImpl.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheImpl.java
index c5f64f7..1f5ac28 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheImpl.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshKeyCacheImpl.java
@@ -14,18 +14,18 @@
 
 package com.google.gerrit.sshd;
 
-import static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME;
+import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
 
 import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountSshKey;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.cache.Cache;
 import com.google.gerrit.server.cache.CacheModule;
 import com.google.gerrit.server.cache.EntryCreator;
 import com.google.gerrit.server.ssh.SshKeyCache;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Module;
 import com.google.inject.Singleton;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
index 816955d..54b0bb5 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
@@ -17,9 +17,9 @@
 import static com.google.inject.Scopes.SINGLETON;
 
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.PeerDaemonUser;
@@ -32,6 +32,7 @@
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.ssh.SshInfo;
+import com.google.gerrit.server.util.RequestScopePropagator;
 import com.google.gerrit.sshd.args4j.AccountGroupIdHandler;
 import com.google.gerrit.sshd.args4j.AccountGroupUUIDHandler;
 import com.google.gerrit.sshd.args4j.AccountIdHandler;
@@ -39,14 +40,9 @@
 import com.google.gerrit.sshd.args4j.ProjectControlHandler;
 import com.google.gerrit.sshd.args4j.SocketAddressHandler;
 import com.google.gerrit.sshd.commands.DefaultCommandModule;
-import com.google.gerrit.sshd.commands.ProjectNode;
 import com.google.gerrit.sshd.commands.QueryShell;
 import com.google.gerrit.util.cli.CmdLineParser;
-import com.google.gerrit.util.cli.OptionHandlerFactory;
 import com.google.gerrit.util.cli.OptionHandlerUtil;
-import com.google.inject.Key;
-import com.google.inject.TypeLiteral;
-import com.google.inject.assistedinject.FactoryProvider;
 import com.google.inject.servlet.RequestScoped;
 
 import org.apache.sshd.common.KeyPairProvider;
@@ -61,6 +57,7 @@
   @Override
   protected void configure() {
     bindScope(RequestScoped.class, SshScope.REQUEST);
+    bind(RequestScopePropagator.class).to(SshScope.Propagator.class);
 
     configureRequestScope();
     configureCmdLineParser();
@@ -81,7 +78,6 @@
     bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON);
     bind(AccountManager.class);
     factory(ChangeUserName.Factory.class);
-    factory(ProjectNode.Factory.class);
 
     bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class);
     bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON);
@@ -129,14 +125,6 @@
 
   private <T> void registerOptionHandler(Class<T> type,
       Class<? extends OptionHandler<T>> impl) {
-    final Key<OptionHandlerFactory<T>> key = OptionHandlerUtil.keyFor(type);
-
-    final TypeLiteral<OptionHandlerFactory<T>> factoryType =
-        new TypeLiteral<OptionHandlerFactory<T>>() {};
-
-    final TypeLiteral<? extends OptionHandler<T>> implType =
-        TypeLiteral.get(impl);
-
-    bind(key).toProvider(FactoryProvider.newFactory(factoryType, implType));
+    install(OptionHandlerUtil.moduleFor(type, impl));
   }
 }
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 d32d429..f923d80 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
@@ -15,6 +15,7 @@
 package com.google.gerrit.sshd;
 
 import com.google.gerrit.server.RequestCleanup;
+import com.google.gerrit.server.util.ThreadLocalRequestScopePropagator;
 import com.google.inject.Key;
 import com.google.inject.OutOfScopeException;
 import com.google.inject.Provider;
@@ -93,21 +94,32 @@
   static class ContextProvider implements Provider<Context> {
     @Override
     public Context get() {
-      return getContext();
+      return requireContext();
     }
   }
 
   static class SshSessionProvider implements Provider<SshSession> {
     @Override
     public SshSession get() {
-      return getContext().getSession();
+      return requireContext().getSession();
+    }
+  }
+
+  static class Propagator extends ThreadLocalRequestScopePropagator<Context> {
+    Propagator() {
+      super(REQUEST, current);
+    }
+
+    @Override
+    protected Context continuingContext(Context ctx) {
+      return ctx.subContext(ctx.getSession(), ctx.getCommandLine());
     }
   }
 
   private static final ThreadLocal<Context> current =
       new ThreadLocal<Context>();
 
-  private static Context getContext() {
+  private static Context requireContext() {
     final Context ctx = current.get();
     if (ctx == null) {
       throw new OutOfScopeException("Not in command/request");
@@ -126,7 +138,7 @@
     public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
       return new Provider<T>() {
         public T get() {
-          return getContext().get(key, creator);
+          return requireContext().get(key, creator);
         }
 
         @Override
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshUtil.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshUtil.java
index 65cfcdb..da245a3 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshUtil.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshUtil.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.sshd.common.KeyPairProvider;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
index 199d210..492966e 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd;
 
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
index f269541..307a10a 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.args4j;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -29,11 +29,10 @@
 public class AccountGroupIdHandler extends OptionHandler<AccountGroup.Id> {
   private final GroupCache groupCache;
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public AccountGroupIdHandler(final GroupCache groupCache,
       @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
-      @Assisted final Setter setter) {
+      @Assisted final Setter<AccountGroup.Id> setter) {
     super(parser, option, setter);
     this.groupCache = groupCache;
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupUUIDHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupUUIDHandler.java
index 90b4987..49bf695 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupUUIDHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupUUIDHandler.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.args4j;
 
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -29,11 +29,10 @@
 public class AccountGroupUUIDHandler extends OptionHandler<AccountGroup.UUID> {
   private final GroupCache groupCache;
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public AccountGroupUUIDHandler(final GroupCache groupCache,
       @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
-      @Assisted final Setter setter) {
+      @Assisted final Setter<AccountGroup.UUID> setter) {
     super(parser, option, setter);
     this.groupCache = groupCache;
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
index 1f6454b..d54ae34 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
@@ -14,14 +14,14 @@
 
 package com.google.gerrit.sshd.args4j;
 
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.account.AccountException;
 import com.google.gerrit.server.account.AccountManager;
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.AuthRequest;
 import com.google.gerrit.server.config.AuthConfig;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -37,13 +37,12 @@
   private final AccountManager accountManager;
   private final AuthType authType;
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public AccountIdHandler(final AccountResolver accountResolver,
       final AccountManager accountManager,
       final AuthConfig authConfig,
       @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
-      @Assisted final Setter setter) {
+      @Assisted final Setter<Account.Id> setter) {
     super(parser, option, setter);
     this.accountResolver = accountResolver;
     this.accountManager = accountManager;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
index 847184d..2d6a4df 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.args4j;
 
-import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
@@ -26,10 +26,10 @@
 import org.kohsuke.args4j.spi.Setter;
 
 public class PatchSetIdHandler extends OptionHandler<PatchSet.Id> {
-  @SuppressWarnings({"unchecked", "rawtypes"})
+
   @Inject
   public PatchSetIdHandler(@Assisted final CmdLineParser parser,
-      @Assisted final OptionDef option, @Assisted final Setter setter) {
+      @Assisted final OptionDef option, @Assisted final Setter<PatchSet.Id> setter) {
     super(parser, option, setter);
   }
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
index 1e0c3a6..e0f7c4c 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.args4j;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.inject.Inject;
@@ -30,12 +30,11 @@
 public class ProjectControlHandler extends OptionHandler<ProjectControl> {
   private final ProjectControl.Factory projectControlFactory;
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public ProjectControlHandler(
       final ProjectControl.Factory projectControlFactory,
       @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
-      @Assisted final Setter setter) {
+      @Assisted final Setter<ProjectControl> setter) {
     super(parser, option, setter);
     this.projectControlFactory = projectControlFactory;
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
index 50e41ae..454a084 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
@@ -28,10 +28,10 @@
 import java.net.SocketAddress;
 
 public class SocketAddressHandler extends OptionHandler<SocketAddress> {
-  @SuppressWarnings({"unchecked", "rawtypes"})
+
   @Inject
   public SocketAddressHandler(@Assisted final CmdLineParser parser,
-      @Assisted final OptionDef option, @Assisted final Setter setter) {
+      @Assisted final OptionDef option, @Assisted final Setter<SocketAddress> setter) {
     super(parser, option, setter);
   }
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
index 434230f..3df73a8 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
@@ -25,10 +25,10 @@
 import org.kohsuke.args4j.spi.Setter;
 
 public class SubcommandHandler extends OptionHandler<String> {
-  @SuppressWarnings({"unchecked", "rawtypes"})
+
   @Inject
   public SubcommandHandler(@Assisted final CmdLineParser parser,
-      @Assisted final OptionDef option, @Assisted final Setter setter) {
+      @Assisted final OptionDef option, @Assisted final Setter<String> setter) {
     super(parser, option, setter);
   }
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
index f3bd051..950bf341 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.commands;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.ProjectConfig;
@@ -224,7 +224,7 @@
         // If we can't get it from the cache, pretend it's not present.
         break;
       }
-      p = getParentName(e.getProject());
+      p = e.getProject().getParent(allProjectsName);
     }
     return parents;
   }
@@ -238,28 +238,10 @@
         continue;
       }
 
-      if (parentName.equals(getParentName(e.getProject()))) {
+      if (parentName.equals(e.getProject().getParent(projectName))) {
         childProjects.add(e.getProject());
       }
     }
     return childProjects;
   }
-
-  /**
-   * Returns the project parent name.
-   *
-   * @return Project parent name, <code>null</code> for the 'All-Projects' root
-   *         project
-   */
-  private Project.NameKey getParentName(final Project project) {
-    if (project.getParent() != null) {
-      return project.getParent();
-    }
-
-    if (project.getNameKey().equals(allProjectsName)) {
-      return null;
-    }
-
-    return allProjectsName;
-  }
 }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
index cc23d1d..a1b8988 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
@@ -15,8 +15,8 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.data.ApprovalType;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
 
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
index b46a2f2..38e0bcb 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
@@ -15,20 +15,20 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.errors.InvalidSshKeyException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountExternalId;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.AccountGroupMember;
-import com.google.gerrit.reviewdb.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.AccountSshKey;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountExternalId;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroupMember;
+import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
+import com.google.gerrit.reviewdb.client.AccountSshKey;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountByEmailCache;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.ssh.SshKeyCache;
 import com.google.gerrit.sshd.BaseCommand;
-import com.google.gwtorm.client.OrmDuplicateKeyException;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmDuplicateKeyException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
index 05e6e59..98202e2 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
@@ -16,8 +16,8 @@
 
 import com.google.gerrit.common.errors.NameAlreadyUsedException;
 import com.google.gerrit.common.errors.PermissionDeniedException;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.account.PerformCreateGroup;
 import com.google.gerrit.sshd.BaseCommand;
 import com.google.inject.Inject;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
index f0327c5..a93cab1 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
@@ -15,9 +15,9 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.errors.ProjectCreationFailedException;
-import com.google.gerrit.reviewdb.AccountGroup;
-import com.google.gerrit.reviewdb.Project;
-import com.google.gerrit.reviewdb.Project.SubmitType;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.project.CreateProject;
 import com.google.gerrit.server.project.CreateProjectArgs;
@@ -32,7 +32,6 @@
 import org.kohsuke.args4j.Option;
 
 import java.io.PrintWriter;
-
 import java.util.List;
 
 /** Create a new project. **/
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
index 5cee06e..16461b6 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -36,7 +36,7 @@
 
     command(gerrit).toProvider(new DispatchCommandProvider(gerrit));
     command(gerrit, "flush-caches").to(FlushCaches.class);
-    command(gerrit, "ls-projects").to(ListProjects.class);
+    command(gerrit, "ls-projects").to(ListProjectsCommand.class);
     command(gerrit, "ls-groups").to(ListGroupsCommand.class);
     command(gerrit, "query").to(Query.class);
     command(gerrit, "show-caches").to(ShowCaches.class);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java
index fd34ab5..e0b988e 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListGroupsCommand.java
@@ -17,13 +17,13 @@
 import com.google.gerrit.common.data.GroupDetail;
 import com.google.gerrit.common.data.GroupList;
 import com.google.gerrit.common.errors.NoSuchGroupException;
-import com.google.gerrit.server.account.VisibleGroups;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.AccountGroup;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.account.VisibleGroups;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.sshd.BaseCommand;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
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
new file mode 100644
index 0000000..d0bbc72
--- /dev/null
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjectsCommand.java
@@ -0,0 +1,43 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.sshd.commands;
+
+import com.google.gerrit.server.project.ListProjects;
+import com.google.gerrit.sshd.BaseCommand;
+import com.google.inject.Inject;
+
+import org.apache.sshd.server.Environment;
+
+final class ListProjectsCommand extends BaseCommand {
+  @Inject
+  private ListProjects impl;
+
+  @Override
+  public void start(final Environment env) {
+    startThread(new CommandRunnable() {
+      @Override
+      public void run() throws Exception {
+        parseCommandLine(impl);
+        if (impl.isShowTree() && (impl.getShowBranch() != null)) {
+          throw new UnloggedFailure(1, "fatal: --tree and --show-branch options are not compatible.");
+        }
+        if (impl.isShowTree() && impl.isShowDescription()) {
+          throw new UnloggedFailure(1, "fatal: --tree and --description options are not compatible.");
+        }
+        impl.display(out);
+      }
+    });
+  }
+}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java
index 9bca0e5..d9a1c3f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java
@@ -66,6 +66,11 @@
     processor.setIncludeCommitMessage(on);
   }
 
+  @Option(name = "--dependencies", usage = "Include depends-on and needed-by information")
+  void setDependencies(boolean on) {
+    processor.setIncludeDependencies(on);
+  }
+
   @Argument(index = 0, required = true, multiValued = true, metaVar = "QUERY", usage = "Query to execute")
   private List<String> query;
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/QueryShell.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/QueryShell.java
index e68c747..18ce77f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/QueryShell.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/QueryShell.java
@@ -15,11 +15,11 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.Version;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gson.JsonObject;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
 import com.google.gwtorm.jdbc.JdbcSchema;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
index c2b5e9c..0e7ff83 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
@@ -15,8 +15,9 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.data.Capable;
-import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.AsyncReceiveCommits;
 import com.google.gerrit.server.git.ReceiveCommits;
 import com.google.gerrit.server.git.TransferConfig;
 import com.google.gerrit.server.git.VisibleRefFilter;
@@ -25,8 +26,8 @@
 
 import org.eclipse.jgit.errors.UnpackException;
 import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.AdvertiseRefsHook;
 import org.eclipse.jgit.transport.ReceivePack;
-import org.eclipse.jgit.transport.RefFilter;
 import org.kohsuke.args4j.Option;
 
 import java.io.IOException;
@@ -39,7 +40,7 @@
 /** Receives change upload over SSH using the Git receive-pack protocol. */
 final class Receive extends AbstractGitCommand {
   @Inject
-  private ReceiveCommits.Factory factory;
+  private AsyncReceiveCommits.Factory factory;
 
   @Inject
   private IdentifiedUser currentUser;
@@ -69,7 +70,8 @@
       throw new Failure(1, "fatal: receive-pack not permitted on this server");
     }
 
-    final ReceiveCommits receive = factory.create(projectControl, repo);
+    final ReceiveCommits receive = factory.create(projectControl, repo)
+        .getReceiveCommits();
 
     Capable r = receive.canUpload();
     if (r != Capable.OK) {
@@ -97,17 +99,17 @@
       msg.append("Unpack error on project \""
           + projectControl.getProject().getName() + "\":\n");
 
-      msg.append("  RefFilter: " + rp.getRefFilter());
-      if (rp.getRefFilter() == RefFilter.DEFAULT) {
+      msg.append("  AdvertiseRefsHook: " + rp.getAdvertiseRefsHook());
+      if (rp.getAdvertiseRefsHook() == AdvertiseRefsHook.DEFAULT) {
         msg.append("DEFAULT");
-      } else if (rp.getRefFilter() instanceof VisibleRefFilter) {
+      } else if (rp.getAdvertiseRefsHook() instanceof VisibleRefFilter) {
         msg.append("VisibleRefFilter");
       } else {
-        msg.append(rp.getRefFilter().getClass());
+        msg.append(rp.getAdvertiseRefsHook().getClass());
       }
       msg.append("\n");
 
-      if (rp.getRefFilter() instanceof VisibleRefFilter) {
+      if (rp.getAdvertiseRefsHook() instanceof VisibleRefFilter) {
         Map<String, Ref> adv = rp.getAdvertisedRefs();
         msg.append("  Visible references (" + adv.size() + "):\n");
         for (Ref ref : adv.values()) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/RenameGroupCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/RenameGroupCommand.java
index b6d5bf5..5b6cf39 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/RenameGroupCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/RenameGroupCommand.java
@@ -18,7 +18,7 @@
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.server.account.PerformRenameGroup;
 import com.google.gerrit.sshd.BaseCommand;
-import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Replicate.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Replicate.java
index 9dc8671..bc4e0bb 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Replicate.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Replicate.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.commands;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.PushAllProjectsOp;
 import com.google.gerrit.server.git.ReplicationQueue;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index 8eb6058..640adbf 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -17,14 +17,12 @@
 import com.google.gerrit.common.data.ApprovalType;
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.common.data.ReviewResult;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.reviewdb.client.ApprovalCategory;
+import com.google.gerrit.reviewdb.client.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.changedetail.AbandonChange;
 import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
 import com.google.gerrit.server.changedetail.PublishDraft;
@@ -32,15 +30,13 @@
 import com.google.gerrit.server.changedetail.Submit;
 import com.google.gerrit.server.mail.EmailException;
 import com.google.gerrit.server.patch.PublishComments;
-import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gerrit.server.workflow.FunctionState;
 import com.google.gerrit.sshd.BaseCommand;
 import com.google.gerrit.util.cli.CmdLineParser;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
@@ -61,8 +57,8 @@
       LoggerFactory.getLogger(ReviewCommand.class);
 
   @Override
-  protected final CmdLineParser newCmdLineParser() {
-    final CmdLineParser parser = super.newCmdLineParser();
+  protected final CmdLineParser newCmdLineParser(Object options) {
+    final CmdLineParser parser = super.newCmdLineParser(options);
     for (ApproveOption c : optionList) {
       parser.addOption(c, c);
     }
@@ -111,24 +107,15 @@
   private ReviewDb db;
 
   @Inject
-  private IdentifiedUser currentUser;
-
-  @Inject
   private ApprovalTypes approvalTypes;
 
   @Inject
-  private ChangeControl.Factory changeControlFactory;
-
-  @Inject
   private DeleteDraftPatchSet.Factory deleteDraftPatchSetFactory;
 
   @Inject
   private AbandonChange.Factory abandonChangeFactory;
 
   @Inject
-  private FunctionState.Factory functionStateFactory;
-
-  @Inject
   private PublishComments.Factory publishCommentsFactory;
 
   @Inject
@@ -205,10 +192,6 @@
   private void approveOne(final PatchSet.Id patchSetId) throws
       NoSuchChangeException, OrmException, EmailException, Failure {
 
-    final Change.Id changeId = patchSetId.getParentKey();
-
-    ChangeControl changeControl = changeControlFactory.validateFor(changeId);
-
     if (changeComment == null) {
       changeComment = "";
     }
@@ -217,7 +200,6 @@
     for (ApproveOption ao : optionList) {
       Short v = ao.value();
       if (v != null) {
-        assertScoreIsAllowed(patchSetId, changeControl, ao, v);
         aps.add(new ApprovalCategoryValue.Id(ao.getCategoryId(), v));
       }
     }
@@ -362,22 +344,6 @@
     return projectControl.getProject().getNameKey().equals(change.getProject());
   }
 
-  private void assertScoreIsAllowed(final PatchSet.Id patchSetId,
-      final ChangeControl changeControl, ApproveOption ao, Short v)
-      throws UnloggedFailure {
-    final PatchSetApproval psa =
-        new PatchSetApproval(new PatchSetApproval.Key(patchSetId, currentUser
-            .getAccountId(), ao.getCategoryId()), v);
-    final FunctionState fs =
-        functionStateFactory.create(changeControl, patchSetId,
-            Collections.<PatchSetApproval> emptyList());
-    psa.setValue(v);
-    fs.normalize(approvalTypes.byId(psa.getCategoryId()), psa);
-    if (v != psa.getValue()) {
-      throw error(ao.name() + "=" + ao.value() + " not permitted");
-    }
-  }
-
   private void initOptionList() {
     optionList = new ArrayList<ApproveOption>();
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
index 985c2d5..6e1a32b 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
@@ -15,19 +15,19 @@
 package com.google.gerrit.sshd.commands;
 
 import com.google.gerrit.common.data.ReviewerResult;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSet;
-import com.google.gerrit.reviewdb.RevId;
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.patch.AddReviewer;
 import com.google.gerrit.server.patch.RemoveReviewer;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.sshd.BaseCommand;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.ResultSet;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.ResultSet;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowQueue.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowQueue.java
index 80a6c11..e835ffe 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowQueue.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ShowQueue.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.commands;
 
-import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.git.WorkQueue.ProjectTask;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java
index b072abf..46eb788 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java
@@ -14,7 +14,7 @@
 
 package com.google.gerrit.sshd.commands;
 
-import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.git.TagCache;
 import com.google.gerrit.server.git.TransferConfig;
 import com.google.gerrit.server.git.VisibleRefFilter;
@@ -45,8 +45,8 @@
 
     final UploadPack up = new UploadPack(repo);
     if (!projectControl.allRefsAreVisible()) {
-      up.setRefFilter(new VisibleRefFilter(tagCache, repo, projectControl,
-          db.get(), true));
+      up.setAdvertiseRefsHook(new VisibleRefFilter(tagCache, repo,
+          projectControl, db.get(), true));
     }
     up.setPackConfig(config.getPackConfig());
     up.setTimeout(config.getTimeout());
diff --git a/gerrit-util-cli/pom.xml b/gerrit-util-cli/pom.xml
index 401a2ba..4ecbda4 100644
--- a/gerrit-util-cli/pom.xml
+++ b/gerrit-util-cli/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-util-cli</artifactId>
@@ -39,12 +39,12 @@
     </dependency>
 
     <dependency>
-      <groupId>com.google.code.guice</groupId>
+      <groupId>com.google.inject</groupId>
       <artifactId>guice</artifactId>
     </dependency>
 
     <dependency>
-      <groupId>com.google.code.guice</groupId>
+      <groupId>com.google.inject.extensions</groupId>
       <artifactId>guice-assistedinject</artifactId>
     </dependency>
   </dependencies>
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
index d5a2a98..de2f7e9 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -42,13 +42,19 @@
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.IllegalAnnotationError;
+import org.kohsuke.args4j.NamedOptionDef;
 import org.kohsuke.args4j.Option;
 import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.BooleanOptionHandler;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Setter;
 
+import java.io.StringWriter;
 import java.io.Writer;
+import java.lang.annotation.Annotation;
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.ResourceBundle;
 
 /**
@@ -60,6 +66,7 @@
  * args4j style format prior to invoking args4j for parsing.
  */
 public class CmdLineParser {
+
   public interface Factory {
     CmdLineParser create(Object bean);
   }
@@ -102,6 +109,19 @@
     parser.printUsage(out, rb);
   }
 
+  public void printDetailedUsage(String name, StringWriter out) {
+    out.write(name);
+    printSingleLineUsage(out, null);
+    out.write('\n');
+    out.write('\n');
+    printUsage(out, null);
+    out.write('\n');
+  }
+
+  public boolean wasHelpRequestedByOption() {
+    return parser.help.value;
+  }
+
   public void parseArgument(final String... args) throws CmdLineException {
     final ArrayList<String> tmp = new ArrayList<String>(args.length);
     for (int argi = 0; argi < args.length; argi++) {
@@ -123,13 +143,86 @@
 
       tmp.add(str);
     }
-
     parser.parseArgument(tmp.toArray(new String[tmp.size()]));
   }
 
+  public void parseOptionMap(Map<String, String[]> parameters)
+      throws CmdLineException {
+    ArrayList<String> tmp = new ArrayList<String>();
+    for (Map.Entry<String, String[]> ent : parameters.entrySet()) {
+      String name = ent.getKey();
+      if (!name.startsWith("-")) {
+        if (name.length() == 1) {
+          name = "-" + name;
+        } else {
+          name = "--" + name;
+        }
+      }
+
+      if (findHandler(name) instanceof BooleanOptionHandler) {
+        boolean on = false;
+        for (String value : ent.getValue()) {
+          on = toBoolean(ent.getKey(), value);
+        }
+        if (on) {
+          tmp.add(name);
+        }
+      } else {
+        for (String value : ent.getValue()) {
+          tmp.add(name);
+          tmp.add(value);
+        }
+      }
+    }
+    parser.parseArgument(tmp.toArray(new String[tmp.size()]));
+  }
+
+  @SuppressWarnings("rawtypes")
+  private OptionHandler findHandler(String name) {
+    for (OptionHandler handler : parser.options) {
+      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;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  private boolean toBoolean(String name, String value) throws CmdLineException {
+    if ("true".equals(value) || "t".equals(value)
+        || "yes".equals(value) || "y".equals(value)
+        || "on".equals(value)
+        || "1".equals(value)
+        || value == null || "".equals(value)) {
+      return true;
+    }
+
+    if ("false".equals(value) || "f".equals(value)
+        || "no".equals(value) || "n".equals(value)
+        || "off".equals(value)
+        || "0".equals(value)) {
+      return false;
+    }
+
+    throw new CmdLineException(parser, String.format(
+        "invalid boolean \"%s=%s\"", name, value));
+  }
+
   private class MyParser extends org.kohsuke.args4j.CmdLineParser {
+    @SuppressWarnings("rawtypes")
+    private List<OptionHandler> options;
+    private HelpOption help;
+
     MyParser(final Object bean) {
       super(bean);
+      ensureOptionsInitialized();
     }
 
     @SuppressWarnings({"unchecked", "rawtypes"})
@@ -137,7 +230,7 @@
     protected OptionHandler createOptionHandler(final OptionDef option,
         final Setter setter) {
       if (isHandlerSpecified(option) || isEnum(setter) || isPrimitive(setter)) {
-        return super.createOptionHandler(option, setter);
+        return add(super.createOptionHandler(option, setter));
       }
 
       final Key<OptionHandlerFactory<?>> key =
@@ -145,12 +238,28 @@
       Injector i = injector;
       while (i != null) {
         if (i.getBindings().containsKey(key)) {
-          return i.getInstance(key).create(this, option, setter);
+          return add(i.getInstance(key).create(this, option, setter));
         }
         i = i.getParent();
       }
 
-      return super.createOptionHandler(option, setter);
+      return add(super.createOptionHandler(option, setter));
+    }
+
+    @SuppressWarnings("rawtypes")
+    private OptionHandler add(OptionHandler handler) {
+      ensureOptionsInitialized();
+      options.add(handler);
+      return handler;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private void ensureOptionsInitialized() {
+      if (options == null) {
+        help = new HelpOption();
+        options = new ArrayList<OptionHandler>();
+        addOption(help, help);
+      }
     }
 
     private boolean isHandlerSpecified(final OptionDef option) {
@@ -165,4 +274,63 @@
       return setter.getType().isPrimitive();
     }
   }
+
+  private static class HelpOption implements Option, Setter<Boolean> {
+    private boolean value;
+
+    @Override
+    public String name() {
+      return "--help";
+    }
+
+    @Override
+    public String[] aliases() {
+      return new String[] {"-h"};
+    }
+
+    @Override
+    public String usage() {
+      return "display this help text";
+    }
+
+    @Override
+    public void addValue(Boolean val) {
+      value = val;
+    }
+
+    @Override
+    public Class<? extends OptionHandler<Boolean>> handler() {
+      return BooleanOptionHandler.class;
+    }
+
+    @Override
+    public String metaVar() {
+      return "";
+    }
+
+    @Override
+    public boolean multiValued() {
+      return false;
+    }
+
+    @Override
+    public boolean required() {
+      return false;
+    }
+
+    @Override
+    public Class<? extends Annotation> annotationType() {
+      return Option.class;
+    }
+
+    @Override
+    public Class<Boolean> getType() {
+      return Boolean.class;
+    }
+
+    @Override
+    public boolean isMultiValued() {
+      return multiValued();
+    }
+  }
 }
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
index 0009d05..8e99778 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
@@ -20,7 +20,6 @@
 
 /** Creates an args4j OptionHandler through a Guice Injector. */
 public interface OptionHandlerFactory<T> {
-  @SuppressWarnings("rawtypes")
-  OptionHandler create(org.kohsuke.args4j.CmdLineParser cmdLineParser,
-      OptionDef optionDef, Setter setter);
+  OptionHandler<T> create(org.kohsuke.args4j.CmdLineParser cmdLineParser,
+      OptionDef optionDef, Setter<T> setter);
 }
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerUtil.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerUtil.java
index ab67397..7af544c 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerUtil.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerUtil.java
@@ -15,8 +15,11 @@
 package com.google.gerrit.util.cli;
 
 import com.google.inject.Key;
-import com.google.inject.TypeLiteral;
-import com.google.inject.internal.MoreTypes.ParameterizedTypeImpl;
+import com.google.inject.Module;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+import com.google.inject.util.Types;
+
+import org.kohsuke.args4j.spi.OptionHandler;
 
 import java.lang.reflect.Type;
 
@@ -25,10 +28,21 @@
   /** Generate a key for an {@link OptionHandlerFactory} in Guice. */
   @SuppressWarnings("unchecked")
   public static <T> Key<OptionHandlerFactory<T>> keyFor(final Class<T> valueType) {
-    final Type factoryType =
-        new ParameterizedTypeImpl(null, OptionHandlerFactory.class, valueType);
+    final Type factoryType = Types.newParameterizedType(OptionHandlerFactory.class, valueType);
+    return (Key<OptionHandlerFactory<T>>) Key.get(factoryType);
+  }
 
-    return (Key<OptionHandlerFactory<T>>) Key.get(TypeLiteral.get(factoryType));
+  @SuppressWarnings("unchecked")
+  private static <T> Key<OptionHandler<T>> handlerOf(Class<T> type) {
+    final Type handlerType = Types.newParameterizedTypeWithOwner(null, OptionHandler.class, type);
+    return (Key<OptionHandler<T>>) Key.get(handlerType);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> Module moduleFor(final Class<T> type, Class<? extends OptionHandler<T>> impl) {
+    return new FactoryModuleBuilder()
+        .implement(handlerOf(type), impl)
+        .build(keyFor(type));
   }
 
   private OptionHandlerUtil() {
diff --git a/gerrit-util-ssl/pom.xml b/gerrit-util-ssl/pom.xml
index eefca62..2e49d47 100644
--- a/gerrit-util-ssl/pom.xml
+++ b/gerrit-util-ssl/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-util-ssl</artifactId>
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index ad58440..733d976a 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>com.google.gerrit</groupId>
     <artifactId>gerrit-parent</artifactId>
-    <version>2.3-SNAPSHOT</version>
+    <version>2.4-SNAPSHOT</version>
   </parent>
 
   <artifactId>gerrit-war</artifactId>
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
index 3bbcc98..b97df3f 100644
--- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
+++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
@@ -14,11 +14,11 @@
 
 package com.google.gerrit.httpd;
 
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gerrit.reviewdb.SystemConfig;
+import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.SitePath;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.client.SchemaFactory;
+import com.google.gwtorm.server.OrmException;
+import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
index ecb0977..01b4a44 100644
--- a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
+++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.httpd.auth.openid.OpenIdModule;
 import com.google.gerrit.lifecycle.LifecycleManager;
 import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.reviewdb.AuthType;
+import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.gerrit.server.config.AuthConfigModule;
 import com.google.gerrit.server.config.CanonicalWebUrlModule;
@@ -33,6 +33,7 @@
 import com.google.gerrit.server.contact.HttpContactStoreConnection;
 import com.google.gerrit.server.git.LocalDiskRepositoryManager;
 import com.google.gerrit.server.git.PushReplication;
+import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
 import com.google.gerrit.server.mail.SmtpEmailSender;
@@ -190,6 +191,7 @@
     final List<Module> modules = new ArrayList<Module>();
     modules.add(new WorkQueue.Module());
     modules.add(new ChangeHookRunner.Module());
+    modules.add(new ReceiveCommitsExecutorModule());
     modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
     modules.add(new EhcachePoolImpl.Module());
     modules.add(new SmtpEmailSender.Module());
diff --git a/pom.xml b/pom.xml
index f3f7c64..1933329 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-parent</artifactId>
   <packaging>pom</packaging>
-  <version>2.3-SNAPSHOT</version>
+  <version>2.4-SNAPSHOT</version>
 
   <name>Gerrit Code Review - Parent</name>
   <url>http://code.google.com/p/gerrit/</url>
@@ -46,13 +46,13 @@
   </issueManagement>
 
   <properties>
-    <jgitVersion>1.1.0.201109151100-r.141-gcd958ba</jgitVersion>
-    <gwtormVersion>1.2</gwtormVersion>
-    <gwtjsonrpcVersion>1.2.5</gwtjsonrpcVersion>
+    <jgitVersion>1.3.0.201202151440-r.75-gff13648</jgitVersion>
+    <gwtormVersion>1.4</gwtormVersion>
+    <gwtjsonrpcVersion>1.3</gwtjsonrpcVersion>
     <gwtexpuiVersion>1.2.5</gwtexpuiVersion>
     <gwtVersion>2.3.0</gwtVersion>
     <slf4jVersion>1.6.1</slf4jVersion>
-    <guiceVersion>2.0</guiceVersion>
+    <guiceVersion>3.0</guiceVersion>
     <jettyVersion>7.2.1.v20101111</jettyVersion>
 
     <gwt.compileReport>false</gwt.compileReport>
@@ -486,6 +486,11 @@
         <type>pom</type>
         <exclusions>
           <exclusion>
+            <!-- conflicts with our use of guice 3.0 -->
+            <groupId>com.google.code.guice</groupId>
+            <artifactId>guice</artifactId>
+          </exclusion>
+          <exclusion>
             <!-- jug-1.1 is LGPL, and the source has been lost -->
             <groupId>jug</groupId>
             <artifactId>jug</artifactId>
@@ -557,19 +562,19 @@
       </dependency>
 
       <dependency>
-        <groupId>com.google.code.guice</groupId>
+        <groupId>com.google.inject</groupId>
         <artifactId>guice</artifactId>
         <version>${guiceVersion}</version>
       </dependency>
 
       <dependency>
-        <groupId>com.google.code.guice</groupId>
+        <groupId>com.google.inject.extensions</groupId>
         <artifactId>guice-servlet</artifactId>
         <version>${guiceVersion}</version>
       </dependency>
 
       <dependency>
-        <groupId>com.google.code.guice</groupId>
+        <groupId>com.google.inject.extensions</groupId>
         <artifactId>guice-assistedinject</artifactId>
         <version>${guiceVersion}</version>
       </dependency>
diff --git a/tools/gitlog2asciidoc.py b/tools/gitlog2asciidoc.py
new file mode 100755
index 0000000..dfbad82
--- /dev/null
+++ b/tools/gitlog2asciidoc.py
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+from optparse import OptionParser
+import re
+import subprocess
+import sys
+
+"""
+This script generates a release note from the output of git log
+between the specified tags.
+
+Options:
+--issues          Show output the commits with issues associated with them.
+--issue-numbers   Show outputs issue numbers of the commits with issues
+                  associated with them
+
+Arguments:
+since -- tag name
+until -- tag name
+
+Example Input:
+
+   * <commit subject>
+   +
+   <commit message>
+
+   Bug: issue 123
+   Change-Id: <change id>
+   Signed-off-by: <name>
+
+Expected Output:
+
+   * issue 123 <commit subject>
+   +
+   <commit message>
+"""
+
+parser = OptionParser(usage='usage: %prog [options] <since> <until>')
+
+parser.add_option('-i', '--issues', action='store_true',
+                  dest='issues_only', default=False,
+                  help='only output the commits with issues association')
+
+parser.add_option('-n', '--issue-numbers', action='store_true',
+                  dest='issue_numbers_only', default=False,
+                  help='only outputs issue numbers of the commits with \
+                        issues association')
+
+(options, args) = parser.parse_args()
+
+if len(args) != 2:
+    parser.error("wrong number of arguments")
+
+issues_only = options.issues_only
+issue_numbers_only = options.issue_numbers_only
+
+since_until = args[0] + '..' + args[1]
+proc = subprocess.Popen(['git', 'log', '--reverse', '--no-merges',
+                         since_until, "--format=* %s%n+%n%b"],
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.STDOUT,)
+
+stdout_value = proc.communicate()[0]
+
+subject = ""
+message = []
+is_issue = False
+
+# regex pattern to match following cases such as Bug: 123, Issue Bug: 123,
+# Bug: GERRIT-123, Bug: issue 123, Bug issue: 123, issue: 123, issue: bug 123
+p = re.compile('bug: GERRIT-|bug(:? issue)?:? |issue(:? bug)?:? ',
+               re.IGNORECASE)
+
+if issue_numbers_only:
+    for line in stdout_value.splitlines(True):
+        if p.match(line):
+            sys.stdout.write(p.sub('', line))
+else:
+    for line in stdout_value.splitlines(True):
+        # Move issue number to subject line
+        if p.match(line):
+            line = p.sub('issue ', line).replace('\n',' ')
+            subject = subject[:2] + line + subject[2:]
+            is_issue = True
+        elif line.startswith('* '):
+            # Write change log for a commit
+            if subject != "":
+                if (not issues_only or is_issue):
+                    # Write subject
+                    sys.stdout.write(subject)
+                    # Write message lines
+                    if message != []:
+                        # Clear + from last line in commit message
+                        message[-1] = '\n'
+                    for m in message:
+                        sys.stdout.write(m)
+            # Start new commit block
+            message = []
+            subject = line
+            is_issue = False
+        # Remove commit footers
+        elif re.match(r'((\w+-)+\w+:)', line):
+            continue
+        # Don't add extra blank line if last one is already blank
+        elif line == '\n' and message and message[-1] != '+\n':
+                message.append('+\n')
+        elif line != '\n':
+            message.append(line)