Merge "When issuing a 'Rebase' the committer will now be the logged in user"
diff --git a/.buckconfig b/.buckconfig
index f6b9349..7c3c02d 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -1,6 +1,7 @@
 [alias]
   api = //:api
   download = //:download
+  download_sources = //:download_sources
   gerrit = //:gerrit
   eclipse = //tools/eclipse:eclipse
   eclipse_project = //tools/eclipse:eclipse_project
diff --git a/.buckversion b/.buckversion
new file mode 100644
index 0000000..dcaab35
--- /dev/null
+++ b/.buckversion
@@ -0,0 +1 @@
+c4df74bef4e101a7e5d0176831825b7946ea64a3
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..be43141
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6.5</pydev_property>
+</pydev_project>
diff --git a/BUCK b/BUCK
index 6dcac95..d467528 100644
--- a/BUCK
+++ b/BUCK
@@ -26,6 +26,7 @@
     '//lib/guice:guice-servlet',
     '//lib:servlet-api-3_0',
   ],
+  export_deps = True,
   visibility = ['PUBLIC'],
 )
 
@@ -37,17 +38,22 @@
     '//gerrit-sshd:sshd',
     '//gerrit-httpd:httpd',
   ],
+  export_deps = True,
   visibility = ['PUBLIC'],
 )
 
 genrule(
   name = 'download',
-  cmd = 'buck build ' +
-    '$(buck audit classpath --dot //tools/eclipse:classpath' +
-    '| egrep \'^  "//lib/\''+
-    '| cut -d\\" -f2' +
-    '| sort | uniq)',
+  cmd = '${//tools:download_all}',
   srcs = [],
-  deps = [],
+  deps = ['//tools:download_all'],
+  out = '__fake.download__',
+)
+
+genrule(
+  name = 'download_sources',
+  cmd = '${//tools:download_all} --src',
+  srcs = [],
+  deps = ['//tools:download_all'],
   out = '__fake.download__',
 )
diff --git a/Documentation/BUCK b/Documentation/BUCK
index a1f5384..47e7b53 100644
--- a/Documentation/BUCK
+++ b/Documentation/BUCK
@@ -10,14 +10,21 @@
     'mkdir -p Documentation/images;' +
     'for s in $SRCS;do ln -s $s Documentation;done;' +
     'mv Documentation/*.{jpg,png} Documentation/images;' +
+    'rm Documentation/licenses.txt;' +
+    'ln -s $SRCDIR/licenses.txt LICENSES.txt;' +
     'zip -qr $OUT *',
   srcs = [genfile(d) for d in HTML] +
-    [genfile('licenses.html')] +
     glob([
       'images/*.jpg',
       'images/*.png',
-    ]),
-  deps = [':' + d for d in HTML] + [':licenses.html'],
+    ]) + [
+    genfile('licenses.html'),
+    genfile('licenses.txt'),
+  ],
+  deps = [':' + d for d in HTML] + [
+    ':licenses.html',
+    ':licenses.txt',
+  ],
   out = 'html.zip',
   visibility = ['PUBLIC'],
 )
diff --git a/Documentation/dev-buck.txt b/Documentation/dev-buck.txt
index 7c99954..c228bb9 100644
--- a/Documentation/dev-buck.txt
+++ b/Documentation/dev-buck.txt
@@ -17,28 +17,30 @@
   ant
 ----
 
-Make sure you have a bin/ directory in your home directory and that it is included in your path:
+Make sure you have a `bin/` directory in your home directory and that
+it is included in your path:
 
 ----
   mkdir ~/bin
   PATH=~/bin:$PATH
 ----
 
-Add a symbolic link in ~/bin to the buck executable:
+Add a symbolic link in `~/bin` to the buck executable:
 
 ----
   ln -s `pwd`/bin/buck ~/bin/
 ----
 
-Verify that buck is accessible:
+Verify that `buck` is accessible:
 
 ----
   which buck
 ----
 
 
-Eclipse Project
----------------
+[[eclipse]]
+Eclipse Integration
+-------------------
 
 
 Generating the Eclipse Project
@@ -57,6 +59,10 @@
 Expand the `gerrit` project, right-click on the `buck-out` folder, select
 'Properties', and then under 'Attributes' check 'Derived'.
 
+Note that if you make any changes in the project configuration that get
+saved to the `.project` file, for example adding Resource Filters on a
+folder, they will be overwritten the next time you run `buck build eclipse`.
+
 
 Refreshing the Classpath
 ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -71,6 +77,19 @@
 ----
 
 
+Attaching Sources
+~~~~~~~~~~~~~~~~~
+
+To save time and bandwidth source JARs are only downloaded by the buck
+build where necessary to compile Java source into JavaScript using the
+GWT compiler.  Additional sources may be obtained, allowing Eclipse to
+show documentation or dive into the implementation of a library JAR:
+
+----
+  buck build download_sources
+----
+
+
 Building on the Command Line
 ----------------------------
 
@@ -144,6 +163,7 @@
 is not regenerated.
 
 
+[[tests]]
 Running Unit Tests
 ------------------
 
@@ -190,6 +210,10 @@
   echo download.MAVEN_CENTRAL = http://nexus.my-company.com/ >>local.properties
 ----
 
+The `local.properties` file may be placed in the root of the gerrit repository
+being built, or in `~/.gerritcodereview/`.  The file in the root of the gerrit
+repository has precedence.
+
 
 Build Process Switch Exit Criteria
 ----------------------------------
diff --git a/Documentation/dev-maven.txt b/Documentation/dev-maven.txt
index 9703c46..c5f8a7a 100644
--- a/Documentation/dev-maven.txt
+++ b/Documentation/dev-maven.txt
@@ -73,7 +73,7 @@
   mvn clean package -DskipTests
 ----
 
-[[run-acceptance-tests]]
+[[tests]]
 Running the Acceptance Tests
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt
index 6d0bc3d..58c836a 100644
--- a/Documentation/dev-readme.txt
+++ b/Documentation/dev-readme.txt
@@ -27,8 +27,12 @@
 To use the Eclipse IDE for development, please see
 link:dev-eclipse.html[Eclipse Setup].
 
-See the link:dev-maven.html[Maven documentation] for more details on
-how to configure the workspace with the Maven build scripts.
+For details on how to configure the Eclipse workspace with Maven
+or Buck, refer to:
+
+1. link:dev-maven.html#eclipse[Eclipse integration with Maven]
+
+2. link:dev-buck.html#eclipse[Eclipse integration with Buck]
 
 
 Mac OS X
@@ -73,7 +77,7 @@
 -------
 
 
-[[run-acceptance-tests]]
+[[tests]]
 Running the Acceptance Tests
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -84,8 +88,12 @@
 started on that site. When the test has finished the Gerrit daemon is
 shutdown.
 
-For instructions on running the integration tests with Maven, please
-click link:dev-maven.html#run-acceptance-tests[here].
+For instructions on running the integration tests with Maven or Buck,
+please refer to:
+
+1. link:dev-maven.html#tests[Running integration tests with Maven]
+
+2. link:dev-buck.html#tests[Running integration tests with Buck]
 
 
 Running the Daemon
@@ -138,51 +146,6 @@
 ----
 
 
-[[test-rest-api]]
-Testing the REST API
-~~~~~~~~~~~~~~~~~~~~
-
-Basic testing of REST API functionality can be done with `curl`:
-
-----
-  curl http://localhost:8080/path/to/api/
-----
-
-By default, `curl` sends `GET` requests.  To test APIs with `PUT` or `POST`,
-an additional argument is required:
-
-----
- curl -X PUT http://localhost:8080/path/to/api/
- curl -X POST http://localhost:8080/path/to/api/
-----
-
-Some REST APIs accept data in the request body of `PUT` and `POST` requests.
-
-Test data can be included from a local file:
-
-----
-  curl -X PUT -d@testdata.txt --header "Content-Type: application/json" http://localhost:8080/path/to/api/
-----
-
-To test APIs that require authentication, the username and password must be specified on
-the command line:
-
-----
- curl --digest --user username:password http://localhost:8080/path/to/api
-----
-
-This makes it easy to switch users for testing of permissions.
-
-It is also possible to test with a username and password from the `.netrc`
-file (on Windows, `_netrc`):
-
-----
- curl --digest -n http://localhost:8080/a/path/to/api/
-----
-
-In both cases, the password should be the user's link:user-upload.html#http[HTTP password].
-
-
 Release Builds
 --------------
 
diff --git a/Documentation/dev-rest-api.txt b/Documentation/dev-rest-api.txt
new file mode 100644
index 0000000..869ac2b
--- /dev/null
+++ b/Documentation/dev-rest-api.txt
@@ -0,0 +1,81 @@
+Gerrit Code Review - REST API Developers' Notes
+===============================================
+
+This document is about developing the REST API.  For details of the
+actual APIs available in Gerrit, please see the
+link:rest-api.html[REST API interface reference].
+
+
+Testing REST API Functionality
+------------------------------
+
+
+Basic Testing
+~~~~~~~~~~~~~
+
+Basic testing of REST API functionality can be done with `curl`:
+
+----
+  curl http://localhost:8080/path/to/api/
+----
+
+By default, `curl` sends `GET` requests.  To test APIs with `PUT`, `POST`,
+or `DELETE`, an additional argument is required:
+
+----
+ curl -X PUT http://localhost:8080/path/to/api/
+ curl -X POST http://localhost:8080/path/to/api/
+ curl -X DELETE http://localhost:8080/path/to/api/
+----
+
+
+Sending Data in the Request
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some REST APIs accept data in the request body of `PUT` and `POST` requests.
+
+Test data can be included from a local file:
+
+----
+  curl -X PUT -d@testdata.txt --header "Content-Type: application/json" http://localhost:8080/path/to/api/
+----
+
+
+Authentication
+~~~~~~~~~~~~~~
+
+To test APIs that require authentication, the username and password must be specified on
+the command line:
+
+----
+ curl --digest --user username:password http://localhost:8080/a/path/to/api/
+----
+
+This makes it easy to switch users for testing of permissions.
+
+It is also possible to test with a username and password from the `.netrc`
+file (on Windows, `_netrc`):
+
+----
+ curl --digest -n http://localhost:8080/a/path/to/api/
+----
+
+In both cases, the password should be the user's link:user-upload.html#http[HTTP password].
+
+
+Verifying Header Content
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To verify the headers returned from a REST API call, use `curl` in verbose mode:
+
+----
+  curl -v -n --digest -X DELETE http://localhost:8080/a/path/to/api/
+----
+
+The headers on both the request and the response will be printed.
+
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
diff --git a/Documentation/project-setup.txt b/Documentation/project-setup.txt
index 244b4b8..36d3c60 100644
--- a/Documentation/project-setup.txt
+++ b/Documentation/project-setup.txt
@@ -108,9 +108,11 @@
 fast-forwarded to the change.
 
 When Gerrit tries to do a merge, by default the merge will only
-succeed if there is no path conflict. By selecting the checkbox
-`Automatically resolve conflicts` Gerrit will try do a content merge
-if a path conflict occurs.
+succeed if there is no path conflict.  A path conflict occurs when
+the same file has also been changed on the other side of the merge.
+
+If `Automatically resolve conflicts` is enabled, Gerrit will try
+to do a content merge when a path conflict occurs.
 
 
 Registering Additional Branches
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 4f9b6a6..748ec186 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -1845,11 +1845,47 @@
   }
 ----
 
+[[list-files]]
+List Files
+~~~~~~~~~~
+[verse]
+'GET /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/'
+
+Lists the files that were modified, added or deleted in a revision.
+
+.Request
+----
+  GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/files/ HTTP/1.0
+----
+
+As result a map is returned that maps the file path to a list of
+link:#file-info[FileInfo] entries. The entries in the map are
+sorted by file path.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  {
+    "/COMMIT_MSG": {
+      "status": "A",
+      "lines_inserted": 7
+    },
+    "gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java": {
+      "lines_inserted": 5,
+      "lines_deleted": 3
+    }
+  }
+----
+
 [[get-content]]
 Get Content
 ~~~~~~~~~~~
 [verse]
-'GET /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#patch-id[\{patch-id\}]/content'
+'GET /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#file-id[\{file-id\}]/content'
 
 Gets the content of a file from a certain revision.
 
@@ -1873,9 +1909,9 @@
 Set Reviewed
 ~~~~~~~~~~~~
 [verse]
-'PUT /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#patch-id[\{patch-id\}]/reviewed'
+'PUT /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#file-id[\{file-id\}]/reviewed'
 
-Marks a patch of a revision as reviewed by the calling user.
+Marks a file of a revision as reviewed by the calling user.
 
 .Request
 ----
@@ -1887,16 +1923,16 @@
   HTTP/1.1 201 Created
 ----
 
-If the patch was already marked as reviewed by the calling user the
+If the file was already marked as reviewed by the calling user the
 response is "`200 OK`".
 
 [[delete-reviewed]]
 Delete Reviewed
 ~~~~~~~~~~~~~~~
 [verse]
-'DELETE /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#patch-id[\{patch-id\}]/reviewed'
+'DELETE /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/files/link:#file-id[\{file-id\}]/reviewed'
 
-Deletes the reviewed flag of the calling user from a patch of a revision.
+Deletes the reviewed flag of the calling user from a file of a revision.
 
 .Request
 ----
@@ -1994,10 +2030,10 @@
 ~~~~~~~~~~~~
 UUID of a draft comment.
 
-[[patch-id]]
-\{patch-id\}
+[[file-id]]
+\{file-id\}
 ~~~~~~~~~~~~
-The file path of the patch.
+The path of the file.
 
 [[revision-id]]
 \{revision-id\}
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index bb83048..1dc8bc8 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -483,6 +483,121 @@
   done.
 ----
 
+[[branch-endpoints]]
+Branch Endpoints
+----------------
+
+[[list-branches]]
+List Branches
+~~~~~~~~~~~~~
+[verse]
+'GET /projects/link:#project-name[\{project-name\}]/branches/'
+
+List the branches of a project.
+
+As result a list of link:#branch-info[BranchInfo] entries is
+returned.
+
+.Request
+----
+  GET /projects/work%2Fmy-project/branches/ HTTP/1.0
+----
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  [
+    {
+      "ref": "HEAD",
+      "revision": "master"
+    },
+    {
+      "ref": "refs/meta/config",
+      "revision": "76016386a0d8ecc7b6be212424978bb45959d668"
+    },
+    {
+      "ref": "refs/heads/master",
+      "revision": "67ebf73496383c6777035e374d2d664009e2aa5c"
+    },
+    {
+      "ref": "refs/heads/stable",
+      "revision": "64ca533bd0eb5252d2fee83f63da67caae9b4674",
+      "can_delete": true
+    }
+  ]
+----
+
+[[get-branch]]
+Get Branch
+~~~~~~~~~~
+[verse]
+'GET /projects/link:#project-name[\{project-name\}]/branches/link:#branch-id[\{branch-id\}]'
+
+Retrieves a branch of a project.
+
+.Request
+----
+  GET /projects/work%2Fmy-project/branches/master HTTP/1.0
+----
+
+As response a link:#branch-info[BranchInfo] entity is returned that
+describes the branch.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  {
+    "ref": "refs/heads/master",
+    "revision": "67ebf73496383c6777035e374d2d664009e2aa5c"
+  }
+----
+
+[[create-branch]]
+Create Branch
+~~~~~~~~~~~~~
+[verse]
+'PUT /projects/link:#project-name[\{project-name\}]/branches/link:#branch-id[\{branch-id\}]'
+
+Creates a new branch.
+
+In the request body additional data for the branch can be provided as
+link:#branch-input[BranchInput].
+
+.Request
+----
+  PUT /projects/MyProject/branches/stable HTTP/1.0
+  Content-Type: application/json;charset=UTF-8
+
+  {
+    "revision": "76016386a0d8ecc7b6be212424978bb45959d668"
+  }
+----
+
+As response a link:#branch-info[BranchInfo] entity is returned that
+describes the created branch.
+
+.Response
+----
+  HTTP/1.1 201 Created
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  {
+    "ref": "refs/heads/stable",
+    "revision": "76016386a0d8ecc7b6be212424978bb45959d668",
+    "can_delete": true
+  }
+----
+
 [[child-project-endpoints]]
 Child Project Endpoints
 -----------------------
@@ -853,6 +968,12 @@
 IDs
 ---
 
+[[branch-id]]
+\{branch-id\}
+~~~~~~~~~~~~~
+The name of a branch or `HEAD`. The prefix `refs/heads/` can be
+omitted.
+
 [[dashboard-id]]
 \{dashboard-id\}
 ~~~~~~~~~~~~~~~~
@@ -871,6 +992,38 @@
 JSON Entities
 -------------
 
+[[branch-info]]
+BranchInfo
+~~~~~~~~~~
+The `BranchInfo` entity contains information about a branch.
+
+[options="header",width="50%",cols="1,^2,4"]
+|=========================
+|Field Name  ||Description
+|`ref`       ||The ref of the branch.
+|`revision`  ||The revision to which the branch points.
+|`can_delete`|`false` if not set|
+Whether the calling user can delete this branch.
+|=========================
+
+[[branch-input]]
+BranchInput
+~~~~~~~~~~~
+The `BranchInput` entity contains information for the creation of
+a new branch.
+
+[options="header",width="50%",cols="1,^2,4"]
+|=======================
+|Field Name||Description
+|`ref`     |optional|
+The name of the branch. The prefix `refs/heads/` can be
+omitted. +
+If set, must match the branch ID in the URL.
+|`revision`|optional|
+The base revision of the new branch. +
+If not set, `HEAD` will be used as base revision.
+|=======================
+
 [[dashboard-info]]
 DashboardInfo
 ~~~~~~~~~~~~~
diff --git a/Documentation/rest-api.txt b/Documentation/rest-api.txt
index 195ca9b..ccc8604 100644
--- a/Documentation/rest-api.txt
+++ b/Documentation/rest-api.txt
@@ -5,7 +5,7 @@
 The API is suitable for automated tools to build upon, as well as
 supporting some ad-hoc scripting use cases.
 
-See also: link:dev-readme.html#test-rest-api[Developer setup: Testing the REST API].
+See also: link:dev-rest-api.html[REST API Developers' Notes].
 
 Endpoints
 ---------
diff --git a/ReleaseNotes/ReleaseNotes-2.5.3.txt b/ReleaseNotes/ReleaseNotes-2.5.3.txt
new file mode 100644
index 0000000..1cbe85f
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.5.3.txt
@@ -0,0 +1,22 @@
+Release notes for Gerrit 2.5.3
+==============================
+
+Gerrit 2.5.3 is now available:
+
+link:http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.5.3.war[http://code.google.com/p/gerrit/downloads/detail?name=gerrit-2.5.3.war]
+
+There are no schema changes from any member of the 2.5.x versions.
+
+However, if upgrading from anything earlier version, follow the upgrade
+procedure in the 2.5 link:ReleaseNotes-2.5.html[Release Notes].
+
+Security Fixes
+--------------
+* Patch vulnerabilities in OpenID client library
++
+Installations using OpenID for authentication were vulnerable to a
+number of attacks over the network.  The openid4java client library
+was identified as the entry point.  In this release Gerrit updated to
+the latest 0.9.8 release, which patches the known attack vectors.
+
+No other changes since 2.5.2.
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index 26ccae7..5479101 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -9,6 +9,7 @@
 [[2_5]]
 Version 2.5.x
 -------------
+* link:ReleaseNotes-2.5.3.html[2.5.3]
 * link:ReleaseNotes-2.5.2.html[2.5.2]
 * link:ReleaseNotes-2.5.1.html[2.5.1]
 * link:ReleaseNotes-2.5.html[2.5]
diff --git a/gerrit-acceptance-tests/BUCK b/gerrit-acceptance-tests/BUCK
index b702d75..6b4c2bf 100644
--- a/gerrit-acceptance-tests/BUCK
+++ b/gerrit-acceptance-tests/BUCK
@@ -8,13 +8,29 @@
   name = 'acceptance_tests',
   srcs = glob(['src/test/java/**/*.java']),
   deps = TEST + [
+    '//gerrit-common:server',
+    '//gerrit-extension-api:api',
     '//gerrit-launcher:launcher',
     '//gerrit-pgm:pgm',
-    '//lib:servlet-api-3_0',
+    '//gerrit-reviewdb:server',
+
+    '//lib:args4j',
+    '//lib:gson',
+    '//lib:guava',
+    '//lib:gwtorm',
     '//lib:h2',
+    '//lib:jsch',
+    '//lib:jsr305',
     '//lib:junit',
+    '//lib:servlet-api-3_0',
+
+    '//lib/log:impl_log4j',
+    '//lib/log:log4j',
+    '//lib/guice:guice',
+    '//lib/jgit:jgit',
     '//lib/jgit:junit',
-    '//lib/openid:http-client',
+    '//lib/openid:httpclient',
+    '//lib/openid:httpcore',
   ],
   source_under_test = TEST,
   labels = ['slow'],
diff --git a/gerrit-antlr/BUCK b/gerrit-antlr/BUCK
index a37da60..0e19320 100644
--- a/gerrit-antlr/BUCK
+++ b/gerrit-antlr/BUCK
@@ -2,16 +2,16 @@
   'QueryLexer.java',
   'QueryParser.java',
 ]
-
-java_library(
-  name = 'antlr',
-  deps = [':query'],
-  visibility = ['PUBLIC'],
-)
+PARSER_DEPS = [
+  ':query_antlr',
+  ':query_exception',
+  '//lib/antlr:java_runtime',
+]
 
 java_library(
   name = 'query_exception',
   srcs = ['src/main/java/com/google/gerrit/server/query/QueryParseException.java'],
+  visibility = ['PUBLIC'],
 )
 
 genantlr(
@@ -20,14 +20,11 @@
   outs = ANTLR_OUTS,
 )
 
+# Hack necessary to expose ANTLR generated code as JAR to Eclipse.
 java_library(
   name = 'lib',
   srcs = [genfile(f) for f in ANTLR_OUTS],
-  deps = [
-    ':query_antlr',
-    ':query_exception',
-    '//lib/antlr:java_runtime',
-  ],
+  deps = PARSER_DEPS,
 )
 
 genrule(
@@ -35,15 +32,12 @@
   cmd = 'ln -s $SRCS $OUT',
   srcs = [genfile('lib__lib__output/lib.jar')],
   deps = [':lib'],
-  out = 'query.jar',
+  out = 'query_parser.jar',
 )
 
 prebuilt_jar(
-  name = 'query',
-  binary_jar = genfile('query.jar'),
-  deps = [
-    ':query_link',
-    ':query_exception',
-    '//lib/antlr:java_runtime',
-  ],
+  name = 'query_parser',
+  binary_jar = genfile('query_parser.jar'),
+  deps = PARSER_DEPS + [':query_link'],
+  visibility = ['PUBLIC'],
 )
diff --git a/gerrit-cache-h2/BUCK b/gerrit-cache-h2/BUCK
index 638f3dc..d3e8994 100644
--- a/gerrit-cache-h2/BUCK
+++ b/gerrit-cache-h2/BUCK
@@ -2,9 +2,13 @@
   name = 'cache-h2',
   srcs = glob(['src/main/java/**/*.java']),
   deps = [
+    '//gerrit-extension-api:api',
     '//gerrit-server:server',
     '//lib:guava',
     '//lib:h2',
+    '//lib/guice:guice',
+    '//lib/jgit:jgit',
+    '//lib/log:api',
   ],
   visibility = ['PUBLIC'],
 )
diff --git a/gerrit-common/BUCK b/gerrit-common/BUCK
index 8dfdbb7..07bbcae 100644
--- a/gerrit-common/BUCK
+++ b/gerrit-common/BUCK
@@ -9,7 +9,10 @@
     '//gerrit-patch-jgit:client',
     '//gerrit-prettify:client',
     '//gerrit-reviewdb:client',
+    '//lib:gwtjsonrpc',
+    '//lib:gwtorm',
     '//lib:jsr305',
+    '//lib/jgit:jgit',
   ],
   visibility = ['PUBLIC'],
 )
@@ -21,7 +24,10 @@
     '//gerrit-patch-jgit:server',
     '//gerrit-prettify:server',
     '//gerrit-reviewdb:server',
+    '//lib:gwtjsonrpc',
+    '//lib:gwtorm',
     '//lib:jsr305',
+    '//lib/jgit:jgit',
   ],
   visibility = ['PUBLIC'],
 )
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 0638906..f08cf7e 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
@@ -58,11 +58,6 @@
 
   @Audit
   @SignInRequired
-  void addBranch(Project.NameKey projectName, String branchName,
-      String startingRevision, AsyncCallback<AddBranchResult> callback);
-
-  @Audit
-  @SignInRequired
   void deleteBranch(Project.NameKey projectName, Set<Branch.NameKey> ids,
       AsyncCallback<Set<Branch.NameKey>> callback);
 }
diff --git a/gerrit-extension-api/BUCK b/gerrit-extension-api/BUCK
index 25aba72..75539f6 100644
--- a/gerrit-extension-api/BUCK
+++ b/gerrit-extension-api/BUCK
@@ -1,10 +1,6 @@
 java_library2(
   name = 'api',
   srcs = glob(['src/main/java/com/google/gerrit/extensions/**/*.java']),
-  compile_deps = [
-    '//lib/guice:guice',
-    '//lib/guice:guice-servlet',
-    '//lib:servlet-api-3_0',
-  ],
+  compile_deps = ['//lib/guice:guice'],
   visibility = ['PUBLIC'],
 )
diff --git a/gerrit-gwtexpui/BUCK b/gerrit-gwtexpui/BUCK
index 4e6774d..41625ff 100644
--- a/gerrit-gwtexpui/BUCK
+++ b/gerrit-gwtexpui/BUCK
@@ -90,6 +90,7 @@
   deps = [
     ':SafeHtml',
     '//lib:junit',
+    '//lib/gwt:user',
     '//lib/gwt:dev',
   ],
   source_under_test = [':SafeHtml'],
diff --git a/gerrit-gwtui/BUCK b/gerrit-gwtui/BUCK
index c9d87c4..dc47d82 100644
--- a/gerrit-gwtui/BUCK
+++ b/gerrit-gwtui/BUCK
@@ -72,7 +72,10 @@
     '//gerrit-reviewdb:client',
     '//lib:gwtjsonrpc',
     '//lib:gwtjsonrpc_src',
+    '//lib:gwtorm',
+    '//lib:jsr305',
     '//lib/gwt:user',
+    '//lib/jgit:jgit',
   ],
   visibility = [
     '//tools/eclipse:classpath',
@@ -87,6 +90,7 @@
     ':ui_module',
     '//lib:junit',
     '//lib/gwt:dev',
+    '//lib/jgit:jgit',
   ],
   source_under_test = [':ui_module'],
 )
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 62662c9..c8f40b2 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
@@ -688,6 +688,7 @@
       addDocLink(m, C.menuDocumentationSearch(), "user-search.html");
       addDocLink(m, C.menuDocumentationUpload(), "user-upload.html");
       addDocLink(m, C.menuDocumentationAccess(), "access-control.html");
+      addDocLink(m, C.menuDocumentationAPI(), "rest-api.html");
       menuLeft.add(m, C.menuDocumentation());
     }
 
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 0b57bcb..683f058 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
@@ -88,6 +88,7 @@
   String menuDocumentationSearch();
   String menuDocumentationUpload();
   String menuDocumentationAccess();
+  String menuDocumentationAPI();
 
   String searchHint();
   String searchButton();
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 f7033e4..defc7e4 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
@@ -71,6 +71,7 @@
 menuDocumentationSearch = Searching
 menuDocumentationUpload = Uploading
 menuDocumentationAccess = Access Controls
+menuDocumentationAPI = REST API
 
 searchHint = Change #, SHA-1, tr:id or owner:email
 searchButton = Search
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java
index 8221668..a532209 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Themer.java
@@ -45,13 +45,17 @@
   }
 
   public void set(ThemeInfo theme) {
-    set(theme.css() != null ? theme.css() : cssText,
-        theme.header() != null ? theme.header() : headerHtml,
-        theme.footer() != null ? theme.footer() : footerHtml);
+    if (theme != null) {
+      set(theme.css() != null ? theme.css() : cssText,
+          theme.header() != null ? theme.header() : headerHtml,
+          theme.footer() != null ? theme.footer() : footerHtml);
+    } else {
+      set(cssText, headerHtml, footerHtml);
+    }
   }
 
   public void clear() {
-    set(cssText, headerHtml, footerHtml);
+    set(null);
   }
 
   void init(Element css, Element header, Element footer) {
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 a7c6a23..23b4c93 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
@@ -19,12 +19,13 @@
 import com.google.gerrit.client.ErrorDialog;
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.GitwebLink;
+import com.google.gerrit.client.projects.BranchInfo;
+import com.google.gerrit.client.projects.ProjectApi;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.BranchLink;
 import com.google.gerrit.client.ui.FancyFlexTable;
 import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.common.data.AddBranchResult;
 import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
@@ -165,13 +166,13 @@
   }
 
   private void doAddNewBranch() {
-    final String branchName = nameTxtBox.getText();
+    final String branchName = nameTxtBox.getText().trim();
     if ("".equals(branchName)) {
       nameTxtBox.setFocus(true);
       return;
     }
 
-    final String rev = irevTxtBox.getText();
+    final String rev = irevTxtBox.getText().trim();
     if ("".equals(rev)) {
       irevTxtBox.setText("HEAD");
       Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@@ -185,62 +186,29 @@
     }
 
     addBranch.setEnabled(false);
-    Util.PROJECT_SVC.addBranch(getProjectKey(), branchName, rev,
-        new GerritCallback<AddBranchResult>() {
-          public void onSuccess(final AddBranchResult result) {
-            addBranch.setEnabled(true);
-            if (!result.hasError()) {
-              nameTxtBox.setText("");
-              irevTxtBox.setText("");
-              display(result.getListBranchesResult().getBranches());
-            } else {
-              final AddBranchResult.Error error = result.getError();
-              final String msg;
-              switch (error.getType()) {
-                case INVALID_NAME:
-                  selectAllAndFocus(nameTxtBox);
-                  msg = Gerrit.M.invalidBranchName(branchName);
-                  break;
-
-                case INVALID_REVISION:
-                  selectAllAndFocus(irevTxtBox);
-                  msg = Gerrit.M.invalidRevision(rev);
-                  break;
-
-                case BRANCH_CREATION_NOT_ALLOWED_UNDER_REFNAME_PREFIX:
-                  selectAllAndFocus(nameTxtBox);
-                  msg =
-                      Gerrit.M.branchCreationNotAllowedUnderRefnamePrefix(error
-                          .getRefname());
-                  break;
-
-                case BRANCH_ALREADY_EXISTS:
-                  selectAllAndFocus(nameTxtBox);
-                  msg = Gerrit.M.branchAlreadyExists(error.getRefname());
-                  break;
-
-                case BRANCH_CREATION_CONFLICT:
-                  selectAllAndFocus(nameTxtBox);
-                  msg =
-                      Gerrit.M.branchCreationConflict(branchName,
-                          error.getRefname());
-                  break;
-
-                default:
-                  msg =
-                      Gerrit.M.branchCreationFailed(branchName,
-                          error.toString());
-              }
-              new ErrorDialog(msg).center();
-            }
-          }
-
+    ProjectApi.createBranch(getProjectKey(), branchName, rev,
+        new GerritCallback<BranchInfo>() {
           @Override
-          public void onFailure(final Throwable caught) {
+          public void onSuccess(BranchInfo result) {
             addBranch.setEnabled(true);
-            super.onFailure(caught);
+            nameTxtBox.setText("");
+            irevTxtBox.setText("");
+            Util.PROJECT_SVC.listBranches(getProjectKey(),
+                new GerritCallback<ListBranchesResult>() {
+                  @Override
+                  public void onSuccess(ListBranchesResult result) {
+                    display(result.getBranches());
+                  }
+                });
           }
-        });
+
+      @Override
+      public void onFailure(Throwable caught) {
+        addBranch.setEnabled(true);
+        selectAllAndFocus(nameTxtBox);
+        new ErrorDialog(caught.getMessage()).center();
+      }
+    });
   }
 
   private static void selectAllAndFocus(final TextBox textBox) {
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 9407a48..7baff8a 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
@@ -567,7 +567,7 @@
                 @Override
                 public void onSuccess(NativeString msg) {
                   b.setEnabled(true);
-                  if (msg != null) {
+                  if (msg != null && !msg.asString().isEmpty()) {
                     Window.alert(msg.asString());
                   }
                 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java
new file mode 100644
index 0000000..6633fca
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/BranchInfo.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2013 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.projects;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+public class BranchInfo extends JavaScriptObject {
+  public final native String ref() /*-{ return this.ref; }-*/;
+  public final native String revision() /*-{ return this.revision; }-*/;
+  public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
+
+  protected BranchInfo() {
+  }
+}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
index be133c5..63bcd64 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
@@ -33,6 +33,15 @@
         .put(input, asyncCallback);
   }
 
+  /** Create a new branch */
+  public static void createBranch(Project.NameKey projectName, String ref,
+      String revision, AsyncCallback<BranchInfo> asyncCallback) {
+    BranchInput input = BranchInput.create();
+    input.setRevision(revision);
+    new RestApi("/projects/").id(projectName.get()).view("branches").id(ref)
+        .ifNoneMatch().put(input, asyncCallback);
+  }
+
   static RestApi config(Project.NameKey name) {
     return new RestApi("/projects/").id(name.get()).view("config");
   }
@@ -53,4 +62,15 @@
 
     final native void setCreateEmptyCommit(boolean cc) /*-{ if(cc)this.create_empty_commit=cc; }-*/;
   }
+
+  private static class BranchInput extends JavaScriptObject {
+    static BranchInput create() {
+      return (BranchInput) createObject();
+    }
+
+    protected BranchInput() {
+    }
+
+    final native void setRevision(String r) /*-{ if(r)this.revision=r; }-*/;
+  }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java
index ccc6a56..a26db05 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java
@@ -62,7 +62,7 @@
   protected void onUnload() {
     super.onUnload();
     if (setTheme) {
-      Gerrit.THEMER.set(null);
+      Gerrit.THEMER.clear();
     }
   }
 
diff --git a/gerrit-httpd/BUCK b/gerrit-httpd/BUCK
index 4b1981b..51f951d 100644
--- a/gerrit-httpd/BUCK
+++ b/gerrit-httpd/BUCK
@@ -3,16 +3,33 @@
   srcs = glob(['src/main/java/**/*.java']),
   resources = glob(['src/main/resources/**/*']),
   deps = [
+    '//gerrit-antlr:query_exception',
+    '//gerrit-common:server',
+    '//gerrit-extension-api:api',
     '//gerrit-gwtexpui:linker_server',
     '//gerrit-gwtexpui:server',
+    '//gerrit-patch-jgit:server',
     '//gerrit-prettify:server',
+    '//gerrit-reviewdb:server',
     '//gerrit-server:server',
+    '//gerrit-util-cli:cli',
+    '//lib:args4j',
+    '//lib:gson',
+    '//lib:guava',
     '//lib:gwtjsonrpc',
+    '//lib:gwtorm',
+    '//lib:jsch',
     '//lib:jsr305',
     '//lib:mime-util',
-    '//lib:servlet-api-3_0',
+    '//lib/commons:codec',
+    '//lib/guice:guice',
+    '//lib/guice:guice-assistedinject',
+    '//lib/guice:guice-servlet',
+    '//lib/jgit:jgit',
     '//lib/jgit:jgit-servlet',
+    '//lib/log:api',
   ],
+  compile_deps = ['//lib:servlet-api-3_0'],
   visibility = ['PUBLIC'],
 )
 
@@ -21,9 +38,18 @@
   srcs = glob(['src/test/java/**/*.java']),
   deps = [
     ':httpd',
+    '//gerrit-common:server',
+    '//gerrit-extension-api:api',
+    '//gerrit-reviewdb:server',
+    '//gerrit-server:server',
     '//lib:easymock',
     '//lib:junit',
+    '//lib:gson',
+    '//lib:gwtorm',
+    '//lib:guava',
     '//lib:servlet-api-3_0',
+    '//lib/guice:guice',
+    '//lib/jgit:jgit',
     '//lib/jgit:junit',
   ],
   source_under_test = [':httpd'],
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 4d82dd5..92a5e41 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -215,7 +215,9 @@
         IdString id = path.remove(0);
         try {
           rsrc = rc.parse(rsrc, id);
-          checkPreconditions(req, rsrc);
+          if (path.isEmpty()) {
+            checkPreconditions(req, rsrc);
+          }
         } catch (ResourceNotFoundException e) {
           if (rc instanceof AcceptsCreate
               && path.isEmpty()
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
deleted file mode 100644
index d26501e..0000000
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/AddBranch.java
+++ /dev/null
@@ -1,233 +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.httpd.rpc.project;
-
-import com.google.gerrit.common.ChangeHooks;
-import com.google.gerrit.common.data.AddBranchResult;
-import com.google.gerrit.common.errors.InvalidRevisionException;
-import com.google.gerrit.httpd.rpc.Handler;
-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.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.ProjectControl;
-import com.google.gerrit.server.project.RefControl;
-import com.google.gerrit.server.util.MagicBranch;
-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.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.ObjectWalk;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-
-class AddBranch extends Handler<AddBranchResult> {
-  private static final Logger log = LoggerFactory.getLogger(AddBranch.class);
-
-  interface Factory {
-    AddBranch create(@Assisted Project.NameKey projectName,
-        @Assisted("branchName") String branchName,
-        @Assisted("startingRevision") String startingRevision);
-  }
-
-  private final ProjectControl.Factory projectControlFactory;
-  private final ListBranches.Factory listBranchesFactory;
-  private final IdentifiedUser identifiedUser;
-  private final GitRepositoryManager repoManager;
-  private final GitReferenceUpdated referenceUpdated;
-  private final ChangeHooks hooks;
-
-  private final Project.NameKey projectName;
-  private final String branchName;
-  private final String startingRevision;
-
-  @Inject
-  AddBranch(final ProjectControl.Factory projectControlFactory,
-      final ListBranches.Factory listBranchesFactory,
-      final IdentifiedUser identifiedUser,
-      final GitRepositoryManager repoManager,
-      GitReferenceUpdated referenceUpdated,
-      final ChangeHooks hooks,
-
-      @Assisted Project.NameKey projectName,
-      @Assisted("branchName") String branchName,
-      @Assisted("startingRevision") String startingRevision) {
-    this.projectControlFactory = projectControlFactory;
-    this.listBranchesFactory = listBranchesFactory;
-    this.identifiedUser = identifiedUser;
-    this.repoManager = repoManager;
-    this.referenceUpdated = referenceUpdated;
-    this.hooks = hooks;
-
-    this.projectName = projectName;
-    this.branchName = branchName;
-    this.startingRevision = startingRevision;
-  }
-
-  @Override
-  public AddBranchResult call() throws NoSuchProjectException, IOException {
-    final ProjectControl projectControl =
-        projectControlFactory.controlFor(projectName);
-
-    String refname = branchName;
-    while (refname.startsWith("/")) {
-      refname = refname.substring(1);
-    }
-    if (!refname.startsWith(Constants.R_REFS)) {
-      refname = Constants.R_HEADS + refname;
-    }
-    if (!Repository.isValidRefName(refname)) {
-      return new AddBranchResult(new AddBranchResult.Error(
-          AddBranchResult.Error.Type.INVALID_NAME, refname));
-    }
-    if (MagicBranch.isMagicBranch(refname)) {
-      return new AddBranchResult(
-          new AddBranchResult.Error(
-              AddBranchResult.Error.Type.BRANCH_CREATION_NOT_ALLOWED_UNDER_REFNAME_PREFIX,
-              MagicBranch.getMagicRefNamePrefix(refname)));
-    }
-
-    final Branch.NameKey name = new Branch.NameKey(projectName, refname);
-    final RefControl refControl = projectControl.controlForRef(name);
-    final Repository repo = repoManager.openRepository(projectName);
-    try {
-      final ObjectId revid = parseStartingRevision(repo);
-      final RevWalk rw = verifyConnected(repo, revid);
-      RevObject object = rw.parseAny(revid);
-
-      if (refname.startsWith(Constants.R_HEADS)) {
-        // Ensure that what we start the branch from is a commit. If we
-        // were given a tag, deference to the commit instead.
-        //
-        try {
-          object = rw.parseCommit(object);
-        } catch (IncorrectObjectTypeException notCommit) {
-          throw new IllegalStateException(startingRevision + " not a commit");
-        }
-      }
-
-      if (!refControl.canCreate(rw, object)) {
-        throw new IllegalStateException("Cannot create " + refname);
-      }
-
-      try {
-        final RefUpdate u = repo.updateRef(refname);
-        u.setExpectedOldObjectId(ObjectId.zeroId());
-        u.setNewObjectId(object.copy());
-        u.setRefLogIdent(identifiedUser.newRefLogIdent());
-        u.setRefLogMessage("created via web from " + startingRevision, false);
-        final RefUpdate.Result result = u.update(rw);
-        switch (result) {
-          case FAST_FORWARD:
-          case NEW:
-          case NO_CHANGE:
-            referenceUpdated.fire(name.getParentKey(), u);
-            hooks.doRefUpdatedHook(name, u, identifiedUser.getAccount());
-            break;
-          case LOCK_FAILURE:
-            if (repo.getRef(refname) != null) {
-              return new AddBranchResult(new AddBranchResult.Error(
-                  AddBranchResult.Error.Type.BRANCH_ALREADY_EXISTS, refname));
-            }
-            String refPrefix = getRefPrefix(refname);
-            while (!Constants.R_HEADS.equals(refPrefix)) {
-              if (repo.getRef(refPrefix) != null) {
-                return new AddBranchResult(new AddBranchResult.Error(
-                    AddBranchResult.Error.Type.BRANCH_CREATION_CONFLICT, refPrefix));
-              }
-              refPrefix = getRefPrefix(refPrefix);
-            }
-          default: {
-            throw new IOException(result.name());
-          }
-        }
-      } catch (IOException err) {
-        log.error("Cannot create branch " + name, err);
-        throw err;
-      }
-    } catch (InvalidRevisionException e) {
-      return new AddBranchResult(new AddBranchResult.Error(
-          AddBranchResult.Error.Type.INVALID_REVISION));
-    } finally {
-      repo.close();
-    }
-
-    return new AddBranchResult(listBranchesFactory.create(projectName).call());
-  }
-
-  private static String getRefPrefix(final String refName) {
-    final int i = refName.lastIndexOf('/');
-    if (i > Constants.R_HEADS.length() - 1) {
-      return refName.substring(0, i);
-    }
-    return Constants.R_HEADS;
-  }
-
-  private ObjectId parseStartingRevision(final Repository repo)
-      throws InvalidRevisionException {
-    try {
-      final ObjectId revid = repo.resolve(startingRevision);
-      if (revid == null) {
-        throw new InvalidRevisionException();
-      }
-      return revid;
-    } catch (IOException err) {
-      log.error("Cannot resolve \"" + startingRevision + "\" in project \""
-          + projectName + "\"", err);
-      throw new InvalidRevisionException();
-    }
-  }
-
-  private RevWalk verifyConnected(final Repository repo, final ObjectId revid)
-      throws InvalidRevisionException {
-    try {
-      final ObjectWalk rw = new ObjectWalk(repo);
-      try {
-        rw.markStart(rw.parseCommit(revid));
-      } catch (IncorrectObjectTypeException err) {
-        throw new InvalidRevisionException();
-      }
-      for (final Ref r : repo.getAllRefs().values()) {
-        try {
-          rw.markUninteresting(rw.parseAny(r.getObjectId()));
-        } catch (MissingObjectException err) {
-          continue;
-        }
-      }
-      rw.checkConnectivity();
-      return rw;
-    } catch (IncorrectObjectTypeException err) {
-      throw new InvalidRevisionException();
-    } catch (MissingObjectException err) {
-      throw new InvalidRevisionException();
-    } catch (IOException err) {
-      log.error("Repository \"" + repo.getDirectory()
-          + "\" may be corrupt; suggest running git fsck", err);
-      throw new InvalidRevisionException();
-    }
-  }
-}
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 2366423..7330337 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
@@ -14,31 +14,24 @@
 
 package com.google.gerrit.httpd.rpc.project;
 
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
 import com.google.gerrit.common.data.ListBranchesResult;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.httpd.rpc.Handler;
 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.ListBranches.BranchInfo;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.project.ProjectControl;
-import com.google.gerrit.server.project.RefControl;
+import com.google.gerrit.server.project.ProjectResource;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
 
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
-
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 class ListBranches extends Handler<ListBranchesResult> {
   interface Factory {
@@ -46,127 +39,37 @@
   }
 
   private final ProjectControl.Factory projectControlFactory;
-  private final GitRepositoryManager repoManager;
+  private final Provider<com.google.gerrit.server.project.ListBranches> listBranchesProvider;
 
   private final Project.NameKey projectName;
 
   @Inject
   ListBranches(final ProjectControl.Factory projectControlFactory,
-      final GitRepositoryManager repoManager,
-
+      final Provider<com.google.gerrit.server.project.ListBranches> listBranchesProvider,
       @Assisted final Project.NameKey name) {
     this.projectControlFactory = projectControlFactory;
-    this.repoManager = repoManager;
+    this.listBranchesProvider = listBranchesProvider;
 
     this.projectName = name;
   }
 
   @Override
   public ListBranchesResult call() throws NoSuchProjectException, IOException {
-    final ProjectControl pctl = projectControlFactory.validateFor( //
-        projectName, //
-        ProjectControl.OWNER | ProjectControl.VISIBLE);
-
-    final List<Branch> branches = new ArrayList<Branch>();
-    Branch headBranch = null;
-    Branch configBranch = null;
-    final Set<String> targets = new HashSet<String>();
-
-    final Repository db;
+    ProjectControl pctl =
+        projectControlFactory.validateFor(projectName, ProjectControl.OWNER
+            | ProjectControl.VISIBLE);
     try {
-      db = repoManager.openRepository(projectName);
-    } catch (RepositoryNotFoundException noGitRepository) {
-      return new ListBranchesResult(branches, false, true);
-    }
-    try {
-      final Map<String, Ref> all = db.getAllRefs();
-
-      if (!all.containsKey(Constants.HEAD)) {
-        // The branch pointed to by HEAD doesn't exist yet, so getAllRefs
-        // filtered it out. If we ask for it individually we can find the
-        // underlying target and put it into the map anyway.
-        //
-        try {
-          Ref head = db.getRef(Constants.HEAD);
-          if (head != null) {
-            all.put(Constants.HEAD, head);
-          }
-        } catch (IOException e) {
-          // Ignore the failure reading HEAD.
-        }
+      List<Branch> branches = Lists.newArrayList();
+      List<BranchInfo> branchInfos = listBranchesProvider.get().apply(new ProjectResource(pctl));
+      for (BranchInfo info : branchInfos) {
+        Branch b = new Branch(new Branch.NameKey(projectName, info.ref));
+        b.setRevision(new RevId(info.revision));
+        b.setCanDelete(Objects.firstNonNull(info.canDelete, false));
+        branches.add(b);
       }
-
-      for (final Ref ref : all.values()) {
-        if (ref.isSymbolic()) {
-          targets.add(ref.getTarget().getName());
-        }
-      }
-
-      for (final Ref ref : all.values()) {
-        if (ref.isSymbolic()) {
-          // A symbolic reference to another branch, instead of
-          // showing the resolved value, show the name it references.
-          //
-          String target = ref.getTarget().getName();
-          RefControl targetRefControl = pctl.controlForRef(target);
-          if (!targetRefControl.isVisible()) {
-            continue;
-          }
-          if (target.startsWith(Constants.R_HEADS)) {
-            target = target.substring(Constants.R_HEADS.length());
-          }
-
-          Branch b = createBranch(ref.getName());
-          b.setRevision(new RevId(target));
-
-          if (Constants.HEAD.equals(ref.getName())) {
-            b.setCanDelete(false);
-            headBranch = b;
-          } else {
-            b.setCanDelete(targetRefControl.canDelete());
-            branches.add(b);
-          }
-          continue;
-        }
-
-        final RefControl refControl = pctl.controlForRef(ref.getName());
-        if (refControl.isVisible()) {
-          if (ref.getName().startsWith(Constants.R_HEADS)) {
-            branches.add(createBranch(ref, refControl, targets));
-          } else if (GitRepositoryManager.REF_CONFIG.equals(ref.getName())) {
-            configBranch = createBranch(ref, refControl, targets);
-          }
-        }
-      }
-    } finally {
-      db.close();
+      return new ListBranchesResult(branches, pctl.canAddRefs(), false);
+    } catch (ResourceNotFoundException e) {
+      throw new NoSuchProjectException(projectName);
     }
-    Collections.sort(branches, new Comparator<Branch>() {
-      @Override
-      public int compare(final Branch a, final Branch b) {
-        return a.getName().compareTo(b.getName());
-      }
-    });
-    if (configBranch != null) {
-      branches.add(0, configBranch);
-    }
-    if (headBranch != null) {
-      branches.add(0, headBranch);
-    }
-    return new ListBranchesResult(branches, pctl.canAddRefs(), false);
-  }
-
-  private Branch createBranch(final Ref ref, final RefControl refControl,
-      final Set<String> targets) {
-    final Branch b = createBranch(ref.getName());
-    if (ref.getObjectId() != null) {
-      b.setRevision(new RevId(ref.getObjectId().name()));
-    }
-    b.setCanDelete(!targets.contains(ref.getName()) && refControl.canDelete());
-    return b;
-  }
-
-  private Branch createBranch(final String name) {
-    return new Branch(new Branch.NameKey(projectName, name));
   }
 }
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 0e46bc3..ade781d 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
@@ -15,7 +15,6 @@
 package com.google.gerrit.httpd.rpc.project;
 
 import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.AddBranchResult;
 import com.google.gerrit.common.data.ListBranchesResult;
 import com.google.gerrit.common.data.ProjectAccess;
 import com.google.gerrit.common.data.ProjectAdminService;
@@ -32,7 +31,6 @@
 import java.util.Set;
 
 class ProjectAdminServiceImpl implements ProjectAdminService {
-  private final AddBranch.Factory addBranchFactory;
   private final ChangeProjectAccess.Factory changeProjectAccessFactory;
   private final ReviewProjectAccess.Factory reviewProjectAccessFactory;
   private final ChangeProjectSettings.Factory changeProjectSettingsFactory;
@@ -43,8 +41,7 @@
   private final ProjectDetailFactory.Factory projectDetailFactory;
 
   @Inject
-  ProjectAdminServiceImpl(final AddBranch.Factory addBranchFactory,
-      final ChangeProjectAccess.Factory changeProjectAccessFactory,
+  ProjectAdminServiceImpl(final ChangeProjectAccess.Factory changeProjectAccessFactory,
       final ReviewProjectAccess.Factory reviewProjectAccessFactory,
       final ChangeProjectSettings.Factory changeProjectSettingsFactory,
       final DeleteBranches.Factory deleteBranchesFactory,
@@ -52,7 +49,6 @@
       final VisibleProjectDetails.Factory visibleProjectDetailsFactory,
       final ProjectAccessFactory.Factory projectAccessFactory,
       final ProjectDetailFactory.Factory projectDetailFactory) {
-    this.addBranchFactory = addBranchFactory;
     this.changeProjectAccessFactory = changeProjectAccessFactory;
     this.reviewProjectAccessFactory = reviewProjectAccessFactory;
     this.changeProjectSettingsFactory = changeProjectSettingsFactory;
@@ -119,12 +115,4 @@
       final AsyncCallback<Set<Branch.NameKey>> callback) {
     deleteBranchesFactory.create(projectName, toRemove).to(callback);
   }
-
-  @Override
-  public void addBranch(final Project.NameKey projectName,
-      final String branchName, final String startingRevision,
-      final AsyncCallback<AddBranchResult> callback) {
-    addBranchFactory.create(projectName, branchName, startingRevision).to(
-        callback);
-  }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
index 2d4f210..c809851 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectModule.java
@@ -28,7 +28,6 @@
     install(new FactoryModule() {
       @Override
       protected void configure() {
-        factory(AddBranch.Factory.class);
         factory(ChangeProjectAccess.Factory.class);
         factory(ReviewProjectAccess.Factory.class);
         factory(ChangeProjectSettings.Factory.class);
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 5cfde6a..7265470 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
@@ -39,6 +39,7 @@
 import com.google.gerrit.server.project.RefControl;
 import com.google.gwtorm.client.KeyUtil;
 import com.google.gwtorm.server.StandardKeyEncoder;
+import com.google.inject.Provider;
 
 import org.easymock.IExpectationSetters;
 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
@@ -84,6 +85,7 @@
 
     mockDb = createStrictMock(Repository.class);
     pc = createStrictMock(ProjectControl.class);
+    expect(pc.getProject()).andReturn(new Project(name)).anyTimes();
     pcf = createStrictMock(ProjectControl.Factory.class);
     grm = createStrictMock(GitRepositoryManager.class);
     refMocks = new ArrayList<RefControl>();
@@ -125,7 +127,7 @@
     validate().andThrow(err);
     doReplay();
     try {
-      new ListBranches(pcf, grm, name).call();
+      new ListBranches(pcf, createListBranchesProvider(grm), name).call();
       fail("did not throw when expected not authorized");
     } catch (NoSuchProjectException e2) {
       assertSame(err, e2);
@@ -161,7 +163,8 @@
     expectLastCall();
 
     doReplay();
-    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r =
+        new ListBranches(pcf, createListBranchesProvider(grm), name).call();
     doVerify();
     assertNotNull(r);
     assertNotNull(r.getBranches());
@@ -302,7 +305,8 @@
     expectLastCall();
 
     doReplay();
-    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r =
+        new ListBranches(pcf, createListBranchesProvider(grm), name).call();
     doVerify();
     assertNotNull(r);
 
@@ -330,7 +334,8 @@
     expectLastCall();
 
     doReplay();
-    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r =
+        new ListBranches(pcf, createListBranchesProvider(grm), name).call();
     doVerify();
     assertNotNull(r);
     assertTrue(r.getBranches().isEmpty());
@@ -359,7 +364,8 @@
     expectLastCall();
 
     doReplay();
-    final ListBranchesResult r = new ListBranches(pcf, grm, name).call();
+    final ListBranchesResult r =
+        new ListBranches(pcf, createListBranchesProvider(grm), name).call();
     doVerify();
     assertNotNull(r);
 
@@ -371,4 +377,14 @@
     assertEquals("bar", r.getBranches().get(1).getShortName());
     assertFalse(r.getBranches().get(1).getCanDelete());
   }
+
+  private static Provider<com.google.gerrit.server.project.ListBranches> createListBranchesProvider(
+      final GitRepositoryManager grm) {
+    return new Provider<com.google.gerrit.server.project.ListBranches>() {
+      @Override
+      public com.google.gerrit.server.project.ListBranches get() {
+        return new com.google.gerrit.server.project.ListBranches(grm);
+      }
+    };
+  }
 }
diff --git a/gerrit-openid/BUCK b/gerrit-openid/BUCK
index 582a7de..0801534 100644
--- a/gerrit-openid/BUCK
+++ b/gerrit-openid/BUCK
@@ -1,17 +1,23 @@
-java_library(
+java_library2(
   name = 'openid',
   srcs = glob(['src/main/java/**/*.java']),
   resources = glob(['src/main/resources/**/*']),
   deps = [
     '//gerrit-common:server',
     '//gerrit-extension-api:api',
+    '//gerrit-gwtexpui:server',
     '//gerrit-httpd:httpd',
+    '//gerrit-reviewdb:server',
+    '//gerrit-server:server',
     '//lib:guava',
+    '//lib:gwtorm',
     '//lib:jsr305',
-    '//lib:servlet-api-3_0',
     '//lib/guice:guice',
+    '//lib/guice:guice-servlet',
+    '//lib/jgit:jgit',
     '//lib/log:api',
     '//lib/openid:consumer',
   ],
+  compile_deps = ['//lib:servlet-api-3_0'],
   visibility = ['PUBLIC'],
 )
diff --git a/gerrit-openid/pom.xml b/gerrit-openid/pom.xml
index e5261ce..45df631 100644
--- a/gerrit-openid/pom.xml
+++ b/gerrit-openid/pom.xml
@@ -51,8 +51,7 @@
 
     <dependency>
       <groupId>org.openid4java</groupId>
-      <artifactId>openid4java-consumer</artifactId>
-      <type>pom</type>
+      <artifactId>openid4java</artifactId>
     </dependency>
 
     <dependency>
diff --git a/gerrit-pgm/BUCK b/gerrit-pgm/BUCK
index daed401..0746bdf 100644
--- a/gerrit-pgm/BUCK
+++ b/gerrit-pgm/BUCK
@@ -3,21 +3,37 @@
   srcs = glob(['src/main/java/**/*.java']),
   resources = glob(['src/main/resources/**/*']),
   deps = [
-    '//gerrit-server:common_rules',
-    '//gerrit-server:server',
-    '//gerrit-httpd:httpd',
-    '//gerrit-sshd:sshd',
-
     '//gerrit-cache-h2:cache-h2',
+    '//gerrit-common:server',
+    '//gerrit-extension-api:api',
+    '//gerrit-gwtexpui:server',
+    '//gerrit-httpd:httpd',
     '//gerrit-openid:openid',
-
+    '//gerrit-server:common_rules',
+    '//gerrit-reviewdb:server',
+    '//gerrit-server:server',
+    '//gerrit-sshd:sshd',
     '//gerrit-util-cli:cli',
+    '//lib:args4j',
+    '//lib:guava',
+    '//lib:gwtorm',
+    '//lib:gwtjsonrpc',
+    '//lib:h2',
+    '//lib:jsr305',
+    '//lib:servlet-api-3_0',
+    '//lib/commons:dbcp',
+    '//lib/guice:guice',
+    '//lib/guice:guice-assistedinject',
+    '//lib/guice:guice-servlet',
+    '//lib/jetty:server',
     '//lib/jetty:servlet',
+    '//lib/jgit:jgit',
+    '//lib/log:api',
     '//lib/log:log4j',
+    '//lib/mina:sshd',
+    '//lib/prolog:prolog-cafe',
   ],
-  compile_deps = [
-    '//gerrit-launcher:launcher',
-  ],
+  compile_deps = ['//gerrit-launcher:launcher'],
   visibility = [
     '//:',
     '//gerrit-acceptance-tests:',
@@ -31,8 +47,11 @@
   srcs = glob(['src/test/java/**/*.java']),
   deps = [
     ':pgm',
+    '//gerrit-server:server',
     '//lib:junit',
     '//lib:easymock',
+    '//lib/guice:guice',
+    '//lib/jgit:jgit',
     '//lib/jgit:junit',
   ],
   source_under_test = [':pgm'],
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
new file mode 100644
index 0000000..b792f68
--- /dev/null
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
@@ -0,0 +1,79 @@
+// Copyright (C) 2013 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 static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.gwtexpui.server.CacheHeaders;
+
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.server.AbstractHttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+class HiddenErrorHandler extends ErrorHandler {
+  private static final Logger log = LoggerFactory.getLogger(HiddenErrorHandler.class);
+  private static final byte[] MSG = "Internal server error\n".getBytes(Charsets.ISO_8859_1);
+
+  public void handle(String target, Request baseRequest,
+      HttpServletRequest req, HttpServletResponse res) throws IOException {
+    AbstractHttpConnection.getCurrentConnection().getRequest().setHandled(true);
+    try {
+      log(req);
+    } finally {
+      replyGenericError(res);
+    }
+  }
+
+  private void replyGenericError(HttpServletResponse res) throws IOException {
+    if (!res.isCommitted()) {
+      res.reset();
+      res.setStatus(SC_INTERNAL_SERVER_ERROR);
+      res.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain; charset=ISO-8859-1");
+      res.setContentLength(MSG.length);
+      try {
+        CacheHeaders.setNotCacheable(res);
+      } finally {
+        ServletOutputStream out = res.getOutputStream();
+        try {
+          out.write(MSG);
+        } finally {
+          out.close();
+        }
+      }
+    }
+  }
+
+  private static void log(HttpServletRequest req) {
+    Throwable err = (Throwable)req.getAttribute("javax.servlet.error.exception");
+    if (err != null) {
+      String uri = req.getRequestURI();
+      if (!Strings.isNullOrEmpty(req.getQueryString())) {
+        uri += "?" + req.getQueryString();
+      }
+      log.error(String.format("Error in %s %s", req.getMethod(), uri), err);
+    }
+  }
+}
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 dd71175..37637d5 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
@@ -332,6 +332,7 @@
     // for Gerrit plug-ins to enable user-level sessions.
     //
     app.setSessionHandler(new SessionHandler());
+    app.setErrorHandler(new HiddenErrorHandler());
 
     // This is the path we are accessed by clients within our domain.
     //
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Browser.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Browser.java
index ea13043..8e3948e 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Browser.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Browser.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.pgm.init;
 
+import com.google.common.base.Strings;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.inject.Inject;
 
@@ -42,7 +43,6 @@
     if (url == null) {
       return;
     }
-
     if (url.startsWith("proxy-")) {
       url = url.substring("proxy-".length());
     }
@@ -54,15 +54,19 @@
       System.err.println("error: invalid httpd.listenUrl: " + url);
       return;
     }
-    final String hostname = uri.getHost();
-    final int port = InitUtil.portOf(uri);
+    waitForServer(uri);
+    openBrowser(uri, link);
+  }
 
-    System.err.print("Waiting for server to start ... ");
+  private void waitForServer(URI uri) throws IOException {
+    String host = uri.getHost();
+    int port = InitUtil.portOf(uri);
+    System.err.format("Waiting for server on %s:%d ... ", host, port);
     System.err.flush();
     for (;;) {
-      final Socket s;
+      Socket s;
       try {
-        s = new Socket(hostname, port);
+        s = new Socket(host, port);
       } catch (IOException e) {
         try {
           Thread.sleep(100);
@@ -74,18 +78,33 @@
       break;
     }
     System.err.println("OK");
+  }
 
-    url = cfg.getString("gerrit", null, "canonicalWebUrl");
-    if (url == null || url.isEmpty()) {
+  private String resolveUrl(URI uri, String link) {
+    String url = cfg.getString("gerrit", null, "canonicalWebUrl");
+    if (Strings.isNullOrEmpty(url)) {
       url = uri.toString();
     }
     if (!url.endsWith("/")) {
       url += "/";
     }
-    if (link != null && !link.isEmpty()) {
+    if (!Strings.isNullOrEmpty(link)) {
       url += "#" + link;
     }
-    System.err.println("Opening browser ...");
-    org.h2.tools.Server.openBrowser(url);
+    return url;
+  }
+
+  private void openBrowser(URI uri, String link) {
+    String url = resolveUrl(uri, link);
+    System.err.format("Opening %s ...", url);
+    System.err.flush();
+    try {
+      org.h2.tools.Server.openBrowser(url);
+      System.err.println("OK");
+    } catch (Exception e) {
+      System.err.println("FAILED");
+      System.err.println("Open Gerrit with a JavaScript capable browser:");
+      System.err.println("  " + url);
+    }
   }
 }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
index ac3e728..20034c1 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
@@ -21,10 +21,11 @@
 class JDBCInitializer implements DatabaseConfigInitializer {
   @Override
   public void initConfig(Section database) {
+    boolean hasUrl = Strings.emptyToNull(database.get("url")) != null;
     database.string("URL", "url", null);
     guessDriver(database);
     database.string("Driver class name", "driver", null);
-    database.string("Database username", "username", username());
+    database.string("Database username", "username", hasUrl ? null : username());
     database.password("username", "password");
   }
 
diff --git a/gerrit-server/BUCK b/gerrit-server/BUCK
index 86cad4e..1d676a0 100644
--- a/gerrit-server/BUCK
+++ b/gerrit-server/BUCK
@@ -1,18 +1,27 @@
 include_defs('//lib/prolog/DEFS')
 
+# TODO(sop) break up gerrit-server java_library(), its too big
 java_library2(
   name = 'server',
   srcs = glob(['src/main/java/**/*.java']),
   resources = glob(['src/main/resources/**/*']),
   deps = [
-    '//gerrit-antlr:antlr',
+    '//gerrit-antlr:query_exception',
+    '//gerrit-antlr:query_parser',
     '//gerrit-common:server',
     '//gerrit-extension-api:api',
+    '//gerrit-patch-commonsnet:commons-net',
+    '//gerrit-patch-jgit:server',
+    '//gerrit-prettify:server',
+    '//gerrit-reviewdb:server',
     '//gerrit-util-cli:cli',
     '//gerrit-util-ssl:ssl',
-    '//gerrit-patch-commonsnet:commons-net',
+    '//lib:args4j',
     '//lib:automaton',
+    '//lib:gson',
     '//lib:guava',
+    '//lib:gwtjsonrpc',
+    '//lib:gwtorm',
     '//lib:jsch',
     '//lib:jsr305',
     '//lib:juniversalchardet',
@@ -20,8 +29,11 @@
     '//lib:ow2-asm',
     '//lib:ow2-asm-tree',
     '//lib:ow2-asm-util',
+    '//lib:parboiled-core',
     '//lib:pegdown',
     '//lib:velocity',
+    '//lib/antlr:java_runtime',
+    '//lib/commons:codec',
     '//lib/commons:dbcp',
     '//lib/commons:lang',
     '//lib/commons:net',
@@ -33,6 +45,7 @@
     '//lib/prolog:prolog-cafe',
   ],
   compile_deps = [
+    '//lib/bouncycastle:bcprov',
     '//lib/bouncycastle:bcpg',
   ],
   visibility = ['PUBLIC'],
@@ -52,10 +65,21 @@
   deps = [
     ':server',
     ':common_rules',
+    '//gerrit-antlr:query_exception',
+    '//gerrit-antlr:query_parser',
+    '//gerrit-common:server',
+    '//gerrit-extension-api:api',
+    '//gerrit-reviewdb:server',
+    '//lib:easymock',
+    '//lib:guava',
+    '//lib:gwtorm',
     '//lib:h2',
     '//lib:junit',
-    '//lib:easymock',
+    '//lib/antlr:java_runtime',
+    '//lib/guice:guice',
+    '//lib/jgit:jgit',
     '//lib/jgit:junit',
+    '//lib/prolog:prolog-cafe',
   ],
   source_under_test = [':server'],
 )
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
index bf77c90..d4fc61b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
@@ -74,6 +74,7 @@
   private final IdentifiedUser currentUser;
   private final CommitValidators.Factory commitValidatorsFactory;
   private final ChangeInserter changeInserter;
+  private final PatchSetInserter patchSetInserter;
   final MergeUtil.Factory mergeUtilFactory;
 
   @Inject
@@ -82,6 +83,7 @@
       final GitRepositoryManager gitManager, final IdentifiedUser currentUser,
       final CommitValidators.Factory commitValidatorsFactory,
       final ChangeInserter changeInserter,
+      final PatchSetInserter patchSetInserter,
       final MergeUtil.Factory mergeUtilFactory) {
     this.patchSetInfoFactory = patchSetInfoFactory;
     this.db = db;
@@ -90,6 +92,7 @@
     this.currentUser = currentUser;
     this.commitValidatorsFactory = commitValidatorsFactory;
     this.changeInserter = changeInserter;
+    this.patchSetInserter = patchSetInserter;
     this.mergeUtilFactory = mergeUtilFactory;
   }
 
@@ -176,16 +179,19 @@
                         destRef.getName()), changeKey).toList();
 
         Change change;
+        boolean createNewChange;
+        PatchSet.Id id;
         if (destChanges.size() > 1) {
           throw new InvalidChangeOperationException("Several changes with key "
               + changeKey + " resides on the same branch. "
               + "Cannot create a new patch set.");
         } else if (destChanges.size() == 1) {
-          // The change key exists on the destination branch.
-          throw new InvalidChangeOperationException(
-              "Change with same change-id: " + changeKey
-                  + " already resides on the same branch. "
-                  + "Cannot create a new change.");
+          // The change key exists on the destination branch. The cherry pick
+          // will be added as a new patch set.
+          change = destChanges.get(0);
+          id = ChangeUtil.nextPatchSetId(git, change.currentPatchSetId());
+
+          createNewChange = false;
         } else {
           // Change key not found on destination branch. We can create a new
           // change.
@@ -193,19 +199,14 @@
               new Change(changeKey, new Change.Id(db.nextChangeId()),
                   currentUser.getAccountId(), new Branch.NameKey(project,
                       destRef.getName()));
+          id = new PatchSet.Id(change.getId(), Change.INITIAL_PATCH_SET_ID);
+          createNewChange = true;
         }
-
-        PatchSet.Id id =
-            new PatchSet.Id(change.getId(), Change.INITIAL_PATCH_SET_ID);
         PatchSet newPatchSet = new PatchSet(id);
         newPatchSet.setCreatedOn(new Timestamp(System.currentTimeMillis()));
         newPatchSet.setUploader(change.getOwner());
         newPatchSet.setRevision(new RevId(cherryPickCommit.name()));
 
-        PatchSetInfo newPatchSetInfo =
-            patchSetInfoFactory.get(cherryPickCommit, newPatchSet.getId());
-        change.setCurrentPatchSet(newPatchSetInfo);
-
         CommitReceivedEvent commitReceivedEvent =
             new CommitReceivedEvent(new ReceiveCommand(ObjectId.zeroId(),
                 cherryPickCommit.getId(), newPatchSet.getRefName()), refControl
@@ -218,8 +219,6 @@
           throw new InvalidChangeOperationException(e.getMessage());
         }
 
-        ChangeUtil.updated(change);
-
         final RefUpdate ru = git.updateRef(newPatchSet.getRefName());
         ru.setExpectedOldObjectId(ObjectId.zeroId());
         ru.setNewObjectId(cherryPickCommit);
@@ -242,11 +241,22 @@
             + change.getKey().get());
         cmsg.setMessage(msgBuf.toString());
 
-        LabelTypes labelTypes = refControl.getProjectControl().getLabelTypes();
+        if (createNewChange) {
+          LabelTypes labelTypes =
+              refControl.getProjectControl().getLabelTypes();
 
-        changeInserter.insertChange(db, change, cmsg, newPatchSet,
-            cherryPickCommit, labelTypes, newPatchSetInfo,
-            Collections.<Account.Id> emptySet());
+          PatchSetInfo newPatchSetInfo =
+              patchSetInfoFactory.get(cherryPickCommit, newPatchSet.getId());
+          change.setCurrentPatchSet(newPatchSetInfo);
+          ChangeUtil.updated(change);
+
+          changeInserter.insertChange(db, change, cmsg, newPatchSet,
+              cherryPickCommit, labelTypes, newPatchSetInfo,
+              Collections.<Account.Id> emptySet());
+        } else {
+          patchSetInserter.insertPatchSet(change, newPatchSet,
+              cherryPickCommit, refControl, cmsg, false);
+        }
 
         return change.getId();
       } finally {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
index 3c81121..1c25a7c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -59,6 +59,19 @@
       final RevCommit commit, RefControl refControl, String message,
       boolean copyLabels) throws OrmException, InvalidChangeOperationException,
       NoSuchChangeException {
+    final ChangeMessage cmsg =
+        new ChangeMessage(new ChangeMessage.Key(change.getId(),
+            ChangeUtil.messageUUID(db)), user.getAccountId(), patchSet.getId());
+    cmsg.setMessage(message);
+
+    return insertPatchSet(change, patchSet, commit, refControl, cmsg,
+        copyLabels);
+  }
+
+  public Change insertPatchSet(Change change, final PatchSet patchSet,
+      final RevCommit commit, RefControl refControl, ChangeMessage changeMessage,
+      boolean copyLabels) throws OrmException, InvalidChangeOperationException,
+      NoSuchChangeException {
 
     final PatchSet.Id currentPatchSetId = change.currentPatchSetId();
 
@@ -114,14 +127,8 @@
       final List<FooterLine> footerLines = commit.getFooterLines();
       ChangeUtil.updateTrackingIds(db, change, trackingFooters, footerLines);
 
-      if (message != null) {
-        final ChangeMessage cmsg =
-            new ChangeMessage(new ChangeMessage.Key(change.getId(),
-                ChangeUtil.messageUUID(db)), user.getAccountId(),
-                patchSet.getId());
-
-        cmsg.setMessage(message);
-        db.changeMessages().insert(Collections.singleton(cmsg));
+      if (changeMessage != null) {
+        db.changeMessages().insert(Collections.singleton(changeMessage));
       }
       db.commit();
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
index 79eeb3f..c6fc709 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.git.validators;
 
+import com.google.common.base.CharMatcher;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.server.GerritPersonIdent;
@@ -555,10 +556,7 @@
    */
   private static String getGerritUrl(String canonicalWebUrl) {
     if (canonicalWebUrl != null) {
-      if (canonicalWebUrl.endsWith("/")) {
-        return canonicalWebUrl.substring(0, canonicalWebUrl.lastIndexOf("/"));
-      }
-      return canonicalWebUrl;
+      return CharMatcher.is('/').trimTrailingFrom(canonicalWebUrl);
     } else {
       return "http://" + getGerritHost(canonicalWebUrl);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java
new file mode 100644
index 0000000..110fe15
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchResource.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.gerrit.extensions.restapi.RestView;
+import com.google.gerrit.server.project.ListBranches.BranchInfo;
+import com.google.inject.TypeLiteral;
+
+public class BranchResource extends ProjectResource {
+  public static final TypeLiteral<RestView<BranchResource>> BRANCH_KIND =
+      new TypeLiteral<RestView<BranchResource>>() {};
+
+  private final BranchInfo branchInfo;
+
+  public BranchResource(ProjectControl control, BranchInfo branchInfo) {
+    super(control);
+    this.branchInfo = branchInfo;
+  }
+
+  public BranchInfo getBranchInfo() {
+    return branchInfo;
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchesCollection.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchesCollection.java
new file mode 100644
index 0000000..8ae07de
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/BranchesCollection.java
@@ -0,0 +1,79 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.extensions.restapi.AcceptsCreate;
+import com.google.gerrit.extensions.restapi.ChildCollection;
+import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestView;
+import com.google.gerrit.server.project.ListBranches.BranchInfo;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import org.eclipse.jgit.lib.Constants;
+
+import java.io.IOException;
+import java.util.List;
+
+public class BranchesCollection implements
+    ChildCollection<ProjectResource, BranchResource>,
+    AcceptsCreate<ProjectResource> {
+  private final DynamicMap<RestView<BranchResource>> views;
+  private final Provider<ListBranches> list;
+  private final CreateBranch.Factory createBranchFactory;
+
+  @Inject
+  BranchesCollection(DynamicMap<RestView<BranchResource>> views,
+      Provider<ListBranches> list, CreateBranch.Factory createBranchFactory) {
+    this.views = views;
+    this.list = list;
+    this.createBranchFactory = createBranchFactory;
+  }
+
+  @Override
+  public RestView<ProjectResource> list() {
+    return list.get();
+  }
+
+  @Override
+  public BranchResource parse(ProjectResource parent, IdString id)
+      throws ResourceNotFoundException, IOException {
+    String branchName = id.get();
+    if (!branchName.startsWith(Constants.R_REFS)
+        && !branchName.equals(Constants.HEAD)) {
+      branchName = Constants.R_HEADS + branchName;
+    }
+    List<BranchInfo> branches = list.get().apply(parent);
+    for (BranchInfo b : branches) {
+      if (branchName.equals(b.ref)) {
+        return new BranchResource(parent.getControl(), b);
+      }
+    }
+    throw new ResourceNotFoundException();
+  }
+
+  @Override
+  public DynamicMap<RestView<BranchResource>> views() {
+    return views;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public CreateBranch create(ProjectResource parent, IdString name) {
+    return createBranchFactory.create(name.get());
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
new file mode 100644
index 0000000..5985de0
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateBranch.java
@@ -0,0 +1,234 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.gerrit.common.ChangeHooks;
+import com.google.gerrit.common.errors.InvalidRevisionException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.DefaultInput;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestModifyView;
+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.extensions.events.GitReferenceUpdated;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.project.CreateBranch.Input;
+import com.google.gerrit.server.project.ListBranches.BranchInfo;
+import com.google.gerrit.server.util.MagicBranch;
+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.errors.RevisionSyntaxException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.ObjectWalk;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+public class CreateBranch implements RestModifyView<ProjectResource, Input> {
+  private static final Logger log = LoggerFactory.getLogger(CreateBranch.class);
+
+  static class Input {
+    String ref;
+
+    @DefaultInput
+    String revision;
+  }
+
+  static interface Factory {
+    CreateBranch create(String ref);
+  }
+
+  private final IdentifiedUser identifiedUser;
+  private final GitRepositoryManager repoManager;
+  private final GitReferenceUpdated referenceUpdated;
+  private final ChangeHooks hooks;
+  private String ref;
+
+  @Inject
+  CreateBranch(IdentifiedUser identifiedUser, GitRepositoryManager repoManager,
+      GitReferenceUpdated referenceUpdated, ChangeHooks hooks,
+      @Assisted String ref) {
+    this.identifiedUser = identifiedUser;
+    this.repoManager = repoManager;
+    this.referenceUpdated = referenceUpdated;
+    this.hooks = hooks;
+    this.ref = ref;
+  }
+
+  @Override
+  public BranchInfo apply(ProjectResource rsrc, Input input)
+      throws BadRequestException, ResourceConflictException, IOException {
+    if (input == null) {
+      input = new Input();
+    }
+    if (input.ref != null && !ref.equals(input.ref)) {
+      throw new BadRequestException("ref must match URL");
+    }
+    if (input.revision == null) {
+      input.revision = Constants.HEAD;
+    }
+    while (ref.startsWith("/")) {
+      ref = ref.substring(1);
+    }
+    if (!ref.startsWith(Constants.R_REFS)) {
+      ref = Constants.R_HEADS + ref;
+    }
+    if (!Repository.isValidRefName(ref)) {
+      throw new BadRequestException("invalid branch name \"" + ref + "\"");
+    }
+    if (MagicBranch.isMagicBranch(ref)) {
+      throw new BadRequestException("not allowed to create branches under \""
+          + MagicBranch.getMagicRefNamePrefix(ref) + "\"");
+    }
+
+    final Branch.NameKey name = new Branch.NameKey(rsrc.getNameKey(), ref);
+    final RefControl refControl = rsrc.getControl().controlForRef(name);
+    final Repository repo = repoManager.openRepository(rsrc.getNameKey());
+    try {
+      final ObjectId revid = parseBaseRevision(repo, rsrc.getNameKey(), input.revision);
+      final RevWalk rw = verifyConnected(repo, revid);
+      RevObject object = rw.parseAny(revid);
+
+      if (ref.startsWith(Constants.R_HEADS)) {
+        // Ensure that what we start the branch from is a commit. If we
+        // were given a tag, deference to the commit instead.
+        //
+        try {
+          object = rw.parseCommit(object);
+        } catch (IncorrectObjectTypeException notCommit) {
+          throw new BadRequestException("\"" + input.revision + "\" not a commit");
+        }
+      }
+
+      if (!refControl.canCreate(rw, object)) {
+        throw new IllegalStateException("Cannot create \"" + ref + "\"");
+      }
+
+      try {
+        final RefUpdate u = repo.updateRef(ref);
+        u.setExpectedOldObjectId(ObjectId.zeroId());
+        u.setNewObjectId(object.copy());
+        u.setRefLogIdent(identifiedUser.newRefLogIdent());
+        u.setRefLogMessage("created via REST from " + input.revision, false);
+        final RefUpdate.Result result = u.update(rw);
+        switch (result) {
+          case FAST_FORWARD:
+          case NEW:
+          case NO_CHANGE:
+            referenceUpdated.fire(name.getParentKey(), u);
+            hooks.doRefUpdatedHook(name, u, identifiedUser.getAccount());
+            break;
+          case LOCK_FAILURE:
+            if (repo.getRef(ref) != null) {
+              throw new ResourceConflictException("branch \"" + ref
+                  + "\" already exists");
+            }
+            String refPrefix = getRefPrefix(ref);
+            while (!Constants.R_HEADS.equals(refPrefix)) {
+              if (repo.getRef(refPrefix) != null) {
+                throw new ResourceConflictException("Cannot create branch \""
+                    + ref + "\" since it conflicts with branch \"" + refPrefix
+                    + "\".");
+              }
+              refPrefix = getRefPrefix(refPrefix);
+            }
+          default: {
+            throw new IOException(result.name());
+          }
+        }
+
+        BranchInfo b = new BranchInfo();
+        b.ref = ref;
+        b.revision = revid.getName();
+        b.setCanDelete(refControl.canDelete());
+        return b;
+      } catch (IOException err) {
+        log.error("Cannot create branch \"" + name + "\"", err);
+        throw err;
+      }
+    } catch (InvalidRevisionException e) {
+      throw new BadRequestException("invalid revision \"" + input.revision + "\"");
+    } finally {
+      repo.close();
+    }
+  }
+
+  private static String getRefPrefix(final String refName) {
+    final int i = refName.lastIndexOf('/');
+    if (i > Constants.R_HEADS.length() - 1) {
+      return refName.substring(0, i);
+    }
+    return Constants.R_HEADS;
+  }
+
+  private ObjectId parseBaseRevision(Repository repo,
+      Project.NameKey projectName, String baseRevision)
+      throws InvalidRevisionException {
+    try {
+      final ObjectId revid = repo.resolve(baseRevision);
+      if (revid == null) {
+        throw new InvalidRevisionException();
+      }
+      return revid;
+    } catch (IOException err) {
+      log.error("Cannot resolve \"" + baseRevision + "\" in project \""
+          + projectName.get() + "\"", err);
+      throw new InvalidRevisionException();
+    } catch (RevisionSyntaxException err) {
+      log.error("Invalid revision syntax \"" + baseRevision + "\"", err);
+      throw new InvalidRevisionException();
+    }
+  }
+
+  private RevWalk verifyConnected(final Repository repo, final ObjectId revid)
+      throws InvalidRevisionException {
+    try {
+      final ObjectWalk rw = new ObjectWalk(repo);
+      try {
+        rw.markStart(rw.parseCommit(revid));
+      } catch (IncorrectObjectTypeException err) {
+        throw new InvalidRevisionException();
+      }
+      for (final Ref r : repo.getAllRefs().values()) {
+        try {
+          rw.markUninteresting(rw.parseAny(r.getObjectId()));
+        } catch (MissingObjectException err) {
+          continue;
+        }
+      }
+      rw.checkConnectivity();
+      return rw;
+    } catch (IncorrectObjectTypeException err) {
+      throw new InvalidRevisionException();
+    } catch (MissingObjectException err) {
+      throw new InvalidRevisionException();
+    } catch (IOException err) {
+      log.error("Repository \"" + repo.getDirectory()
+          + "\" may be corrupt; suggest running git fsck", err);
+      throw new InvalidRevisionException();
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetBranch.java
new file mode 100644
index 0000000..781cf01
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetBranch.java
@@ -0,0 +1,26 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.project.ListBranches.BranchInfo;
+
+public class GetBranch implements RestReadView<BranchResource> {
+
+  @Override
+  public BranchInfo apply(BranchResource rsrc) {
+    return rsrc.getBranchInfo();
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java
new file mode 100644
index 0000000..b01c757
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListBranches.java
@@ -0,0 +1,160 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ListBranches implements RestReadView<ProjectResource> {
+
+  private final GitRepositoryManager repoManager;
+
+  @Inject
+  public ListBranches(GitRepositoryManager repoManager) {
+    this.repoManager = repoManager;
+  }
+
+  @Override
+  public List<BranchInfo> apply(ProjectResource rsrc)
+      throws ResourceNotFoundException, IOException {
+    List<BranchInfo> branches = Lists.newArrayList();
+
+    BranchInfo headBranch = null;
+    BranchInfo configBranch = null;
+    final Set<String> targets = Sets.newHashSet();
+
+    final Repository db;
+    try {
+      db = repoManager.openRepository(rsrc.getNameKey());
+    } catch (RepositoryNotFoundException noGitRepository) {
+      throw new ResourceNotFoundException();
+    }
+
+    try {
+      final Map<String, Ref> all = db.getAllRefs();
+
+      if (!all.containsKey(Constants.HEAD)) {
+        // The branch pointed to by HEAD doesn't exist yet, so getAllRefs
+        // filtered it out. If we ask for it individually we can find the
+        // underlying target and put it into the map anyway.
+        //
+        try {
+          Ref head = db.getRef(Constants.HEAD);
+          if (head != null) {
+            all.put(Constants.HEAD, head);
+          }
+        } catch (IOException e) {
+          // Ignore the failure reading HEAD.
+        }
+      }
+
+      for (final Ref ref : all.values()) {
+        if (ref.isSymbolic()) {
+          targets.add(ref.getTarget().getName());
+        }
+      }
+
+      for (final Ref ref : all.values()) {
+        if (ref.isSymbolic()) {
+          // A symbolic reference to another branch, instead of
+          // showing the resolved value, show the name it references.
+          //
+          String target = ref.getTarget().getName();
+          RefControl targetRefControl = rsrc.getControl().controlForRef(target);
+          if (!targetRefControl.isVisible()) {
+            continue;
+          }
+          if (target.startsWith(Constants.R_HEADS)) {
+            target = target.substring(Constants.R_HEADS.length());
+          }
+
+          BranchInfo b = new BranchInfo();
+          b.ref = ref.getName();
+          b.revision = target;
+
+          if (Constants.HEAD.equals(ref.getName())) {
+            b.setCanDelete(false);
+            headBranch = b;
+          } else {
+            b.setCanDelete(targetRefControl.canDelete());
+            branches.add(b);
+          }
+          continue;
+        }
+
+        final RefControl refControl = rsrc.getControl().controlForRef(ref.getName());
+        if (refControl.isVisible()) {
+          if (ref.getName().startsWith(Constants.R_HEADS)) {
+            branches.add(createBranchInfo(ref, refControl, targets));
+          } else if (GitRepositoryManager.REF_CONFIG.equals(ref.getName())) {
+            configBranch = createBranchInfo(ref, refControl, targets);
+          }
+        }
+      }
+    } finally {
+      db.close();
+    }
+    Collections.sort(branches, new Comparator<BranchInfo>() {
+      @Override
+      public int compare(final BranchInfo a, final BranchInfo b) {
+        return a.ref.compareTo(b.ref);
+      }
+    });
+    if (configBranch != null) {
+      branches.add(0, configBranch);
+    }
+    if (headBranch != null) {
+      branches.add(0, headBranch);
+    }
+    return branches;
+  }
+
+  private static BranchInfo createBranchInfo(Ref ref, RefControl refControl,
+      Set<String> targets) {
+    BranchInfo b = new BranchInfo();
+    b.ref = ref.getName();
+    if (ref.getObjectId() != null) {
+      b.revision = ref.getObjectId().name();
+    }
+    b.setCanDelete(!targets.contains(ref.getName()) && refControl.canDelete());
+    return b;
+  }
+
+  public static class BranchInfo {
+    public String ref;
+    public String revision;
+    public Boolean canDelete;
+
+    void setCanDelete(boolean canDelete) {
+      this.canDelete = canDelete ? true : null;
+    }
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
index d979245..3b44f66 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/Module.java
@@ -14,13 +14,13 @@
 
 package com.google.gerrit.server.project;
 
+import static com.google.gerrit.server.project.BranchResource.BRANCH_KIND;
 import static com.google.gerrit.server.project.ChildProjectResource.CHILD_PROJECT_KIND;
 import static com.google.gerrit.server.project.DashboardResource.DASHBOARD_KIND;
 import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
 
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.RestApiModule;
-import com.google.gerrit.server.project.CreateProject;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public class Module extends RestApiModule {
@@ -31,6 +31,7 @@
 
     DynamicMap.mapOf(binder(), PROJECT_KIND);
     DynamicMap.mapOf(binder(), CHILD_PROJECT_KIND);
+    DynamicMap.mapOf(binder(), BRANCH_KIND);
     DynamicMap.mapOf(binder(), DASHBOARD_KIND);
 
     put(PROJECT_KIND).to(PutProject.class);
@@ -51,6 +52,11 @@
     get(PROJECT_KIND, "statistics.git").to(GetStatistics.class);
     post(PROJECT_KIND, "gc").to(GarbageCollect.class);
 
+    child(PROJECT_KIND, "branches").to(BranchesCollection.class);
+    put(BRANCH_KIND).to(PutBranch.class);
+    get(BRANCH_KIND).to(GetBranch.class);
+    install(new FactoryModuleBuilder().build(CreateBranch.Factory.class));
+
     child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class);
     get(DASHBOARD_KIND).to(GetDashboard.class);
     put(DASHBOARD_KIND).to(SetDashboard.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutBranch.java
new file mode 100644
index 0000000..2cd5659
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutBranch.java
@@ -0,0 +1,29 @@
+// Copyright (C) 2013 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.project;
+
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.project.CreateBranch.Input;
+
+public class PutBranch implements RestModifyView<BranchResource, Input> {
+
+  @Override
+  public Object apply(BranchResource rsrc, Input input)
+      throws ResourceConflictException {
+    throw new ResourceConflictException("Branch \"" + rsrc.getBranchInfo().ref
+        + "\" already exists");
+  }
+}
diff --git a/gerrit-sshd/BUCK b/gerrit-sshd/BUCK
index 72e63cb..769be58 100644
--- a/gerrit-sshd/BUCK
+++ b/gerrit-sshd/BUCK
@@ -2,13 +2,27 @@
   name = 'sshd',
   srcs = glob(['src/main/java/**/*.java']),
   deps = [
+    '//gerrit-extension-api:api',
     '//gerrit-cache-h2:cache-h2',
+    '//gerrit-common:server',
+    '//gerrit-patch-jgit:server',
+    '//gerrit-reviewdb:server',
     '//gerrit-server:server',
     '//gerrit-util-cli:cli',
+    '//lib:args4j',
+    '//lib:gson',
+    '//lib:guava',
+    '//lib:gwtorm',
+    '//lib:jsch',
+    '//lib/commons:codec',
+    '//lib/guice:guice',
+    '//lib/guice:guice-assistedinject',
+    '//lib/guice:guice-servlet',  # SSH should not depend on servlet
     '//lib/log:api',
     '//lib/log:log4j',
     '//lib/mina:core',
     '//lib/mina:sshd',
+    '//lib/jgit:jgit',
   ],
   compile_deps = [
     '//lib/bouncycastle:bcprov',
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/Commands.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/Commands.java
index 929a895..1a5e62cc 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/Commands.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/Commands.java
@@ -16,7 +16,6 @@
 
 import com.google.inject.Key;
 
-import org.apache.commons.lang.StringUtils;
 import org.apache.sshd.server.Command;
 
 import java.lang.annotation.Annotation;
@@ -124,7 +123,7 @@
     NestedCommandNameImpl(final CommandName parent, final String name) {
       this.parent = parent;
       this.name = name;
-      this.descr = StringUtils.EMPTY;
+      this.descr = "";
     }
 
     NestedCommandNameImpl(final CommandName parent, final String name,
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 69598ce..5f6130c 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
@@ -34,6 +34,7 @@
 
 package com.google.gerrit.util.cli;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.LinkedHashMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -153,12 +154,7 @@
         }
         out.write('=');
 
-        String var = handler.getDefaultMetaVariable();
-        if (handler instanceof EnumOptionHandler) {
-          var = var.substring(1, var.length() - 1);
-          var = var.replaceAll(" ", "");
-        }
-        out.write(var);
+        out.write(metaVar(handler, n));
         if (!n.required()) {
           out.write(']');
         }
@@ -186,6 +182,17 @@
     }
   }
 
+  private static String metaVar(OptionHandler<?> handler, NamedOptionDef n) {
+    String var = n.metaVar();
+    if (Strings.isNullOrEmpty(var)) {
+      var = handler.getDefaultMetaVariable();
+      if (handler instanceof EnumOptionHandler) {
+        var = var.substring(1, var.length() - 1).replace(" ", "");
+      }
+    }
+    return var;
+  }
+
   public boolean wasHelpRequestedByOption() {
     return parser.help.value;
   }
diff --git a/gerrit-war/BUCK b/gerrit-war/BUCK
index 2f2b34c..8cf24ad 100644
--- a/gerrit-war/BUCK
+++ b/gerrit-war/BUCK
@@ -1,14 +1,22 @@
-java_library(
+java_library2(
   name = 'init',
   srcs = glob(['src/main/java/**/*.java']),
   deps = [
+    '//gerrit-cache-h2:cache-h2',
+    '//gerrit-extension-api:api',
+    '//gerrit-httpd:httpd',
+    '//gerrit-openid:openid',
+    '//gerrit-reviewdb:server',
     '//gerrit-server:common_rules',
     '//gerrit-server:server',
-    '//gerrit-httpd:httpd',
     '//gerrit-sshd:sshd',
-    '//gerrit-cache-h2:cache-h2',
-    '//gerrit-openid:openid',
+    '//lib:gwtorm',
+    '//lib/guice:guice',
+    '//lib/guice:guice-servlet',
+    '//lib/log:api',
+    '//lib/jgit:jgit',
   ],
+  compile_deps = ['//lib:servlet-api-3_0'],
   visibility = [
     '//:',
     '//gerrit-gwtdebug:gwtdebug',
diff --git a/gerrit-war/src/main/resources/log4j.properties b/gerrit-war/src/main/resources/log4j.properties
index 250fa4c..1fcca6d 100644
--- a/gerrit-war/src/main/resources/log4j.properties
+++ b/gerrit-war/src/main/resources/log4j.properties
@@ -38,10 +38,8 @@
 
 # Silence non-critical messages from openid4java
 #
+log4j.logger.org.apache.http=WARN
 log4j.logger.org.apache.xml=WARN
-log4j.logger.httpclient.wire=WARN
-log4j.logger.org.apache.commons.httpclient=WARN
-log4j.logger.org.apache.commons.httpclient.HttpMethodBase=ERROR
 log4j.logger.org.openid4java=WARN
 log4j.logger.org.openid4java.consumer.ConsumerManager=FATAL
 log4j.logger.org.openid4java.discovery.Discovery=ERROR
diff --git a/lib/BUCK b/lib/BUCK
index c4de186..9f24e6f 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -169,7 +169,6 @@
   sha1 = '3fc3013adf98701efcc594a1ea99a3f841dc81bb',
   license = 'Apache2.0',
   attach_source = False,
-  visibility = [],
 )
 
 maven_jar(
diff --git a/lib/guice/BUCK b/lib/guice/BUCK
index 0cfe5f5..48c3be3 100644
--- a/lib/guice/BUCK
+++ b/lib/guice/BUCK
@@ -7,16 +7,24 @@
   'META-INF/NOTICE',
 ]
 
-maven_jar(
+java_library(
   name = 'guice',
+  deps = [
+    ':guice_library',
+    ':javax-inject',
+  ],
+  export_deps = True,
+  visibility = ['PUBLIC'],
+)
+
+maven_jar(
+  name = 'guice_library',
   id = 'com.google.inject:guice:' + VERSION,
   sha1 = '9d84f15fe35e2c716a02979fb62f50a29f38aefa',
   license = 'Apache2.0',
-  deps = [
-    ':javax-inject',
-    ':aopalliance',
-  ],
+  deps = [':aopalliance'],
   exclude = EXCLUDE,
+  visibility = [],
 )
 
 maven_jar(
@@ -37,7 +45,6 @@
   exclude = EXCLUDE,
 )
 
-
 maven_jar(
   name = 'aopalliance',
   id = 'aopalliance:aopalliance:1.0',
diff --git a/lib/jetty/BUCK b/lib/jetty/BUCK
index b7bdbac..6eac1a9 100644
--- a/lib/jetty/BUCK
+++ b/lib/jetty/BUCK
@@ -34,8 +34,8 @@
     ':continuation',
     ':http',
   ],
+  export_deps = True,
   exclude = EXCLUDE,
-  visibility = [],
 )
 
 maven_jar(
@@ -44,7 +44,6 @@
   sha1 = 'f60cfe6267038000b459508529c88737601081e4',
   license = 'Apache2.0',
   exclude = EXCLUDE,
-  visibility = [],
 )
 
 maven_jar(
@@ -54,7 +53,6 @@
   license = 'Apache2.0',
   deps = [':io'],
   exclude = EXCLUDE,
-  visibility = [],
 )
 
 maven_jar(
diff --git a/lib/maven.defs b/lib/maven.defs
index 2d2d656..3aeb891 100644
--- a/lib/maven.defs
+++ b/lib/maven.defs
@@ -35,6 +35,7 @@
     sha1 = '', bin_sha1 = '', src_sha1 = '',
     repository = MAVEN_CENTRAL,
     attach_source = True,
+    export_deps = False,
     visibility = ['PUBLIC']):
   from os import path
 
@@ -72,7 +73,6 @@
     deps = ['//tools:download_jar'],
     out = binjar,
   )
-  download = [':' + name + '__download_bin']
   license = ['//lib:LICENSE-' + license]
 
   if src_sha1 or attach_source:
@@ -90,17 +90,36 @@
       prebuilt_jar(
         name = name + '_src',
         binary_jar = genfile(srcjar),
-        deps = [':' + name + '__download_src'] + license,
+        deps = license + [':' + name + '__download_src'],
         visibility = visibility,
       )
-    download.append(':' + name + '__download_src')
   else:
     srcjar = None
+    genrule(
+      name = name + '__download_src',
+      cmd = ':>$OUT',
+      srcs = [],
+      out = '__' + name + '__no_src',
+    )
 
-  prebuilt_jar(
-    name = name,
-    deps = deps + download + license,
-    binary_jar = genfile(binjar),
-    source_jar = genfile(srcjar) if srcjar else None,
-    visibility = visibility,
-  )
+  if export_deps:
+    prebuilt_jar(
+      name = name + '__jar',
+      deps = deps + license + [':' + name + '__download_bin'],
+      binary_jar = genfile(binjar),
+      source_jar = genfile(srcjar) if srcjar else None,
+    )
+    java_library(
+      name = name,
+      deps = [':' + name + '__jar'],
+      export_deps = True,
+      visibility = visibility,
+    )
+  else:
+    prebuilt_jar(
+      name = name,
+      deps = deps + license + [':' + name + '__download_bin'],
+      binary_jar = genfile(binjar),
+      source_jar = genfile(srcjar) if srcjar else None,
+      visibility = visibility,
+    )
diff --git a/lib/openid/BUCK b/lib/openid/BUCK
index 19ce077..b766532 100644
--- a/lib/openid/BUCK
+++ b/lib/openid/BUCK
@@ -1,25 +1,18 @@
 include_defs('//lib/maven.defs')
 
-java_library(
-  name = 'consumer',
-  deps = [
-    ':http-client',
-    ':nekohtml',
-    ':nodeps',
-  ],
-  visibility = ['PUBLIC'],
-)
-
 maven_jar(
-  name = 'nodeps',
-  id = 'org.openid4java:openid4java-nodeps:0.9.6',
-  sha1 = '52ca394f5f6d38b78e35a5a6a0a341dc5b3aaf34',
+  name = 'consumer',
+  id = 'org.openid4java:openid4java:0.9.8',
+  sha1 = 'de4f1b33d3b0f0b2ab1d32834ec1190b39db4160',
   license = 'Apache2.0',
   deps = [
+    ':httpclient',
+    ':nekohtml',
+    ':xerces',
     '//lib/commons:logging',
     '//lib/guice:guice',
   ],
-  visibility = [],
+  visibility = ['PUBLIC'],
 )
 
 maven_jar(
@@ -42,32 +35,29 @@
 )
 
 maven_jar(
-  name = 'http-client',
-  id = 'org.apache.httpcomponents:httpclient:4.0',
-  sha1 = 'a76d7fd8033d48b4c67b4ccf159abb080c1059b6',
+  name = 'httpclient',
+  id = 'org.apache.httpcomponents:httpclient:4.1',
+  sha1 = '93cd011acb220de08b57d96106e5800d7097742b',
   license = 'Apache2.0',
   deps = [
-    ':http-core',
+    ':httpcore',
     '//lib/commons:codec',
     '//lib/commons:logging',
   ],
   exclude = [
-    'META-INF/DEPENDENCIES',
-    'META-INF/LICENSE',
-    'META-INF/NOTICE',
+    'META-INF/LICENSE.txt',
+    'META-INF/NOTICE.txt',
   ],
   visibility = ['//gerrit-acceptance-tests:'],
 )
 
 maven_jar(
-  name = 'http-core',
-  id = 'org.apache.httpcomponents:httpcore:4.0.1',
-  sha1 = 'e813b8722c387b22e1adccf7914729db09bcb4a9',
+  name = 'httpcore',
+  id = 'org.apache.httpcomponents:httpcore:4.1',
+  sha1 = '33fc26c02f8043ab0ede19eadc8c9885386b255c',
   license = 'Apache2.0',
   exclude = [
-    'META-INF/DEPENDENCIES',
-    'META-INF/LICENSE',
-    'META-INF/NOTICE',
+    'META-INF/LICENSE.txt',
+    'META-INF/NOTICE.txt',
   ],
-  visibility = [],
 )
diff --git a/lib/prolog/java/BuckPrologCompiler.java b/lib/prolog/java/BuckPrologCompiler.java
index d23e15d..b731ea7 100644
--- a/lib/prolog/java/BuckPrologCompiler.java
+++ b/lib/prolog/java/BuckPrologCompiler.java
@@ -12,11 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import com.googlecode.prolog_cafe.compiler.CompileException;
+import com.googlecode.prolog_cafe.compiler.Compiler;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.jar.JarEntry;
@@ -29,9 +33,6 @@
 import javax.tools.StandardJavaFileManager;
 import javax.tools.ToolProvider;
 
-import com.googlecode.prolog_cafe.compiler.CompileException;
-import com.googlecode.prolog_cafe.compiler.Compiler;
-
 public class BuckPrologCompiler {
   public static void main(String[] argv) throws IOException, CompileException {
     List<File> srcs = new ArrayList<File>();
@@ -82,14 +83,16 @@
         classpath.append(jar.getPath());
       }
       ArrayList<String> args = new ArrayList<String>();
-      args.add("-g:none");
-      args.add("-nowarn");
+      args.addAll(Arrays.asList(new String[]{
+          "-source", "6",
+          "-target", "6",
+          "-g:none",
+          "-nowarn",
+          "-d", classes.getPath()}));
       if (classpath.length() > 0) {
         args.add("-classpath");
         args.add(classpath.toString());
       }
-      args.add("-d");
-      args.add(classes.getPath());
       if (!javac.getTask(null, fm, d, args, null,
           fm.getJavaFileObjectsFromFiles(find(java, ".java"))).call()) {
         StringBuilder msg = new StringBuilder();
diff --git a/plugins/replication b/plugins/replication
index e7d3274..6b5ca01 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit e7d327447da27f060d0f9c0db6b52dfbe25ec48f
+Subproject commit 6b5ca0107992973f5d8b3b9b35bd68653d8c2219
diff --git a/pom.xml b/pom.xml
index 07c8992..0037bdad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -526,9 +526,8 @@
 
       <dependency>
         <groupId>org.openid4java</groupId>
-        <artifactId>openid4java-consumer</artifactId>
-        <version>0.9.6</version>
-        <type>pom</type>
+        <artifactId>openid4java</artifactId>
+        <version>0.9.8</version>
         <exclusions>
           <exclusion>
             <!-- conflicts with our use of guice 3.0 -->
@@ -575,12 +574,6 @@
       </dependency>
 
       <dependency>
-        <groupId>org.apache.httpcomponents</groupId>
-        <artifactId>httpclient</artifactId>
-        <version>4.0</version>
-      </dependency>
-
-      <dependency>
         <groupId>com.jcraft</groupId>
         <artifactId>jsch</artifactId>
         <version>0.1.44-1</version>
diff --git a/tools/BUCK b/tools/BUCK
index 306b2f4..ee384a1 100644
--- a/tools/BUCK
+++ b/tools/BUCK
@@ -1,4 +1,10 @@
 python_binary(
+  name = 'download_all',
+  main = 'download_all.py',
+  visibility = ['PUBLIC'],
+)
+
+python_binary(
   name = 'download_jar',
   main = 'download_jar.py',
   visibility = ['PUBLIC'],
diff --git a/tools/download_all.py b/tools/download_all.py
new file mode 100755
index 0000000..b21140b
--- /dev/null
+++ b/tools/download_all.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+# Copyright (C) 2013 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.
+
+from optparse import OptionParser
+import re
+from subprocess import check_call, CalledProcessError, Popen, PIPE
+
+MAIN = ['//tools/eclipse:classpath']
+PAT = re.compile(r'"(//.*?__download_[^"]*)" -> "//tools:download_jar"')
+
+opts = OptionParser()
+opts.add_option('--src', action='store_true')
+args, _ = opts.parse_args()
+
+targets = set()
+
+p = Popen(['buck', 'audit', 'classpath', '--dot'] + MAIN, stdout = PIPE)
+for line in p.stdout:
+  m = PAT.search(line)
+  if m:
+    n = m.group(1)
+    if args.src and n.endswith('__download_bin'):
+      n = n[:-4] + '_src'
+    targets.add(n)
+r = p.wait()
+if r != 0:
+  exit(r)
+
+try:
+  check_call(['buck', 'build'] + sorted(targets))
+except CalledProcessError as err:
+  exit(1)
diff --git a/tools/download_jar.py b/tools/download_jar.py
index 8584092..97ee608 100755
--- a/tools/download_jar.py
+++ b/tools/download_jar.py
@@ -28,6 +28,11 @@
   'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2',
 }
 
+GERRIT_HOME = path.expanduser('~/.gerritcodereview')
+CACHE_DIR = path.join(GERRIT_HOME, 'buck-cache')
+LOCAL_PROPERTIES = 'local.properties'
+
+
 def hashfile(p):
   d = sha1()
   with open(p, 'rb') as f:
@@ -48,8 +53,19 @@
       raise err
 
 def download_properties(root_dir):
-  local_prop = path.join(root_dir, 'local.properties')
+  """ Get the download properties.
+
+  First tries to find the properties file in the given root directory,
+  and if not found there, tries in the Gerrit settings folder in the
+  user's home directory.
+
+  Returns a set of download properties, which may be empty.
+
+  """
   p = {}
+  local_prop = path.join(root_dir, LOCAL_PROPERTIES)
+  if not path.isfile(local_prop):
+    local_prop = path.join(GERRIT_HOME, LOCAL_PROPERTIES)
   if path.isfile(local_prop):
     try:
       with open(local_prop) as fd:
@@ -58,17 +74,17 @@
             d = [e.strip() for e in line.split('=', 1)]
             name, url = d[0], d[1]
             p[name[len('download.'):]] = url
-    except OSError as err:
+    except OSError:
       pass
   return p
 
-def cache_entry(root_dir, args):
+def cache_entry(args):
   if args.v:
     h = args.v
   else:
     h = sha1(args.u).hexdigest()
   name = '%s-%s' % (path.basename(args.o), h)
-  return path.join(root_dir, 'buck-cache', name)
+  return path.join(CACHE_DIR, name)
 
 def resolve_url(url, redirects):
   s = url.find(':')
@@ -81,10 +97,8 @@
     root = redirects[scheme]
   else:
     root = REPO_ROOTS[scheme]
-  while root.endswith('/'):
-    root = root[:-1]
-  while rest.startswith('/'):
-    rest = rest[1:]
+  root = root.rstrip('/')
+  rest = rest.lstrip('/')
   return '/'.join([root, rest])
 
 opts = OptionParser()
@@ -102,7 +116,7 @@
     break
 
 redirects = download_properties(root_dir)
-cache_ent = cache_entry(root_dir, args)
+cache_ent = cache_entry(args)
 src_url = resolve_url(args.u, redirects)
 
 if not path.exists(cache_ent):
@@ -110,8 +124,12 @@
     safe_mkdirs(path.dirname(cache_ent))
     print('Download %s' % src_url, file=stderr)
     check_call(['curl', '--proxy-anyauth', '-sfo', cache_ent, src_url])
-  except (OSError, CalledProcessError) as err:
-    print('error using curl: %s' % str(err), file=stderr)
+  except OSError as err:
+    print('error creating directory %s: %s' %
+          (path.dirname(cache_ent), err), file=stderr)
+    exit(1)
+  except CalledProcessError as err:
+    print('error using curl: %s' % err, file=stderr)
     exit(1)
 
 if args.v:
@@ -138,13 +156,16 @@
     finally:
       zf.close()
   except (BadZipfile, LargeZipFile) as err:
-    print("error opening %s: %s"  % (cache_ent, str(err)), file=stderr)
+    print("error opening %s: %s"  % (cache_ent, err), file=stderr)
     exit(1)
 
 safe_mkdirs(path.dirname(args.o))
 if exclude:
   shutil.copyfile(cache_ent, args.o)
-  check_call(['zip', '-d', args.o] + exclude)
+  try:
+    check_call(['zip', '-d', args.o] + exclude)
+  except CalledProcessError as err:
+    print('error removing files from zip: %s' % err, file=stderr)
 else:
   try:
     link(cache_ent, args.o)