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)