Merge "Remove user-rescoping from PermissionBackend"
diff --git a/0001-Replace-native-http-git-_archive-with-Skylark-rules.patch b/0001-Replace-native-http-git-_archive-with-Skylark-rules.patch
deleted file mode 100644
index 3ccf5cd..0000000
--- a/0001-Replace-native-http-git-_archive-with-Skylark-rules.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-Date: Wed, 30 May 2018 21:22:18 +0200
-Subject: [PATCH] Replace native {http,git}_archive with Skylark rules
-
-See [1] for more details.
-
-Test Plan:
-
-* Apply this CL on Bazel master: [2] and build bazel
-* Run with this custom built bazel version:
-
- $ bazel test //javatests/...
- $ bazel test //closure/...
-
-[1] https://groups.google.com/d/topic/bazel-discuss/dO2MHQLwJF0/discussion
-[2] https://bazel-review.googlesource.com/#/c/bazel/+/55932/
----
- closure/repositories.bzl | 23 ++++++++++++-----------
- 1 file changed, 12 insertions(+), 11 deletions(-)
-
-diff --git a/closure/repositories.bzl b/closure/repositories.bzl
-index 9b84a72..2816fb6 100644
---- closure/repositories.bzl
-+++ closure/repositories.bzl
-@@ -14,6 +14,7 @@
-
- """External dependencies for Closure Rules."""
-
-+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
- load("//closure/private:java_import_external.bzl", "java_import_external")
- load("//closure/private:platform_http_file.bzl", "platform_http_file")
- load("//closure:filegroup_external.bzl", "filegroup_external")
-@@ -405,7 +406,7 @@ def com_google_common_html_types():
- )
-
- def com_google_common_html_types_html_proto():
-- native.http_file(
-+ http_file(
- name = "com_google_common_html_types_html_proto",
- sha256 = "6ece202f11574e37d0c31d9cf2e9e11a0dbc9218766d50d211059ebd495b49c3",
- urls = [
-@@ -633,7 +634,7 @@ def com_google_javascript_closure_compiler():
-
- def com_google_javascript_closure_library():
- # After updating: bazel run //closure/library:regenerate -- "$PWD"
-- native.new_http_archive(
-+ http_archive(
- name = "com_google_javascript_closure_library",
- urls = [
- "https://mirror.bazel.build/github.com/google/closure-library/archive/v20180405.tar.gz",
-@@ -658,7 +659,7 @@ def com_google_jsinterop_annotations():
-
- def com_google_protobuf():
- # Note: Protobuf 3.6.0+ is going to use C++11
-- native.http_archive(
-+ http_archive(
- name = "com_google_protobuf",
- strip_prefix = "protobuf-3.5.1",
- sha256 = "826425182ee43990731217b917c5c3ea7190cfda141af4869e6d4ad9085a740f",
-@@ -669,7 +670,7 @@ def com_google_protobuf():
- )
-
- def com_google_protobuf_js():
-- native.new_http_archive(
-+ http_archive(
- name = "com_google_protobuf_js",
- urls = [
- "https://mirror.bazel.build/github.com/google/protobuf/archive/v3.5.1.tar.gz",
-@@ -722,7 +723,7 @@ def com_google_template_soy():
- )
-
- def com_google_template_soy_jssrc():
-- native.new_http_archive(
-+ http_archive(
- name = "com_google_template_soy_jssrc",
- sha256 = "c76ab4cb6e46a7c76336640b3c40d6897b420209a6c0905cdcd32533dda8126a",
- urls = [
-@@ -757,7 +758,7 @@ def com_squareup_javapoet():
- )
-
- def fonts_noto_hinted_deb():
-- native.http_file(
-+ http_file(
- name = "fonts_noto_hinted_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/f/fonts-noto/fonts-noto-hinted_20161116-1_all.deb",
-@@ -767,7 +768,7 @@ def fonts_noto_hinted_deb():
- )
-
- def fonts_noto_mono_deb():
-- native.http_file(
-+ http_file(
- name = "fonts_noto_mono_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/f/fonts-noto/fonts-noto-mono_20161116-1_all.deb",
-@@ -801,7 +802,7 @@ def javax_inject():
- )
-
- def libexpat_amd64_deb():
-- native.http_file(
-+ http_file(
- name = "libexpat_amd64_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/e/expat/libexpat1_2.1.0-6+deb8u3_amd64.deb",
-@@ -811,7 +812,7 @@ def libexpat_amd64_deb():
- )
-
- def libfontconfig_amd64_deb():
-- native.http_file(
-+ http_file(
- name = "libfontconfig_amd64_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.3+deb8u1_amd64.deb",
-@@ -821,7 +822,7 @@ def libfontconfig_amd64_deb():
- )
-
- def libfreetype_amd64_deb():
-- native.http_file(
-+ http_file(
- name = "libfreetype_amd64_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.5.2-3+deb8u1_amd64.deb",
-@@ -831,7 +832,7 @@ def libfreetype_amd64_deb():
- )
-
- def libpng_amd64_deb():
-- native.http_file(
-+ http_file(
- name = "libpng_amd64_deb",
- urls = [
- "https://mirror.bazel.build/http.us.debian.org/debian/pool/main/libp/libpng/libpng12-0_1.2.50-2+deb8u2_amd64.deb",
---
-2.16.3
-
diff --git a/0002-Bump-Dagger-to-2.14.1-to-support-Java-9.patch b/0002-Bump-Dagger-to-2.14.1-to-support-Java-9.patch
deleted file mode 100644
index df6780d..0000000
--- a/0002-Bump-Dagger-to-2.14.1-to-support-Java-9.patch
+++ /dev/null
@@ -1,116 +0,0 @@
-Date: Thu, 21 Jun 2018 19:29:13 +0200
-Subject: [PATCH 2/2] Bump Dagger to 2.14.1 to support Java 9
-
-Closes #275
----
- closure/repositories.bzl | 41 +++++++++++++++++++++++++++++------------
- 1 file changed, 29 insertions(+), 12 deletions(-)
-
-diff --git a/closure/repositories.bzl b/closure/repositories.bzl
-index 2816fb6..fe63b6f 100644
---- closure/repositories.bzl
-+++ closure/repositories.bzl
-@@ -35,6 +35,7 @@ def closure_repositories(
- omit_com_google_dagger=False,
- omit_com_google_dagger_compiler=False,
- omit_com_google_dagger_producers=False,
-+ omit_com_google_dagger_spi=False,
- omit_com_google_errorprone_error_prone_annotations=False,
- omit_com_google_errorprone_javac_shaded=False,
- omit_com_google_guava=False,
-@@ -101,6 +102,8 @@ def closure_repositories(
- com_google_dagger_compiler()
- if not omit_com_google_dagger_producers:
- com_google_dagger_producers()
-+ if not omit_com_google_dagger_spi:
-+ com_google_dagger_spi()
- if not omit_com_google_errorprone_error_prone_annotations:
- com_google_errorprone_error_prone_annotations()
- if not omit_com_google_errorprone_javac_shaded:
-@@ -418,10 +421,10 @@ def com_google_common_html_types_html_proto():
- def com_google_dagger():
- java_import_external(
- name = "com_google_dagger",
-- jar_sha256 = "8b7806518bed270950002158934fbd8281725ee09909442f2f22b58520b667a7",
-+ jar_sha256 = "374cfee26c9c93f44caa1946583c9edc135bb9a42838476522551ec46aa55c7c",
- jar_urls = [
-- "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger/2.9/dagger-2.9.jar",
-- "https://repo1.maven.org/maven2/com/google/dagger/dagger/2.9/dagger-2.9.jar",
-+ "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger/2.14.1/dagger-2.14.1.jar",
-+ "https://repo1.maven.org/maven2/com/google/dagger/dagger/2.14.1/dagger-2.14.1.jar",
- ],
- licenses = ["notice"], # Apache 2.0
- deps = ["@javax_inject"],
-@@ -441,17 +444,20 @@ def com_google_dagger():
- def com_google_dagger_compiler():
- java_import_external(
- name = "com_google_dagger_compiler",
-- jar_sha256 = "afe356def27710db5b60cad8e7a6c06510dc3d3b854f30397749cbf0d0e71315",
-+ jar_sha256 = "ff16d55273e375349537fc82292b00de04d8a2caca2d4aa6c642692b1a68194d",
- jar_urls = [
-- "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.9/dagger-compiler-2.9.jar",
-- "https://repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.9/dagger-compiler-2.9.jar",
-+ "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.14.1/dagger-compiler-2.14.1.jar",
-+ "https://repo1.maven.org/maven2/com/google/dagger/dagger-compiler/2.14.1/dagger-compiler-2.14.1.jar",
- ],
- licenses = ["notice"], # Apache 2.0
- deps = [
- "@com_google_code_findbugs_jsr305",
- "@com_google_dagger//:runtime",
- "@com_google_dagger_producers//:runtime",
-+ "@com_google_dagger_spi",
- "@com_google_guava",
-+ "@com_google_java_format",
-+ "@com_squareup_javapoet",
- ],
- extra_build_file_content = "\n".join([
- "java_plugin(",
-@@ -471,10 +477,10 @@ def com_google_dagger_compiler():
- def com_google_dagger_producers():
- java_import_external(
- name = "com_google_dagger_producers",
-- jar_sha256 = "b452dc1b95dd02f6272e97b15d1bd35d92b5f484a7d69bb73887b6c6699d8843",
-+ jar_sha256 = "96f950bc4b94d013b0c538632a4bc630f33eda8b01f63ae752b76c5e48783859",
- jar_urls = [
-- "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.9/dagger-producers-2.9.jar",
-- "https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.9/dagger-producers-2.9.jar",
-+ "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.14.1/dagger-producers-2.14.1.jar",
-+ "https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.14.1/dagger-producers-2.14.1.jar",
- ],
- licenses = ["notice"], # Apache 2.0
- deps = [
-@@ -495,6 +501,17 @@ def com_google_dagger_producers():
- ]),
- )
-
-+def com_google_dagger_spi():
-+ java_import_external(
-+ name = "com_google_dagger_spi",
-+ jar_sha256 = "6a20d6c6620fefe50747e9e910e0d0c178cf39d76b67ccffb505ac9a167302cb",
-+ jar_urls = [
-+ "https://mirror.bazel.build/repo1.maven.org/maven2/com/google/dagger/dagger-spi/2.14.1/dagger-spi-2.14.1.jar",
-+ "https://repo1.maven.org/maven2/com/google/dagger/dagger-spi/2.14.1/dagger-spi-2.14.1.jar",
-+ ],
-+ licenses = ["notice"], # Apache 2.0
-+ )
-+
- def com_google_errorprone_error_prone_annotations():
- java_import_external(
- name = "com_google_errorprone_error_prone_annotations",
-@@ -749,10 +766,10 @@ def com_ibm_icu_icu4j():
- def com_squareup_javapoet():
- java_import_external(
- name = "com_squareup_javapoet",
-- jar_sha256 = "2f671d5f056f04922feff78dd60c34979fc9863b16ad706551a9b68842c1a3d0",
-+ jar_sha256 = "5bb5abdfe4366c15c0da3332c57d484e238bd48260d6f9d6acf2b08fdde1efea",
- jar_urls = [
-- "https://mirror.bazel.build/repo1.maven.org/maven2/com/squareup/javapoet/1.7.0/javapoet-1.7.0.jar",
-- "https://repo1.maven.org/maven2/com/squareup/javapoet/1.7.0/javapoet-1.7.0.jar",
-+ "https://mirror.bazel.build/repo1.maven.org/maven2/com/squareup/javapoet/1.9.0/javapoet-1.9.0.jar",
-+ "https://repo1.maven.org/maven2/com/squareup/javapoet/1.9.0/javapoet-1.9.0.jar",
- ],
- licenses = ["notice"], # Apache 2.0
- )
---
-2.16.3
-
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index 3b2b65f..cad9489 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -217,6 +217,19 @@
Default is `INHERIT`, which means that this property is inherited from
the parent project.
+[[change.workInProgressByDefault]]change.workInProgressByDefault::
++
+Controls whether all new changes in the project are set as WIP by default.
++
+Note that a new change will be ready if the `workInProgress` field in
+link:rest-api-changes.html#change-input[ChangeInput] is set to `false` explicitly
+when calling the link:rest-api-changes.html#create-change[CreateChange] REST API
+or the `ready` link:user-upload.html#wip[PushOption] is used during
+the Git push.
++
+Default is `INHERIT`, which means that this property is inherited from
+the parent project.
+
[[submit-section]]
=== Submit section
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index 04f749d..8b4bece 100644
--- a/Documentation/dev-bazel.txt
+++ b/Documentation/dev-bazel.txt
@@ -417,6 +417,92 @@
details. Users should watch the cache sizes and clean them manually if
necessary.
+[[npm-binary]]
+== NPM Binaries
+
+Parts of the PolyGerrit build require running NPM-based JavaScript programs as
+"binaries". We don't attempt to resolve and download NPM dependencies at build
+time, but instead use pre-built bundles of the NPM binary along with all its
+dependencies. Some packages on
+link:https://docs.npmjs.com/misc/registry[registry.npmjs.org] come with their
+dependencies bundled, but this is the exception rather than the rule. More
+commonly, to add a new binary to this list, you will need to bundle the binary
+yourself.
+
+[NOTE]
+We can only use binaries that meet certain licensing requirements, and that do
+not include any native code.
+
+Start by checking that the license and file types of the bundle are acceptable:
+[source,bash]
+----
+ gerrit_repo=/path/to/gerrit
+ package=some-npm-package
+ version=1.2.3
+
+ npm install -g license-checker && \
+ rm -rf /tmp/$package-$version && mkdir -p /tmp/$package-$version && \
+ cd /tmp/$package-$version && \
+ npm install $package@$version && \
+ license-checker | grep licenses: | sort -u
+----
+
+This will output a list of the different licenses used by the package and all
+its transitive dependencies. We can only legally distribute a bundle via our
+storage bucket if the licenses allow us to do so. As long as all of the listed
+license are allowed by
+link:https://opensource.google.com/docs/thirdparty/licenses/[Google's
+standards]. Any `by_exception_only`, commercial, prohibited, or unlisted
+licenses are not allowed; otherwise, it is ok to distribute the source. If in
+doubt, contact a maintainer who is a Googler.
+
+Next, check the file types:
+[source,bash]
+----
+ cd /tmp/$package-$version
+ find . -type f | xargs file | grep -v 'ASCII\|UTF-8\|empty$'
+----
+
+If you see anything that looks like a native library or binary, then we can't
+use the bundle.
+
+If everything looks good, create the bundle, and note the SHA-1:
+[source,bash]
+----
+ $gerrit_repo/tools/js/npm_pack.py $package $version && \
+ sha1sum $package-$version.tgz
+----
+
+This creates a file named `$package-$version.tgz` in your working directory.
+
+Any project maintainer can upload this file to the
+link:https://console.cloud.google.com/storage/browser/gerrit-maven/npm-packages[storage
+bucket].
+
+Finally, add the new binary to the build process:
+----
+ # WORKSPACE
+ npm_binary(
+ name = "some-npm-package",
+ repository = GERRIT,
+ )
+
+ # lib/js/npm.bzl
+ NPM_VERSIONS = {
+ ...
+ "some-npm-package": "1.2.3",
+ }
+
+ NPM_SHA1S = {
+ ...
+ "some-npm-package": "<sha1>",
+ }
+----
+
+To use the binary from the Bazel build, you need to use the `run_npm_binary.py`
+wrapper script. For an example, see the use of `crisper` in `tools/bzl/js.bzl`.
+
+
GERRIT
------
Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/dev-contributing.txt b/Documentation/dev-contributing.txt
index e065e57..62d73cc 100644
--- a/Documentation/dev-contributing.txt
+++ b/Documentation/dev-contributing.txt
@@ -164,7 +164,7 @@
To format Java source code, Gerrit uses the
link:https://github.com/google/google-java-format[`google-java-format`]
-tool (version 1.5), and to format Bazel BUILD and WORKSPACE files the
+tool (version 1.5), and to format Bazel BUILD, WORKSPACE and .bzl files the
link:https://github.com/bazelbuild/buildtools/tree/master/buildifier[`buildifier`]
tool (version 0.12.0).
These tools automatically apply format according to the style guides; this
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 35ff40b..5c008c7 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -2734,7 +2734,7 @@
[source, java]
----
import com.google.gerrit.extensions.annotations.ExtensionPoint;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
public class MyPlugin implements MailFilter {
public boolean shouldProcessMessage(MailMessage message) {
@@ -2871,6 +2871,17 @@
Plugin authors should also consider binding their SubmitRule using a `Gerrit-BatchModule`.
See link:dev-plugins.html[Batch runtime] for more informations.
+
+The SubmitRule extension point allows you to write complex rules, but writing
+small self-contained rules should be preferred: doing so allows end users to
+compose several rules to form more complex submit checks.
+
+The `SubmitRequirement` class allows rules to communicate what the user needs
+to change in order to be compliant. These requirements should be kept once they
+are met, but marked as `OK`. If the requirements were not displayed, reviewers
+would need to use their precious time to manually check that they were met.
+
+
== SEE ALSO
* link:js-api.html[JavaScript API]
diff --git a/Documentation/install-quick.txt b/Documentation/install-quick.txt
index 7b80229..2503449 100644
--- a/Documentation/install-quick.txt
+++ b/Documentation/install-quick.txt
@@ -172,7 +172,14 @@
user@host:~/demo-project$
----
-Then make a change to it and upload it as a reviewable change in Gerrit.
+Install the link:user-changeid.html[Change-Id commitmsg hook]
+
+----
+ scp -p -P 29418 user@localhost:hooks/commit-msg $(git rev-parse --git-dir)/hooks/
+----
+
+Then make a change to the repository and upload it as a reviewable change
+in Gerrit.
----
user@host:~/demo-project$ date > testfile.txt
diff --git a/Documentation/intro-user.txt b/Documentation/intro-user.txt
index 436408d..662e0b3 100644
--- a/Documentation/intro-user.txt
+++ b/Documentation/intro-user.txt
@@ -827,6 +827,12 @@
and download commands. Note that this option is only shown if the Flash plugin
is available and the JavaScript Clipboard API is unavailable.
+- [[work-in-progress-by-default]]`Set new changes work-in-progress`:
++
+Whether new changes are uploaded as work-in-progress per default. This
+preference just sets the default; the behavior can still be overridden using a
+link:user-upload.html#wip[push option].
+
[[my-menu]]
In addition it is possible to customize the menu entries of the `My`
menu. This can be used to make the navigation to frequently used
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 025b29d..edb642e 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1255,6 +1255,7 @@
"review_category_strategy": "ABBREV",
"mute_common_path_prefixes": true,
"publish_comments_on_push": true,
+ "work_in_progress_by_default": true,
"default_base_for_merges": "FIRST_PARENT",
"my": [
{
@@ -1361,6 +1362,7 @@
"review_category_strategy": "NAME",
"diff_view": "SIDE_BY_SIDE",
"publish_comments_on_push": true,
+ "work_in_progress_by_default": true,
"mute_common_path_prefixes": true,
"my": [
{
@@ -2654,6 +2656,9 @@
|`publish_comments_on_push` |not set if `false`|
Whether to link:user-upload.html#publish-comments[publish draft comments] on
push by default.
+|`work_in_progress_by_default` |not set if `false`|
+Whether to link:user-upload.html#wip[set work-in-progress] on
+push or on create changes online by default.
|============================================
[[preferences-input]]
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index fb0a0df..3b25f47 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -2277,7 +2277,9 @@
--
Marks a change as ignored. The change will not be shown in the incoming
-reviews dashboard, and email notifications will be suppressed.
+reviews dashboard, and email notifications will be suppressed. Ignoring
+a change does not cause the change's "updated" timestamp to be modified,
+and the owner is not notified.
.Request
----
@@ -6282,10 +6284,14 @@
Only set if the file was renamed or copied.
|`lines_inserted`|optional|
Number of inserted lines. +
-Not set for binary files or if no lines were inserted.
+Not set for binary files or if no lines were inserted. +
+An empty last line is not included in the count and hence this number can
+differ by one from details provided in <<#diff-info,DiffInfo>>.
|`lines_deleted` |optional|
Number of deleted lines. +
-Not set for binary files or if no lines were deleted.
+Not set for binary files or if no lines were deleted. +
+An empty last line is not included in the count and hence this number can
+differ by one from details provided in <<#diff-info,DiffInfo>>.
|`size_delta` ||
Number of bytes by which the file size increased/decreased.
|`size` ||
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 792cca8..4a5cd1d 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -2890,10 +2890,13 @@
|`reject_implicit_merges`|optional|
link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
implicit merges should be rejected on changes pushed to the project.
-|`private_by_default` ||
+|`private_by_default` ||
link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
all new changes are set as private by default.
-|`max_object_size_limit` ||
+|`work_in_progress_by_default`||
+link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
+all new changes are set as work-in-progress by default.
+|`max_object_size_limit` ||
The link:config-gerrit.html#receive.maxObjectSizeLimit[max object size
limit] of this project as a link:#max-object-size-limit-info[
MaxObjectSizeLimitInfo] entity.
diff --git a/Documentation/user-search-projects.txt b/Documentation/user-search-projects.txt
index ba20adb..11c1326 100644
--- a/Documentation/user-search-projects.txt
+++ b/Documentation/user-search-projects.txt
@@ -24,6 +24,11 @@
Matches projects whose description contains 'DESCRIPTION', using a
full-text search.
+[[state]]
+state:'STATE'::
++
+Matches project's state. Can be either 'active' or 'read-only'.
+
== Magical Operators
[[is-visible]]
diff --git a/Documentation/user-upload.txt b/Documentation/user-upload.txt
index ce62b93..baf388e 100644
--- a/Documentation/user-upload.txt
+++ b/Documentation/user-upload.txt
@@ -309,6 +309,11 @@
Only change owners, project owners and site administrators can specify
`work-in-progress` and `ready` options on push.
+The default for this option can be set as a
+link:intro-user.html#work-in-progress-by-default[user preference]. If the
+preference is set so the default behavior is to create `work-in-progress`
+changes, this can be overridden with the `ready` option.
+
[[message]]
==== Message
diff --git a/WORKSPACE b/WORKSPACE
index 70200d1..e490c63 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -14,19 +14,9 @@
http_archive(
name = "io_bazel_rules_closure",
- build_file_content = "\n".join([
- "exports_files([",
- " \"0001-Replace-native-http-git-_archive-with-Skylark-rules.patch\",",
- " \"0002-Bump-Dagger-to-2.14.1-to-support-Java-9.patch\",",
- "])",
- ]),
- patches = [
- "//:0001-Replace-native-http-git-_archive-with-Skylark-rules.patch",
- "//:0002-Bump-Dagger-to-2.14.1-to-support-Java-9.patch",
- ],
- sha256 = "a80acb69c63d5f6437b099c111480a4493bad4592015af2127a2f49fb7512d8d",
- strip_prefix = "rules_closure-0.7.0",
- url = "https://github.com/bazelbuild/rules_closure/archive/0.7.0.tar.gz",
+ sha256 = "4dd84dd2bdd6c9f56cb5a475d504ea31d199c34309e202e9379501d01c3067e5",
+ strip_prefix = "rules_closure-3103a773820b59b76345f94c231cb213e0d404e2",
+ url = "https://github.com/bazelbuild/rules_closure/archive/3103a773820b59b76345f94c231cb213e0d404e2.tar.gz",
)
# File is specific to Polymer and copied from the Closure Github -- should be
@@ -888,8 +878,8 @@
maven_jar(
name = "commons-io",
- artifact = "commons-io:commons-io:1.4",
- sha1 = "a8762d07e76cfde2395257a5da47ba7c1dbd3dce",
+ artifact = "commons-io:commons-io:2.2",
+ sha1 = "83b5b8a7ba1c08f9e8c8ff2373724e33d3c1e22a",
)
maven_jar(
@@ -956,6 +946,10 @@
load("//tools/bzl:js.bzl", "bower_archive", "npm_binary")
+# NPM binaries bundled along with their dependencies.
+#
+# For full instructions on adding new binaries to the build, see
+# http://gerrit-review.googlesource.com/Documentation/dev-bazel.html#npm-binary
npm_binary(
name = "bower",
)
diff --git a/gerrit-acceptance-tests/tests.bzl b/gerrit-acceptance-tests/tests.bzl
new file mode 100644
index 0000000..c1e34dd
--- /dev/null
+++ b/gerrit-acceptance-tests/tests.bzl
@@ -0,0 +1,21 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+def acceptance_tests(
+ group,
+ deps = [],
+ labels = [],
+ vm_args = ["-Xmx256m"],
+ **kwargs):
+ junit_tests(
+ name = group,
+ deps = deps + [
+ "//gerrit-acceptance-tests:lib",
+ ],
+ tags = labels + [
+ "acceptance",
+ "slow",
+ ],
+ size = "large",
+ jvm_flags = vm_args,
+ **kwargs
+ )
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java
index 1dcb284..fbdf52c 100644
--- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java
+++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/info/GeneralPreferences.java
@@ -151,6 +151,9 @@
public final native boolean
publishCommentsOnPush() /*-{ return this.publish_comments_on_push || false }-*/;
+ public final native boolean
+ workInProgressByDefault() /*-{ return this.work_in_progress_by_default || false }-*/;
+
public final native JsArray<TopMenuItem> my() /*-{ return this.my; }-*/;
public final native void changesPerPage(int n) /*-{ this.changes_per_page = n }-*/;
@@ -230,6 +233,9 @@
public final native void publishCommentsOnPush(
boolean p) /*-{ this.publish_comments_on_push = p }-*/;
+ public final native void workInProgressByDefault(
+ boolean p) /*-{ this.work_in_progress_by_default = p }-*/;
+
public final void setMyMenus(List<TopMenuItem> myMenus) {
initMy();
for (TopMenuItem n : myMenus) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
index 0b32cd5..3e21619 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
@@ -69,6 +69,8 @@
String publishCommentsOnPush();
+ String workInProgressByDefault();
+
String myMenu();
String myMenuInfo();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
index 4b01513..c32efed 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
@@ -39,6 +39,7 @@
muteCommonPathPrefixes = Mute Common Path Prefixes In File List
signedOffBy = Insert Signed-off-by Footer For Inline Edit Changes
publishCommentsOnPush = Publish Comments On Push
+workInProgressByDefault = Set all new changes work-in-progress by default
myMenu = My Menu
myMenuInfo = \
Menu items for the 'My' top level menu. \
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
index f349065..afb8718 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
@@ -56,6 +56,7 @@
private CheckBox muteCommonPathPrefixes;
private CheckBox signedOffBy;
private CheckBox publishCommentsOnPush;
+ private CheckBox workInProgressByDefault;
private ListBox maximumPageSize;
private ListBox dateFormat;
private ListBox timeFormat;
@@ -163,9 +164,10 @@
muteCommonPathPrefixes = new CheckBox(Util.C.muteCommonPathPrefixes());
signedOffBy = new CheckBox(Util.C.signedOffBy());
publishCommentsOnPush = new CheckBox(Util.C.publishCommentsOnPush());
+ workInProgressByDefault = new CheckBox(Util.C.workInProgressByDefault());
boolean flashClippy = !UserAgent.hasJavaScriptClipboard() && UserAgent.Flash.isInstalled();
- final Grid formGrid = new Grid(15 + (flashClippy ? 1 : 0), 2);
+ final Grid formGrid = new Grid(16 + (flashClippy ? 1 : 0), 2);
int row = 0;
@@ -229,6 +231,10 @@
formGrid.setWidget(row, fieldIdx, publishCommentsOnPush);
row++;
+ formGrid.setText(row, labelIdx, "");
+ formGrid.setWidget(row, fieldIdx, workInProgressByDefault);
+ row++;
+
if (flashClippy) {
formGrid.setText(row, labelIdx, "");
formGrid.setWidget(row, fieldIdx, useFlashClipboard);
@@ -264,6 +270,7 @@
e.listenTo(muteCommonPathPrefixes);
e.listenTo(signedOffBy);
e.listenTo(publishCommentsOnPush);
+ e.listenTo(workInProgressByDefault);
e.listenTo(diffView);
e.listenTo(reviewCategoryStrategy);
e.listenTo(emailStrategy);
@@ -303,6 +310,7 @@
muteCommonPathPrefixes.setEnabled(on);
signedOffBy.setEnabled(on);
publishCommentsOnPush.setEnabled(on);
+ workInProgressByDefault.setEnabled(on);
reviewCategoryStrategy.setEnabled(on);
diffView.setEnabled(on);
emailStrategy.setEnabled(on);
@@ -329,6 +337,7 @@
muteCommonPathPrefixes.setValue(p.muteCommonPathPrefixes());
signedOffBy.setValue(p.signedOffBy());
publishCommentsOnPush.setValue(p.publishCommentsOnPush());
+ workInProgressByDefault.setValue(p.workInProgressByDefault());
setListBox(
reviewCategoryStrategy,
GeneralPreferencesInfo.ReviewCategoryStrategy.NONE,
@@ -421,6 +430,7 @@
p.muteCommonPathPrefixes(muteCommonPathPrefixes.getValue());
p.signedOffBy(signedOffBy.getValue());
p.publishCommentsOnPush(publishCommentsOnPush.getValue());
+ p.workInProgressByDefault(workInProgressByDefault.getValue());
p.reviewCategoryStrategy(
getListBox(
reviewCategoryStrategy, ReviewCategoryStrategy.NONE, ReviewCategoryStrategy.values()));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
index c0947a8..9def3b3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
@@ -79,6 +79,8 @@
String privateByDefault();
+ String workInProgressByDefault();
+
String enableReviewerByEmail();
String matchAuthorToCommitterDate();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index 8d6878f..1d1bb6d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -31,6 +31,7 @@
requireChangeID = Require <code>Change-Id</code> in commit message
rejectImplicitMerges = Reject implicit merges when changes are pushed for review
privateByDefault = Set all new changes private by default
+workInProgressByDefault = Set all new changes work-in-progress by default
headingMaxObjectSizeLimit = Maximum Git object size limit
headingGroupOptions = Group Options
isVisibleToAll = Make group visible to all registered users.
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index 64e147d..751e951 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -88,6 +88,7 @@
private ListBox requireSignedPush;
private ListBox rejectImplicitMerges;
private ListBox privateByDefault;
+ private ListBox workInProgressByDefault;
private ListBox enableReviewerByEmail;
private ListBox matchAuthorToCommitterDate;
private NpTextBox maxObjectSizeLimit;
@@ -198,6 +199,7 @@
requireChangeID.setEnabled(isOwner);
rejectImplicitMerges.setEnabled(isOwner);
privateByDefault.setEnabled(isOwner);
+ workInProgressByDefault.setEnabled(isOwner);
maxObjectSizeLimit.setEnabled(isOwner);
enableReviewerByEmail.setEnabled(isOwner);
matchAuthorToCommitterDate.setEnabled(isOwner);
@@ -278,6 +280,10 @@
saveEnabler.listenTo(privateByDefault);
grid.addHtml(AdminConstants.I.privateByDefault(), privateByDefault);
+ workInProgressByDefault = newInheritedBooleanBox();
+ saveEnabler.listenTo(workInProgressByDefault);
+ grid.addHtml(AdminConstants.I.workInProgressByDefault(), workInProgressByDefault);
+
enableReviewerByEmail = newInheritedBooleanBox();
saveEnabler.listenTo(enableReviewerByEmail);
grid.addHtml(AdminConstants.I.enableReviewerByEmail(), enableReviewerByEmail);
@@ -427,6 +433,7 @@
}
setBool(rejectImplicitMerges, result.rejectImplicitMerges());
setBool(privateByDefault, result.privateByDefault());
+ setBool(workInProgressByDefault, result.workInProgressByDefault());
setBool(enableReviewerByEmail, result.enableReviewerByEmail());
setBool(matchAuthorToCommitterDate, result.matchAuthorToCommitterDate());
setSubmitType(result.defaultSubmitType());
@@ -700,6 +707,7 @@
rsp,
getBool(rejectImplicitMerges),
getBool(privateByDefault),
+ getBool(workInProgressByDefault),
getBool(enableReviewerByEmail),
getBool(matchAuthorToCommitterDate),
maxObjectSizeLimit.getText().trim(),
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java
index cf40762..d942c2e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffInfo.java
@@ -137,7 +137,10 @@
private static void append(StringBuilder s, JsArrayString lines) {
for (int i = 0; i < lines.length(); i++) {
- s.append(lines.get(i)).append('\n');
+ if (s.length() > 0) {
+ s.append('\n');
+ }
+ s.append(lines.get(i));
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
index f670ac7..4185ef3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
@@ -60,6 +60,9 @@
public final native InheritedBooleanInfo privateByDefault()
/*-{ return this.private_by_default; }-*/ ;
+ public final native InheritedBooleanInfo workInProgressByDefault()
+ /*-{ return this.work_in_progress_by_default; }-*/ ;
+
public final native InheritedBooleanInfo enableReviewerByEmail()
/*-{ return this.enable_reviewer_by_email; }-*/ ;
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 66afdb2..3be52e6 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
@@ -153,6 +153,7 @@
InheritableBoolean requireSignedPush,
InheritableBoolean rejectImplicitMerges,
InheritableBoolean privateByDefault,
+ InheritableBoolean workInProgressByDefault,
InheritableBoolean enableReviewerByEmail,
InheritableBoolean matchAuthorToCommitterDate,
String maxObjectSizeLimit,
@@ -175,6 +176,7 @@
}
in.setRejectImplicitMerges(rejectImplicitMerges);
in.setPrivateByDefault(privateByDefault);
+ in.setWorkInProgressByDefault(workInProgressByDefault);
in.setMaxObjectSizeLimit(maxObjectSizeLimit);
if (submitType != null) {
in.setSubmitType(submitType);
@@ -313,6 +315,13 @@
private native void setPrivateByDefault(String v) /*-{ if(v)this.private_by_default=v; }-*/;
+ final void setWorkInProgressByDefault(InheritableBoolean v) {
+ setWorkInProgressByDefault(v.name());
+ }
+
+ private native void setWorkInProgressByDefault(
+ String v) /*-{ if(v)this.work_in_progress_by_default=v; }-*/;
+
final void setEnableReviewerByEmail(InheritableBoolean v) {
setEnableReviewerByEmailRaw(v.name());
}
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index abb28ce..960b558 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -68,6 +68,10 @@
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.index.project.ProjectIndex;
+import com.google.gerrit.index.project.ProjectIndexCollection;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
@@ -108,8 +112,6 @@
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.index.group.GroupIndexer;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.send.EmailHeader;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.MutableNotesMigration;
@@ -274,6 +276,7 @@
@Inject private ChangeIndexCollection changeIndexes;
@Inject private AccountIndexCollection accountIndexes;
+ @Inject private ProjectIndexCollection projectIndexes;
@Inject private EventRecorder.Factory eventRecorderFactory;
@Inject private InProcessProtocol inProcessProtocol;
@Inject private Provider<AnonymousUser> anonymousUser;
@@ -900,6 +903,41 @@
};
}
+ protected AutoCloseable disableProjectIndex() {
+ disableProjectIndexWrites();
+ ProjectIndex searchIndex = projectIndexes.getSearchIndex();
+ if (!(searchIndex instanceof DisabledProjectIndex)) {
+ projectIndexes.setSearchIndex(new DisabledProjectIndex(searchIndex), false);
+ }
+
+ return new AutoCloseable() {
+ @Override
+ public void close() {
+ enableProjectIndexWrites();
+ ProjectIndex searchIndex = projectIndexes.getSearchIndex();
+ if (searchIndex instanceof DisabledProjectIndex) {
+ projectIndexes.setSearchIndex(((DisabledProjectIndex) searchIndex).unwrap(), false);
+ }
+ }
+ };
+ }
+
+ protected void disableProjectIndexWrites() {
+ for (ProjectIndex i : projectIndexes.getWriteIndexes()) {
+ if (!(i instanceof DisabledProjectIndex)) {
+ projectIndexes.addWriteIndex(new DisabledProjectIndex(i));
+ }
+ }
+ }
+
+ protected void enableProjectIndexWrites() {
+ for (ProjectIndex i : projectIndexes.getWriteIndexes()) {
+ if (i instanceof DisabledProjectIndex) {
+ projectIndexes.addWriteIndex(((DisabledProjectIndex) i).unwrap());
+ }
+ }
+ }
+
protected static Gson newGson() {
return OutputFormat.JSON_COMPACT.newGson();
}
@@ -1307,8 +1345,7 @@
protected void assertDiffForNewFile(
DiffInfo diff, RevCommit commit, String path, String expectedContentSideB) throws Exception {
- List<String> expectedLines = new ArrayList<>();
- Collections.addAll(expectedLines, expectedContentSideB.split("\n"));
+ List<String> expectedLines = ImmutableList.copyOf(expectedContentSideB.split("\n", -1));
assertThat(diff.binary).isNull();
assertThat(diff.changeType).isEqualTo(ChangeType.ADDED);
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index 2336f2f..f2d0f70 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -34,10 +34,10 @@
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ReviewerState;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
+import com.google.gerrit.mail.EmailHeader.AddressList;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.send.EmailHeader;
-import com.google.gerrit.server.mail.send.EmailHeader.AddressList;
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.FakeEmailSender.Message;
import java.io.IOException;
diff --git a/java/com/google/gerrit/acceptance/BUILD b/java/com/google/gerrit/acceptance/BUILD
index 25e1d7c..0214cea 100644
--- a/java/com/google/gerrit/acceptance/BUILD
+++ b/java/com/google/gerrit/acceptance/BUILD
@@ -19,6 +19,7 @@
"//java/com/google/gerrit/index",
"//java/com/google/gerrit/launcher",
"//java/com/google/gerrit/lucene",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/pgm",
"//java/com/google/gerrit/pgm/init",
@@ -98,7 +99,9 @@
"//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/httpd",
"//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lucene",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/pgm/init",
"//java/com/google/gerrit/reviewdb:server",
diff --git a/java/com/google/gerrit/acceptance/DisabledProjectIndex.java b/java/com/google/gerrit/acceptance/DisabledProjectIndex.java
new file mode 100644
index 0000000..2524a76
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/DisabledProjectIndex.java
@@ -0,0 +1,76 @@
+// Copyright (C) 2018 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.acceptance;
+
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.Schema;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.project.ProjectIndex;
+import com.google.gerrit.index.query.DataSource;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.reviewdb.client.Project;
+
+/**
+ * This class wraps an index and assumes the search index can't handle any queries. However, it does
+ * return the current schema as the assumption is that we need a search index for starting Gerrit in
+ * the first place and only later lose the index connection (making it so that we can't send
+ * requests there anymore).
+ */
+public class DisabledProjectIndex implements ProjectIndex {
+ private final ProjectIndex index;
+
+ public DisabledProjectIndex(ProjectIndex index) {
+ this.index = index;
+ }
+
+ public ProjectIndex unwrap() {
+ return index;
+ }
+
+ @Override
+ public Schema<ProjectData> getSchema() {
+ return index.getSchema();
+ }
+
+ @Override
+ public void close() {
+ index.close();
+ }
+
+ @Override
+ public void replace(ProjectData obj) {
+ throw new UnsupportedOperationException("ProjectIndex is disabled");
+ }
+
+ @Override
+ public void delete(Project.NameKey key) {
+ throw new UnsupportedOperationException("ProjectIndex is disabled");
+ }
+
+ @Override
+ public void deleteAll() {
+ throw new UnsupportedOperationException("ProjectIndex is disabled");
+ }
+
+ @Override
+ public DataSource<ProjectData> getSource(Predicate<ProjectData> p, QueryOptions opts) {
+ throw new UnsupportedOperationException("ProjectIndex is disabled");
+ }
+
+ @Override
+ public void markReady(boolean ready) {
+ throw new UnsupportedOperationException("ProjectIndex is disabled");
+ }
+}
diff --git a/java/com/google/gerrit/acceptance/ProjectResetter.java b/java/com/google/gerrit/acceptance/ProjectResetter.java
index f4a8da3..1fed8f8 100644
--- a/java/com/google/gerrit/acceptance/ProjectResetter.java
+++ b/java/com/google/gerrit/acceptance/ProjectResetter.java
@@ -23,6 +23,7 @@
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
@@ -32,7 +33,6 @@
import com.google.gerrit.server.account.GroupIncludeCache;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.index.RefState;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.project.ProjectCache;
diff --git a/java/com/google/gerrit/acceptance/TestAccount.java b/java/com/google/gerrit/acceptance/TestAccount.java
index 094e8b0..5ce44ff 100644
--- a/java/com/google/gerrit/acceptance/TestAccount.java
+++ b/java/com/google/gerrit/acceptance/TestAccount.java
@@ -17,8 +17,8 @@
import static java.util.stream.Collectors.toList;
import com.google.common.net.InetAddresses;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.server.mail.Address;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.List;
diff --git a/java/com/google/gerrit/common/data/GroupReference.java b/java/com/google/gerrit/common/data/GroupReference.java
index dc22d62..cfaad17 100644
--- a/java/com/google/gerrit/common/data/GroupReference.java
+++ b/java/com/google/gerrit/common/data/GroupReference.java
@@ -22,11 +22,6 @@
private static final String PREFIX = "group ";
- /** @return a new reference to the given group description. */
- public static GroupReference forGroup(AccountGroup group) {
- return new GroupReference(group.getGroupUUID(), group.getName());
- }
-
public static GroupReference forGroup(GroupDescription.Basic group) {
return new GroupReference(group.getGroupUUID(), group.getName());
}
@@ -66,6 +61,9 @@
}
public void setName(String newName) {
+ if (newName == null) {
+ throw new NullPointerException();
+ }
this.name = newName;
}
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index 3755faa..f322c3d 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -21,6 +21,7 @@
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
@@ -79,6 +80,7 @@
protected static final String MAPPINGS = "mappings";
protected static final String ORDER = "order";
protected static final String SEARCH = "_search";
+ protected static final String SETTINGS = "settings";
protected static <T> List<T> decodeProtos(
JsonObject doc, String fieldName, ProtobufCodec<T> codec) {
@@ -181,7 +183,8 @@
}
// Recreate the index.
- response = performRequest("PUT", getMappings(), indexName, Collections.emptyMap());
+ String indexCreationFields = concatJsonString(getSettings(), getMappings());
+ response = performRequest("PUT", indexCreationFields, indexName, Collections.emptyMap());
statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
String error = String.format("Failed to create index %s: %s", indexName, statusCode);
@@ -193,6 +196,10 @@
protected abstract String getMappings();
+ private String getSettings() {
+ return gson.toJson(ImmutableMap.of(SETTINGS, ElasticSetting.createSetting()));
+ }
+
protected abstract String getId(V v);
protected String getMappingsForSingleType(String candidateType, MappingProperties properties) {
@@ -294,6 +301,10 @@
return performRequest("POST", payload, uri, params);
}
+ private String concatJsonString(String target, String addition) {
+ return target.substring(0, target.length() - 1) + "," + addition.substring(1);
+ }
+
private Response performRequest(
String method, Object payload, String uri, Map<String, String> params) throws IOException {
String payloadStr = payload instanceof String ? (String) payload : payload.toString();
diff --git a/java/com/google/gerrit/elasticsearch/ElasticMapping.java b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
index a30e546..f8c4168 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticMapping.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticMapping.java
@@ -34,9 +34,9 @@
|| fieldType == FieldType.INTEGER_RANGE
|| fieldType == FieldType.LONG) {
mapping.addNumber(name);
- } else if (fieldType == FieldType.PREFIX
- || fieldType == FieldType.FULL_TEXT
- || fieldType == FieldType.STORED_ONLY) {
+ } else if (fieldType == FieldType.FULL_TEXT) {
+ mapping.addStringWithAnalyzer(name);
+ } else if (fieldType == FieldType.PREFIX || fieldType == FieldType.STORED_ONLY) {
mapping.addString(name);
} else {
throw new IllegalStateException("Unsupported field type: " + fieldType.getName());
@@ -88,6 +88,13 @@
return this;
}
+ Builder addStringWithAnalyzer(String name) {
+ FieldProperties key = new FieldProperties(adapter.stringFieldType());
+ key.analyzer = "custom_with_char_filter";
+ fields.put(name, key);
+ return this;
+ }
+
Builder add(String name, String type) {
fields.put(name, new FieldProperties(type));
return this;
@@ -102,6 +109,7 @@
String type;
String index;
String format;
+ String analyzer;
Map<String, FieldProperties> fields;
FieldProperties(String type) {
diff --git a/java/com/google/gerrit/elasticsearch/ElasticSetting.java b/java/com/google/gerrit/elasticsearch/ElasticSetting.java
new file mode 100644
index 0000000..6fd234d
--- /dev/null
+++ b/java/com/google/gerrit/elasticsearch/ElasticSetting.java
@@ -0,0 +1,92 @@
+// Copyright (C) 2018 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.elasticsearch;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+class ElasticSetting {
+ /** The custom char mappings of "." to " " and "_" to " " in the form of UTF-8 */
+ private static final ImmutableMap<String, String> CUSTOM_CHAR_MAPPING =
+ ImmutableMap.of("\\u002E", "\\u0020", "\\u005F", "\\u0020");
+
+ static SettingProperties createSetting() {
+ ElasticSetting.Builder settings = new ElasticSetting.Builder();
+ settings.addCharFilter();
+ settings.addAnalyzer();
+ return settings.build();
+ }
+
+ static class Builder {
+ private final ImmutableMap.Builder<String, FieldProperties> fields =
+ new ImmutableMap.Builder<>();
+
+ SettingProperties build() {
+ SettingProperties properties = new SettingProperties();
+ properties.analysis = fields.build();
+ return properties;
+ }
+
+ void addCharFilter() {
+ FieldProperties charMapping = new FieldProperties("mapping");
+ charMapping.mappings = getCustomCharMappings(CUSTOM_CHAR_MAPPING);
+
+ FieldProperties charFilter = new FieldProperties();
+ charFilter.customMapping = charMapping;
+ fields.put("char_filter", charFilter);
+ }
+
+ void addAnalyzer() {
+ FieldProperties customAnalyzer = new FieldProperties("custom");
+ customAnalyzer.tokenizer = "standard";
+ customAnalyzer.charFilter = new String[] {"custom_mapping"};
+ customAnalyzer.filter = new String[] {"lowercase"};
+
+ FieldProperties analyzer = new FieldProperties();
+ analyzer.customWithCharFilter = customAnalyzer;
+ fields.put("analyzer", analyzer);
+ }
+
+ private static String[] getCustomCharMappings(ImmutableMap<String, String> map) {
+ int mappingIndex = 0;
+ int numOfMappings = map.size();
+ String[] mapping = new String[numOfMappings];
+ for (Map.Entry<String, String> e : map.entrySet()) {
+ mapping[mappingIndex++] = e.getKey() + "=>" + e.getValue();
+ }
+ return mapping;
+ }
+ }
+
+ static class SettingProperties {
+ Map<String, FieldProperties> analysis;
+ }
+
+ static class FieldProperties {
+ String tokenizer;
+ String type;
+ String[] charFilter;
+ String[] filter;
+ String[] mappings;
+ FieldProperties customMapping;
+ FieldProperties customWithCharFilter;
+
+ FieldProperties() {}
+
+ FieldProperties(String type) {
+ this.type = type;
+ }
+ }
+}
diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
index 80115aa..b3dd1f1 100644
--- a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
+++ b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
@@ -33,6 +33,7 @@
public InheritedBooleanInfo requireSignedPush;
public InheritedBooleanInfo rejectImplicitMerges;
public InheritedBooleanInfo privateByDefault;
+ public InheritedBooleanInfo workInProgressByDefault;
public InheritedBooleanInfo enableReviewerByEmail;
public InheritedBooleanInfo matchAuthorToCommitterDate;
public InheritedBooleanInfo rejectEmptyCommit;
diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInput.java b/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
index 37a2e8b..1a6d77b 100644
--- a/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
+++ b/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
@@ -30,6 +30,7 @@
public InheritableBoolean requireSignedPush;
public InheritableBoolean rejectImplicitMerges;
public InheritableBoolean privateByDefault;
+ public InheritableBoolean workInProgressByDefault;
public InheritableBoolean enableReviewerByEmail;
public InheritableBoolean matchAuthorToCommitterDate;
public InheritableBoolean rejectEmptyCommit;
diff --git a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
index 9dcba5e..1f16d8d 100644
--- a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
+++ b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
@@ -158,6 +158,7 @@
public EmailFormat emailFormat;
public DefaultBase defaultBaseForMerges;
public Boolean publishCommentsOnPush;
+ public Boolean workInProgressByDefault;
public boolean isShowInfoInReviewCategory() {
return getReviewCategoryStrategy() != ReviewCategoryStrategy.NONE;
@@ -227,6 +228,7 @@
p.signedOffBy = false;
p.defaultBaseForMerges = DefaultBase.FIRST_PARENT;
p.publishCommentsOnPush = false;
+ p.workInProgressByDefault = false;
return p;
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
index 6918325..057a1a2 100644
--- a/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
@@ -47,4 +47,16 @@
DiffInfo diffInfo = actual();
return Truth.assertThat(diffInfo.changeType).named("changeType");
}
+
+ public FileMetaSubject metaA() {
+ isNotNull();
+ DiffInfo diffInfo = actual();
+ return FileMetaSubject.assertThat(diffInfo.metaA).named("metaA");
+ }
+
+ public FileMetaSubject metaB() {
+ isNotNull();
+ DiffInfo diffInfo = actual();
+ return FileMetaSubject.assertThat(diffInfo.metaB).named("metaB");
+ }
}
diff --git a/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java b/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java
new file mode 100644
index 0000000..e77eef1
--- /dev/null
+++ b/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java
@@ -0,0 +1,40 @@
+// Copyright (C) 2018 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.extensions.common.testing;
+
+import static com.google.common.truth.Truth.assertAbout;
+
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.IntegerSubject;
+import com.google.common.truth.Subject;
+import com.google.common.truth.Truth;
+import com.google.gerrit.extensions.common.DiffInfo.FileMeta;
+
+public class FileMetaSubject extends Subject<FileMetaSubject, FileMeta> {
+
+ public static FileMetaSubject assertThat(FileMeta fileMeta) {
+ return assertAbout(FileMetaSubject::new).that(fileMeta);
+ }
+
+ private FileMetaSubject(FailureMetadata failureMetadata, FileMeta fileMeta) {
+ super(failureMetadata, fileMeta);
+ }
+
+ public IntegerSubject totalLineCount() {
+ isNotNull();
+ FileMeta fileMeta = actual();
+ return Truth.assertThat(fileMeta.lines).named("total line count");
+ }
+}
diff --git a/java/com/google/gerrit/httpd/BUILD b/java/com/google/gerrit/httpd/BUILD
index bbb5b66..3e71098 100644
--- a/java/com/google/gerrit/httpd/BUILD
+++ b/java/com/google/gerrit/httpd/BUILD
@@ -13,6 +13,7 @@
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/audit",
"//java/com/google/gerrit/server/git/receive",
"//java/com/google/gerrit/server/ioutil",
"//java/com/google/gerrit/server/restapi",
diff --git a/java/com/google/gerrit/httpd/auth/oauth/BUILD b/java/com/google/gerrit/httpd/auth/oauth/BUILD
index 96726ad..7315ce1 100644
--- a/java/com/google/gerrit/httpd/auth/oauth/BUILD
+++ b/java/com/google/gerrit/httpd/auth/oauth/BUILD
@@ -10,6 +10,7 @@
"//java/com/google/gerrit/httpd",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/audit",
"//lib:gson",
"//lib:guava",
"//lib:gwtorm",
diff --git a/java/com/google/gerrit/httpd/auth/openid/BUILD b/java/com/google/gerrit/httpd/auth/openid/BUILD
index bfb2551..f80e9d5 100644
--- a/java/com/google/gerrit/httpd/auth/openid/BUILD
+++ b/java/com/google/gerrit/httpd/auth/openid/BUILD
@@ -13,6 +13,7 @@
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/util/http",
"//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/audit",
"//lib:guava",
"//lib:gwtorm",
"//lib:servlet-api-3_1",
diff --git a/java/com/google/gerrit/httpd/init/BUILD b/java/com/google/gerrit/httpd/init/BUILD
index 292ceff..d557c0e 100644
--- a/java/com/google/gerrit/httpd/init/BUILD
+++ b/java/com/google/gerrit/httpd/init/BUILD
@@ -18,6 +18,7 @@
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server:module",
"//java/com/google/gerrit/server/api",
+ "//java/com/google/gerrit/server/audit",
"//java/com/google/gerrit/server/cache/h2",
"//java/com/google/gerrit/server/cache/mem",
"//java/com/google/gerrit/server/git/receive",
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 9ce7690..8e380f5 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -47,6 +47,7 @@
import com.google.gerrit.server.account.AccountDeactivator;
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.api.GerritApiModule;
+import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
import com.google.gerrit.server.change.ChangeCleanupRunner;
@@ -342,6 +343,7 @@
modules.add(new SmtpEmailSender.Module());
modules.add(new SignedTokenEmailTokenVerifier.Module());
modules.add(new LocalMergeSuperSetComputation.Module());
+ modules.add(new AuditModule());
// Plugin module needs to be inserted *before* the index module.
// There is the concept of LifecycleModule, in Gerrit's own extension
diff --git a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java b/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
index 0ae9c4c..0bcd8f8 100644
--- a/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
+++ b/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
@@ -127,8 +127,12 @@
replace(config, toDelete, section);
} else if (AccessSection.isValid(name)) {
- if (checkIfOwner && !forProject.ref(name).test(RefPermission.WRITE_CONFIG)) {
- continue;
+ if (checkIfOwner) {
+ try {
+ forProject.ref(name).check(RefPermission.WRITE_CONFIG);
+ } catch (AuthException e) {
+ continue;
+ }
}
RefPattern.validate(name);
@@ -143,8 +147,15 @@
config.remove(config.getAccessSection(name));
}
- } else if (!checkIfOwner || forProject.ref(name).test(RefPermission.WRITE_CONFIG)) {
+ } else if (!checkIfOwner) {
config.remove(config.getAccessSection(name));
+ } else {
+ try {
+ forProject.ref(name).check(RefPermission.WRITE_CONFIG);
+ config.remove(config.getAccessSection(name));
+ } catch (AuthException e) {
+ // Do nothing.
+ }
}
}
diff --git a/java/com/google/gerrit/index/BUILD b/java/com/google/gerrit/index/BUILD
index 2442b593..6604ca1 100644
--- a/java/com/google/gerrit/index/BUILD
+++ b/java/com/google/gerrit/index/BUILD
@@ -37,6 +37,7 @@
"//java/com/google/gerrit/common:annotations",
"//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/metrics",
+ "//java/com/google/gerrit/reviewdb:server",
"//lib:guava",
"//lib:gwtjsonrpc",
"//lib:gwtorm",
diff --git a/java/com/google/gerrit/server/index/RefState.java b/java/com/google/gerrit/index/RefState.java
similarity index 98%
rename from java/com/google/gerrit/server/index/RefState.java
rename to java/com/google/gerrit/index/RefState.java
index 6b893f0..f0e465d 100644
--- a/java/com/google/gerrit/server/index/RefState.java
+++ b/java/com/google/gerrit/index/RefState.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.index;
+package com.google.gerrit.index;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
diff --git a/java/com/google/gerrit/index/project/ProjectData.java b/java/com/google/gerrit/index/project/ProjectData.java
index 9d6b571..7365660 100644
--- a/java/com/google/gerrit/index/project/ProjectData.java
+++ b/java/com/google/gerrit/index/project/ProjectData.java
@@ -14,23 +14,43 @@
package com.google.gerrit.index.project;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
import com.google.common.collect.ImmutableList;
import com.google.gerrit.reviewdb.client.Project;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
public class ProjectData {
private final Project project;
- private final ImmutableList<Project.NameKey> ancestors;
+ private final Optional<ProjectData> parent;
- public ProjectData(Project project, Iterable<Project.NameKey> ancestors) {
+ public ProjectData(Project project, Optional<ProjectData> parent) {
this.project = project;
- this.ancestors = ImmutableList.copyOf(ancestors);
+ this.parent = parent;
}
public Project getProject() {
return project;
}
- public ImmutableList<Project.NameKey> getAncestors() {
- return ancestors;
+ public Optional<ProjectData> getParent() {
+ return parent;
+ }
+
+ /** Returns all {@link ProjectData} in the hierarchy starting with the current one. */
+ public ImmutableList<ProjectData> tree() {
+ List<ProjectData> parents = new ArrayList<>();
+ Optional<ProjectData> curr = Optional.of(this);
+ while (curr.isPresent()) {
+ parents.add(curr.get());
+ curr = curr.get().parent;
+ }
+ return ImmutableList.copyOf(parents);
+ }
+
+ public ImmutableList<String> getParentNames() {
+ return tree().stream().skip(1).map(p -> p.getProject().getName()).collect(toImmutableList());
}
}
diff --git a/java/com/google/gerrit/index/project/ProjectField.java b/java/com/google/gerrit/index/project/ProjectField.java
index 1c2f629b..5e484b2 100644
--- a/java/com/google/gerrit/index/project/ProjectField.java
+++ b/java/com/google/gerrit/index/project/ProjectField.java
@@ -14,23 +14,30 @@
package com.google.gerrit.index.project;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.index.FieldDef.exact;
import static com.google.gerrit.index.FieldDef.fullText;
import static com.google.gerrit.index.FieldDef.prefix;
+import static com.google.gerrit.index.FieldDef.storedOnly;
-import com.google.common.collect.Iterables;
import com.google.gerrit.index.FieldDef;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
/** Index schema for projects. */
public class ProjectField {
+ private static byte[] toRefState(Project project) {
+ return RefState.create(RefNames.REFS_CONFIG, project.getConfigRefState())
+ .toByteArray(project.getNameKey());
+ }
public static final FieldDef<ProjectData, String> NAME =
exact("name").stored().build(p -> p.getProject().getName());
public static final FieldDef<ProjectData, String> DESCRIPTION =
- fullText("description").build(p -> p.getProject().getDescription());
+ fullText("description").stored().build(p -> p.getProject().getDescription());
public static final FieldDef<ProjectData, String> PARENT_NAME =
exact("parent_name").build(p -> p.getProject().getParentName());
@@ -38,7 +45,26 @@
public static final FieldDef<ProjectData, Iterable<String>> NAME_PART =
prefix("name_part").buildRepeatable(p -> SchemaUtil.getNameParts(p.getProject().getName()));
+ public static final FieldDef<ProjectData, String> STATE =
+ exact("state").stored().build(p -> p.getProject().getState().name());
+
public static final FieldDef<ProjectData, Iterable<String>> ANCESTOR_NAME =
- exact("ancestor_name")
- .buildRepeatable(p -> Iterables.transform(p.getAncestors(), Project.NameKey::get));
+ exact("ancestor_name").buildRepeatable(p -> p.getParentNames());
+
+ /**
+ * All values of all refs that were used in the course of indexing this document. This covers
+ * {@code refs/meta/config} of the current project and all of its parents.
+ *
+ * <p>Emitted as UTF-8 encoded strings of the form {@code project:ref/name:[hex sha]}.
+ */
+ public static final FieldDef<ProjectData, Iterable<byte[]>> REF_STATE =
+ storedOnly("ref_state")
+ .buildRepeatable(
+ projectData ->
+ projectData
+ .tree()
+ .stream()
+ .filter(p -> p.getProject().getConfigRefState() != null)
+ .map(p -> toRefState(p.getProject()))
+ .collect(toImmutableList()));
}
diff --git a/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java b/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
index cbea4fe..07b5adb 100644
--- a/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
+++ b/java/com/google/gerrit/index/project/ProjectSchemaDefinitions.java
@@ -21,6 +21,7 @@
public class ProjectSchemaDefinitions extends SchemaDefinitions<ProjectData> {
+ @Deprecated
static final Schema<ProjectData> V1 =
schema(
ProjectField.NAME,
@@ -29,6 +30,8 @@
ProjectField.NAME_PART,
ProjectField.ANCESTOR_NAME);
+ static final Schema<ProjectData> V2 = schema(V1, ProjectField.STATE, ProjectField.REF_STATE);
+
public static final ProjectSchemaDefinitions INSTANCE = new ProjectSchemaDefinitions();
private ProjectSchemaDefinitions() {
diff --git a/java/com/google/gerrit/server/mail/Address.java b/java/com/google/gerrit/mail/Address.java
similarity index 95%
rename from java/com/google/gerrit/server/mail/Address.java
rename to java/com/google/gerrit/mail/Address.java
index e91f3f3..24ab353 100644
--- a/java/com/google/gerrit/server/mail/Address.java
+++ b/java/com/google/gerrit/mail/Address.java
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail;
+package com.google.gerrit.mail;
-import com.google.gerrit.server.mail.send.EmailHeader;
+import com.google.gerrit.common.Nullable;
public class Address {
public static Address parse(String in) {
@@ -50,8 +50,8 @@
}
}
- final String name;
- final String email;
+ @Nullable private final String name;
+ private final String email;
public Address(String email) {
this(null, email);
@@ -62,6 +62,7 @@
this.email = email;
}
+ @Nullable
public String getName() {
return name;
}
diff --git a/java/com/google/gerrit/mail/BUILD b/java/com/google/gerrit/mail/BUILD
new file mode 100644
index 0000000..90bb82c
--- /dev/null
+++ b/java/com/google/gerrit/mail/BUILD
@@ -0,0 +1,18 @@
+java_library(
+ name = "mail",
+ srcs = glob(["*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/common:annotations",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//lib:guava",
+ "//lib/auto:auto-value",
+ "//lib/auto:auto-value-annotations",
+ "//lib/flogger:api",
+ "//lib/jsoup",
+ "//lib/log:jsonevent-layout",
+ "//lib/log:log4j",
+ "//lib/mime4j:core",
+ "//lib/mime4j:dom",
+ ],
+)
diff --git a/java/com/google/gerrit/server/mail/send/EmailHeader.java b/java/com/google/gerrit/mail/EmailHeader.java
similarity index 97%
rename from java/com/google/gerrit/server/mail/send/EmailHeader.java
rename to java/com/google/gerrit/mail/EmailHeader.java
index 29354f2..69d5fcd 100644
--- a/java/com/google/gerrit/server/mail/send/EmailHeader.java
+++ b/java/com/google/gerrit/mail/EmailHeader.java
@@ -12,12 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.send;
+package com.google.gerrit.mail;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.MoreObjects;
-import com.google.gerrit.server.mail.Address;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
@@ -183,7 +182,7 @@
list.add(addr);
}
- void remove(java.lang.String email) {
+ public void remove(java.lang.String email) {
list.removeIf(address -> address.getEmail().equals(email));
}
diff --git a/java/com/google/gerrit/server/mail/receive/HtmlParser.java b/java/com/google/gerrit/mail/HtmlParser.java
similarity index 98%
rename from java/com/google/gerrit/server/mail/receive/HtmlParser.java
rename to java/com/google/gerrit/mail/HtmlParser.java
index d68f076..9821599 100644
--- a/java/com/google/gerrit/server/mail/receive/HtmlParser.java
+++ b/java/com/google/gerrit/mail/HtmlParser.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
diff --git a/java/com/google/gerrit/server/mail/receive/MailComment.java b/java/com/google/gerrit/mail/MailComment.java
similarity index 84%
rename from java/com/google/gerrit/server/mail/receive/MailComment.java
rename to java/com/google/gerrit/mail/MailComment.java
index 8571e12..fd8198c 100644
--- a/java/com/google/gerrit/server/mail/receive/MailComment.java
+++ b/java/com/google/gerrit/mail/MailComment.java
@@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.gerrit.reviewdb.client.Comment;
import java.util.Objects;
/** A comment parsed from inbound email */
public class MailComment {
- enum CommentType {
+ public enum CommentType {
CHANGE_MESSAGE,
FILE_COMMENT,
INLINE_COMMENT
@@ -42,6 +42,22 @@
this.isLink = isLink;
}
+ public CommentType getType() {
+ return type;
+ }
+
+ public Comment getInReplyTo() {
+ return inReplyTo;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
/**
* Checks if the provided comment concerns the same exact spot in the change. This is basically an
* equals method except that the message is not checked.
diff --git a/java/com/google/gerrit/server/mail/MailHeader.java b/java/com/google/gerrit/mail/MailHeader.java
similarity index 97%
rename from java/com/google/gerrit/server/mail/MailHeader.java
rename to java/com/google/gerrit/mail/MailHeader.java
index cf145e5..2f31a9c 100644
--- a/java/com/google/gerrit/server/mail/MailHeader.java
+++ b/java/com/google/gerrit/mail/MailHeader.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail;
+package com.google.gerrit.mail;
/** Variables used by emails to hold data */
public enum MailHeader {
diff --git a/java/com/google/gerrit/server/mail/receive/MailHeaderParser.java b/java/com/google/gerrit/mail/MailHeaderParser.java
similarity index 92%
rename from java/com/google/gerrit/server/mail/receive/MailHeaderParser.java
rename to java/com/google/gerrit/mail/MailHeaderParser.java
index d176095..8eb4d97 100644
--- a/java/com/google/gerrit/server/mail/receive/MailHeaderParser.java
+++ b/java/com/google/gerrit/mail/MailHeaderParser.java
@@ -12,14 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
-import com.google.gerrit.server.mail.MailHeader;
-import com.google.gerrit.server.mail.MailUtil;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.format.DateTimeParseException;
@@ -44,7 +42,8 @@
} else if (header.startsWith(MailHeader.COMMENT_DATE.fieldWithDelimiter())) {
String ts = header.substring(MailHeader.COMMENT_DATE.fieldWithDelimiter().length()).trim();
try {
- metadata.timestamp = Timestamp.from(MailUtil.rfcDateformatter.parse(ts, Instant::from));
+ metadata.timestamp =
+ Timestamp.from(MailProcessingUtil.rfcDateformatter.parse(ts, Instant::from));
} catch (DateTimeParseException e) {
logger.atSevere().withCause(e).log(
"Mail: Error while parsing timestamp from header of message %s", m.id());
@@ -91,7 +90,8 @@
} else if (metadata.timestamp == null && line.contains(MailHeader.COMMENT_DATE.getName())) {
String ts = extractFooter(MailHeader.COMMENT_DATE.withDelimiter(), line);
try {
- metadata.timestamp = Timestamp.from(MailUtil.rfcDateformatter.parse(ts, Instant::from));
+ metadata.timestamp =
+ Timestamp.from(MailProcessingUtil.rfcDateformatter.parse(ts, Instant::from));
} catch (DateTimeParseException e) {
logger.atSevere().withCause(e).log(
"Mail: Error while parsing timestamp from footer of message %s", m.id());
diff --git a/java/com/google/gerrit/server/mail/receive/MailMessage.java b/java/com/google/gerrit/mail/MailMessage.java
similarity index 96%
rename from java/com/google/gerrit/server/mail/receive/MailMessage.java
rename to java/com/google/gerrit/mail/MailMessage.java
index 0d20464..bb83dfd 100644
--- a/java/com/google/gerrit/server/mail/receive/MailMessage.java
+++ b/java/com/google/gerrit/mail/MailMessage.java
@@ -12,12 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.server.mail.Address;
import java.time.Instant;
/**
diff --git a/java/com/google/gerrit/server/mail/receive/MailMetadata.java b/java/com/google/gerrit/mail/MailMetadata.java
similarity index 96%
rename from java/com/google/gerrit/server/mail/receive/MailMetadata.java
rename to java/com/google/gerrit/mail/MailMetadata.java
index 04c2add..a311461 100644
--- a/java/com/google/gerrit/server/mail/receive/MailMetadata.java
+++ b/java/com/google/gerrit/mail/MailMetadata.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.common.base.MoreObjects;
import java.sql.Timestamp;
diff --git a/java/com/google/gerrit/server/mail/receive/MailParsingException.java b/java/com/google/gerrit/mail/MailParsingException.java
similarity index 94%
rename from java/com/google/gerrit/server/mail/receive/MailParsingException.java
rename to java/com/google/gerrit/mail/MailParsingException.java
index b91bb18..7e85a27 100644
--- a/java/com/google/gerrit/server/mail/receive/MailParsingException.java
+++ b/java/com/google/gerrit/mail/MailParsingException.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
/** An {@link Exception} indicating that an email could not be parsed. */
public class MailParsingException extends Exception {
diff --git a/java/com/google/gerrit/mail/MailProcessingUtil.java b/java/com/google/gerrit/mail/MailProcessingUtil.java
new file mode 100644
index 0000000..b63189a
--- /dev/null
+++ b/java/com/google/gerrit/mail/MailProcessingUtil.java
@@ -0,0 +1,23 @@
+// Copyright (C) 2018 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.mail;
+
+import java.time.format.DateTimeFormatter;
+
+public class MailProcessingUtil {
+
+ public static DateTimeFormatter rfcDateformatter =
+ DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss ZZZ");
+}
diff --git a/java/com/google/gerrit/server/mail/receive/ParserUtil.java b/java/com/google/gerrit/mail/ParserUtil.java
similarity index 98%
rename from java/com/google/gerrit/server/mail/receive/ParserUtil.java
rename to java/com/google/gerrit/mail/ParserUtil.java
index e770a3e..6a27ac4 100644
--- a/java/com/google/gerrit/server/mail/receive/ParserUtil.java
+++ b/java/com/google/gerrit/mail/ParserUtil.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
diff --git a/java/com/google/gerrit/server/mail/receive/RawMailParser.java b/java/com/google/gerrit/mail/RawMailParser.java
similarity index 98%
rename from java/com/google/gerrit/server/mail/receive/RawMailParser.java
rename to java/com/google/gerrit/mail/RawMailParser.java
index 57fe21f..00754d3 100644
--- a/java/com/google/gerrit/server/mail/receive/RawMailParser.java
+++ b/java/com/google/gerrit/mail/RawMailParser.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -21,7 +21,6 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.io.CharStreams;
import com.google.common.primitives.Ints;
-import com.google.gerrit.server.mail.Address;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
diff --git a/java/com/google/gerrit/server/mail/receive/TextParser.java b/java/com/google/gerrit/mail/TextParser.java
similarity index 98%
rename from java/com/google/gerrit/server/mail/receive/TextParser.java
rename to java/com/google/gerrit/mail/TextParser.java
index b99c608..1a63599 100644
--- a/java/com/google/gerrit/server/mail/receive/TextParser.java
+++ b/java/com/google/gerrit/mail/TextParser.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
diff --git a/java/com/google/gerrit/pgm/BUILD b/java/com/google/gerrit/pgm/BUILD
index 95570ec..64dd1d8 100644
--- a/java/com/google/gerrit/pgm/BUILD
+++ b/java/com/google/gerrit/pgm/BUILD
@@ -36,6 +36,7 @@
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server:module",
"//java/com/google/gerrit/server/api",
+ "//java/com/google/gerrit/server/audit",
"//java/com/google/gerrit/server/cache/h2",
"//java/com/google/gerrit/server/cache/mem",
"//java/com/google/gerrit/server/git/receive",
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index c38e7f5..517787c 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -56,6 +56,7 @@
import com.google.gerrit.server.account.InternalAccountDirectory;
import com.google.gerrit.server.api.GerritApiModule;
import com.google.gerrit.server.api.PluginApiModule;
+import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
import com.google.gerrit.server.change.ChangeCleanupRunner;
@@ -422,6 +423,7 @@
modules.add(cfgInjector.getInstance(GerritGlobalModule.class));
modules.add(new GerritApiModule());
modules.add(new PluginApiModule());
+ modules.add(new AuditModule());
modules.add(new SearchingChangeCacheImpl.Module(slave));
modules.add(new InternalAccountDirectory.Module());
diff --git a/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java b/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
index 765e38c..a70d254 100644
--- a/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
+++ b/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
@@ -40,7 +40,8 @@
PRIVATE_BY_DEFAULT("change", "privateByDefault"),
ENABLE_REVIEWER_BY_EMAIL("reviewer", "enableByEmail"),
MATCH_AUTHOR_TO_COMMITTER_DATE("submit", "matchAuthorToCommitterDate"),
- REJECT_EMPTY_COMMIT("submit", "rejectEmptyCommit");
+ REJECT_EMPTY_COMMIT("submit", "rejectEmptyCommit"),
+ WORK_IN_PROGRESS_BY_DEFAULT("change", "workInProgressByDefault");
// Git config
private final String section;
diff --git a/java/com/google/gerrit/reviewdb/client/Project.java b/java/com/google/gerrit/reviewdb/client/Project.java
index 921667e..996f1ec 100644
--- a/java/com/google/gerrit/reviewdb/client/Project.java
+++ b/java/com/google/gerrit/reviewdb/client/Project.java
@@ -99,6 +99,8 @@
protected String themeName;
+ protected String configRefState;
+
protected Project() {}
public Project(Project.NameKey nameKey) {
@@ -239,4 +241,14 @@
public void setParentName(NameKey n) {
parent = n;
}
+
+ /** Returns the {@code ObjectId} as 40 digit hex of {@code refs/meta/config}'s HEAD. */
+ public String getConfigRefState() {
+ return configRefState;
+ }
+
+ /** Sets the {@code ObjectId} as 40 digit hex of {@code refs/meta/config}'s HEAD. */
+ public void setConfigRefState(String state) {
+ configRefState = state;
+ }
}
diff --git a/java/com/google/gerrit/server/ApprovalsUtil.java b/java/com/google/gerrit/server/ApprovalsUtil.java
index 0d12eca..3625de6 100644
--- a/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -263,12 +263,17 @@
private boolean canSee(ReviewDb db, ChangeNotes notes, Account.Id accountId) {
try {
- return projectCache.checkedGet(notes.getProjectName()).statePermitsRead()
- && permissionBackend
- .absentUser(accountId)
- .change(notes)
- .database(db)
- .test(ChangePermission.READ);
+ if (!projectCache.checkedGet(notes.getProjectName()).statePermitsRead()) {
+ return false;
+ }
+ permissionBackend
+ .absentUser(accountId)
+ .change(notes)
+ .database(db)
+ .check(ChangePermission.READ);
+ return true;
+ } catch (AuthException e) {
+ return false;
} catch (IOException | PermissionBackendException e) {
logger.atWarning().withCause(e).log(
"Failed to check if account %d can see change %d",
diff --git a/java/com/google/gerrit/server/BUILD b/java/com/google/gerrit/server/BUILD
index 280a467..e99c686 100644
--- a/java/com/google/gerrit/server/BUILD
+++ b/java/com/google/gerrit/server/BUILD
@@ -36,10 +36,12 @@
"//java/com/google/gerrit/index:query_exception",
"//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/prettify:server",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server/ioutil",
+ "//java/com/google/gerrit/server/util/git",
"//java/com/google/gerrit/util/cli",
"//java/com/google/gerrit/util/ssl",
"//java/org/apache/commons/net",
diff --git a/java/com/google/gerrit/server/ReviewerByEmailSet.java b/java/com/google/gerrit/server/ReviewerByEmailSet.java
index c16c9c8..caae45e 100644
--- a/java/com/google/gerrit/server/ReviewerByEmailSet.java
+++ b/java/com/google/gerrit/server/ReviewerByEmailSet.java
@@ -17,7 +17,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Table;
-import com.google.gerrit.server.mail.Address;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import java.sql.Timestamp;
diff --git a/java/com/google/gerrit/server/account/AccountDirectory.java b/java/com/google/gerrit/server/account/AccountDirectory.java
index eeca29c..ee9265f 100644
--- a/java/com/google/gerrit/server/account/AccountDirectory.java
+++ b/java/com/google/gerrit/server/account/AccountDirectory.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.account;
import com.google.gerrit.extensions.common.AccountInfo;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import java.util.Set;
/**
@@ -47,6 +48,6 @@
STATUS
}
- public abstract void fillAccountInfo(
- Iterable<? extends AccountInfo> in, Set<FillOptions> options);
+ public abstract void fillAccountInfo(Iterable<? extends AccountInfo> in, Set<FillOptions> options)
+ throws PermissionBackendException;
}
diff --git a/java/com/google/gerrit/server/account/AccountLoader.java b/java/com/google/gerrit/server/account/AccountLoader.java
index ddad864..4398d9e 100644
--- a/java/com/google/gerrit/server/account/AccountLoader.java
+++ b/java/com/google/gerrit/server/account/AccountLoader.java
@@ -20,6 +20,7 @@
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.util.ArrayList;
@@ -83,18 +84,18 @@
provided.add(info);
}
- public void fill() {
+ public void fill() throws PermissionBackendException {
directory.fillAccountInfo(Iterables.concat(created.values(), provided), options);
}
- public void fill(Collection<? extends AccountInfo> infos) {
+ public void fill(Collection<? extends AccountInfo> infos) throws PermissionBackendException {
for (AccountInfo info : infos) {
put(info);
}
fill();
}
- public AccountInfo fillOne(Account.Id id) {
+ public AccountInfo fillOne(Account.Id id) throws PermissionBackendException {
AccountInfo info = get(id);
fill();
return info;
diff --git a/java/com/google/gerrit/server/account/InternalAccountDirectory.java b/java/com/google/gerrit/server/account/InternalAccountDirectory.java
index cf21c70..ce97ff9 100644
--- a/java/com/google/gerrit/server/account/InternalAccountDirectory.java
+++ b/java/com/google/gerrit/server/account/InternalAccountDirectory.java
@@ -18,16 +18,23 @@
import static java.util.stream.Collectors.toSet;
import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.AvatarInfo;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.avatar.AvatarProvider;
+import com.google.gerrit.server.permissions.GlobalPermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
@@ -35,6 +42,7 @@
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
@Singleton
@@ -51,22 +59,45 @@
private final AccountCache accountCache;
private final DynamicItem<AvatarProvider> avatar;
private final IdentifiedUser.GenericFactory userFactory;
+ private final Provider<CurrentUser> self;
+ private final PermissionBackend permissionBackend;
@Inject
InternalAccountDirectory(
AccountCache accountCache,
DynamicItem<AvatarProvider> avatar,
- IdentifiedUser.GenericFactory userFactory) {
+ IdentifiedUser.GenericFactory userFactory,
+ Provider<CurrentUser> self,
+ PermissionBackend permissionBackend) {
this.accountCache = accountCache;
this.avatar = avatar;
this.userFactory = userFactory;
+ this.self = self;
+ this.permissionBackend = permissionBackend;
}
@Override
- public void fillAccountInfo(Iterable<? extends AccountInfo> in, Set<FillOptions> options) {
+ public void fillAccountInfo(Iterable<? extends AccountInfo> in, Set<FillOptions> options)
+ throws PermissionBackendException {
if (options.equals(ID_ONLY)) {
return;
}
+
+ boolean canModifyAccount = false;
+ Account.Id currentUserId = null;
+ if (self.get().isIdentifiedUser()) {
+ currentUserId = self.get().getAccountId();
+
+ try {
+ permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
+ canModifyAccount = true;
+ } catch (AuthException e) {
+ canModifyAccount = false;
+ }
+ }
+
+ Set<FillOptions> fillOptionsWithoutSecondaryEmails =
+ Sets.difference(options, EnumSet.of(FillOptions.SECONDARY_EMAILS));
Set<Account.Id> ids =
Streams.stream(in).map(a -> new Account.Id(a._accountId)).collect(toSet());
Map<Account.Id, AccountState> accountStates = accountCache.get(ids);
@@ -74,7 +105,15 @@
Account.Id id = new Account.Id(info._accountId);
AccountState state = accountStates.get(id);
if (state != null) {
- fill(info, accountStates.get(id), options);
+ if (!options.contains(FillOptions.SECONDARY_EMAILS)
+ || Objects.equals(currentUserId, state.getAccount().getId())
+ || canModifyAccount) {
+ fill(info, accountStates.get(id), options);
+ } else {
+ // user is not allowed to see secondary emails
+ fill(info, accountStates.get(id), fillOptionsWithoutSecondaryEmails);
+ }
+
} else {
info._accountId = options.contains(FillOptions.ID) ? id.get() : null;
}
diff --git a/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java b/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
index a1d0c4f..9ef5753 100644
--- a/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
+++ b/java/com/google/gerrit/server/api/accounts/AccountApiImpl.java
@@ -79,7 +79,6 @@
import com.google.gerrit.server.restapi.account.StarredChanges;
import com.google.gerrit.server.restapi.account.Stars;
import com.google.gerrit.server.restapi.change.ChangesCollection;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.List;
@@ -393,7 +392,7 @@
public List<GroupInfo> getGroups() throws RestApiException {
try {
return getGroups.apply(account);
- } catch (OrmException e) {
+ } catch (Exception e) {
throw asRestApiException("Cannot get groups", e);
}
}
@@ -518,7 +517,11 @@
@Override
public List<AgreementInfo> listAgreements() throws RestApiException {
- return getAgreements.apply(account);
+ try {
+ return getAgreements.apply(account);
+ } catch (Exception e) {
+ throw asRestApiException("Cannot get agreements", e);
+ }
}
@Override
diff --git a/java/com/google/gerrit/server/audit/AuditModule.java b/java/com/google/gerrit/server/audit/AuditModule.java
index 0052aaa..df037b6 100644
--- a/java/com/google/gerrit/server/audit/AuditModule.java
+++ b/java/com/google/gerrit/server/audit/AuditModule.java
@@ -16,6 +16,7 @@
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.audit.group.GroupAuditListener;
+import com.google.gerrit.server.group.GroupAuditService;
import com.google.inject.AbstractModule;
public class AuditModule extends AbstractModule {
@@ -24,6 +25,6 @@
protected void configure() {
DynamicSet.setOf(binder(), AuditListener.class);
DynamicSet.setOf(binder(), GroupAuditListener.class);
- bind(AuditService.class);
+ bind(GroupAuditService.class).to(AuditService.class);
}
}
diff --git a/java/com/google/gerrit/server/audit/AuditService.java b/java/com/google/gerrit/server/audit/AuditService.java
index 9528670..2055e33 100644
--- a/java/com/google/gerrit/server/audit/AuditService.java
+++ b/java/com/google/gerrit/server/audit/AuditService.java
@@ -22,12 +22,13 @@
import com.google.gerrit.server.audit.group.GroupAuditListener;
import com.google.gerrit.server.audit.group.GroupMemberAuditEvent;
import com.google.gerrit.server.audit.group.GroupSubgroupAuditEvent;
+import com.google.gerrit.server.group.GroupAuditService;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
@Singleton
-public class AuditService {
+public class AuditService implements GroupAuditService {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final DynamicSet<AuditListener> auditListeners;
@@ -47,6 +48,7 @@
}
}
+ @Override
public void dispatchAddMembers(
Account.Id actor,
AccountGroup.UUID updatedGroup,
@@ -63,6 +65,7 @@
}
}
+ @Override
public void dispatchDeleteMembers(
Account.Id actor,
AccountGroup.UUID updatedGroup,
@@ -79,6 +82,7 @@
}
}
+ @Override
public void dispatchAddSubgroups(
Account.Id actor,
AccountGroup.UUID updatedGroup,
@@ -95,6 +99,7 @@
}
}
+ @Override
public void dispatchDeleteSubgroups(
Account.Id actor,
AccountGroup.UUID updatedGroup,
diff --git a/java/com/google/gerrit/server/audit/BUILD b/java/com/google/gerrit/server/audit/BUILD
new file mode 100644
index 0000000..5efdc5a
--- /dev/null
+++ b/java/com/google/gerrit/server/audit/BUILD
@@ -0,0 +1,73 @@
+java_library(
+ name = "audit",
+ srcs = glob(
+ ["**/*.java"],
+ ),
+ resource_strip_prefix = "resources",
+ resources = ["//resources/com/google/gerrit/server"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/common:annotations",
+ "//java/com/google/gerrit/common:server",
+ "//java/com/google/gerrit/extensions:api",
+ "//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/index:query_exception",
+ "//java/com/google/gerrit/index/project",
+ "//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/metrics",
+ "//java/com/google/gerrit/prettify:server",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/ioutil",
+ "//java/com/google/gerrit/util/cli",
+ "//java/com/google/gerrit/util/ssl",
+ "//java/org/apache/commons/net",
+ "//java/org/eclipse/jgit:server",
+ "//lib:args4j",
+ "//lib:automaton",
+ "//lib:blame-cache",
+ "//lib:grappa",
+ "//lib:gson",
+ "//lib:guava",
+ "//lib:guava-retrying",
+ "//lib:gwtjsonrpc",
+ "//lib:gwtorm",
+ "//lib:jsch",
+ "//lib:juniversalchardet",
+ "//lib:mime-util",
+ "//lib:pegdown",
+ "//lib:protobuf",
+ "//lib:servlet-api-3_1",
+ "//lib:soy",
+ "//lib:tukaani-xz",
+ "//lib/auto:auto-value",
+ "//lib/auto:auto-value-annotations",
+ "//lib/bouncycastle:bcpkix-neverlink",
+ "//lib/bouncycastle:bcprov-neverlink",
+ "//lib/commons:codec",
+ "//lib/commons:compress",
+ "//lib/commons:dbcp",
+ "//lib/commons:lang",
+ "//lib/commons:net",
+ "//lib/commons:validator",
+ "//lib/flogger:api",
+ "//lib/guice",
+ "//lib/guice:guice-assistedinject",
+ "//lib/guice:guice-servlet",
+ "//lib/jgit/org.eclipse.jgit.archive:jgit-archive",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ "//lib/jsoup",
+ "//lib/log:jsonevent-layout",
+ "//lib/log:log4j",
+ "//lib/lucene:lucene-analyzers-common",
+ "//lib/lucene:lucene-core-and-backward-codecs",
+ "//lib/lucene:lucene-queryparser",
+ "//lib/mime4j:core",
+ "//lib/mime4j:dom",
+ "//lib/ow2:ow2-asm",
+ "//lib/ow2:ow2-asm-tree",
+ "//lib/ow2:ow2-asm-util",
+ "//lib/prolog:runtime",
+ "//proto:cache_java_proto",
+ ],
+)
diff --git a/java/com/google/gerrit/server/change/ChangeInserter.java b/java/com/google/gerrit/server/change/ChangeInserter.java
index 8ca364b..e8c55e8 100644
--- a/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -29,6 +29,7 @@
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Account;
@@ -459,18 +460,24 @@
.stream()
.filter(
accountId -> {
+ if (!projectState.statePermitsRead()) {
+ return false;
+ }
+
try {
- return permissionBackend
- .absentUser(accountId)
- .change(notes)
- .database(db)
- .test(ChangePermission.READ)
- && projectState.statePermitsRead();
+ permissionBackend
+ .absentUser(accountId)
+ .change(notes)
+ .database(db)
+ .check(ChangePermission.READ);
+ return true;
} catch (PermissionBackendException e) {
logger.atWarning().withCause(e).log(
"Failed to check if account %d can see change %d",
accountId.get(), notes.getChangeId().get());
return false;
+ } catch (AuthException e) {
+ return false;
}
})
.collect(toSet());
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index a5bcf48..04b649b 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -91,6 +91,7 @@
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.query.QueryResult;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
@@ -123,7 +124,6 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.index.change.ChangeField;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
@@ -415,7 +415,8 @@
return format(cd, Optional.of(rsrc.getPatchSet().getId()), true);
}
- public List<List<ChangeInfo>> formatQueryResults(List<QueryResult<ChangeData>> in) {
+ public List<List<ChangeInfo>> formatQueryResults(List<QueryResult<ChangeData>> in)
+ throws PermissionBackendException {
try (Timer0.Context ignored = metrics.formatQueryResultsLatency.start()) {
accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
List<List<ChangeInfo>> res = new ArrayList<>(in.size());
@@ -433,7 +434,8 @@
}
}
- public List<ChangeInfo> formatChangeDatas(Collection<ChangeData> in) throws OrmException {
+ public List<ChangeInfo> formatChangeDatas(Collection<ChangeData> in)
+ throws OrmException, PermissionBackendException {
accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
ensureLoaded(in);
List<ChangeInfo> out = new ArrayList<>(in.size());
diff --git a/java/com/google/gerrit/server/change/ReviewerResource.java b/java/com/google/gerrit/server/change/ReviewerResource.java
index 778897e..52f3585 100644
--- a/java/com/google/gerrit/server/change/ReviewerResource.java
+++ b/java/com/google/gerrit/server/change/ReviewerResource.java
@@ -19,10 +19,10 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.mail.Address;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 57255a3..b6a257b 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -91,7 +91,6 @@
import com.google.gerrit.server.account.GroupIncludeCacheImpl;
import com.google.gerrit.server.account.VersionedAuthorizedKeys;
import com.google.gerrit.server.account.externalids.ExternalIdModule;
-import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.auth.AuthBackend;
import com.google.gerrit.server.auth.UniversalAuthBackend;
import com.google.gerrit.server.auth.oauth.OAuthTokenCache;
@@ -301,7 +300,6 @@
bind(IdentifiedUser.GenericFactory.class).in(SINGLETON);
bind(AccountControl.Factory.class);
- install(new AuditModule());
bind(UiActions.class);
bind(GitReferenceUpdated.class);
diff --git a/java/com/google/gerrit/server/events/EventBroker.java b/java/com/google/gerrit/server/events/EventBroker.java
index 7d35070..1aff0fa 100644
--- a/java/com/google/gerrit/server/events/EventBroker.java
+++ b/java/com/google/gerrit/server/events/EventBroker.java
@@ -171,21 +171,31 @@
return false;
}
ReviewDb db = dbProvider.get();
- return permissionBackend
- .user(user)
- .change(notesFactory.createChecked(db, change))
- .database(db)
- .test(ChangePermission.READ);
+ try {
+ permissionBackend
+ .user(user)
+ .change(notesFactory.createChecked(db, change))
+ .database(db)
+ .check(ChangePermission.READ);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
protected boolean isVisibleTo(Branch.NameKey branchName, CurrentUser user)
throws PermissionBackendException {
ProjectState pe = projectCache.get(branchName.getParentKey());
- if (pe == null) {
+ if (pe == null || !pe.statePermitsRead()) {
return false;
}
- return pe.statePermitsRead()
- && permissionBackend.user(user).ref(branchName).test(RefPermission.READ);
+
+ try {
+ permissionBackend.user(user).ref(branchName).check(RefPermission.READ);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
protected boolean isVisibleTo(Event event, CurrentUser user)
diff --git a/java/com/google/gerrit/server/git/NotifyConfig.java b/java/com/google/gerrit/server/git/NotifyConfig.java
index d2d3a39..d39cf12 100644
--- a/java/com/google/gerrit/server/git/NotifyConfig.java
+++ b/java/com/google/gerrit/server/git/NotifyConfig.java
@@ -16,8 +16,8 @@
import com.google.common.base.Strings;
import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.mail.Address;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index d5b1966..516dcd4 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -2204,6 +2204,7 @@
}
private void setChangeId(int id) {
+ possiblyOverrideWorkInProgress();
changeId = new Change.Id(id);
ins =
@@ -2224,6 +2225,16 @@
}
}
+ private void possiblyOverrideWorkInProgress() {
+ // When wip or ready explicitly provided, leave it as is.
+ if (magicBranch.workInProgress || magicBranch.ready) {
+ return;
+ }
+ magicBranch.workInProgress =
+ projectState.is(BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT)
+ || firstNonNull(user.state().getGeneralPreferences().workInProgressByDefault, false);
+ }
+
private void addOps(BatchUpdate bu) throws RestApiException {
checkState(changeId != null, "must call setChangeId before addOps");
try {
@@ -2528,11 +2539,23 @@
if (magicBranch != null
&& (magicBranch.workInProgress || magicBranch.ready)
&& magicBranch.workInProgress != change.isWorkInProgress()
- && (!user.getAccountId().equals(change.getOwner())
- && !permissions.test(ProjectPermission.WRITE_CONFIG)
- && !permissionBackend.user(user).test(GlobalPermission.ADMINISTRATE_SERVER))) {
- reject(inputCommand, ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP);
- return false;
+ && !user.getAccountId().equals(change.getOwner())) {
+ boolean hasWriteConfigPermission = false;
+ try {
+ permissions.check(ProjectPermission.WRITE_CONFIG);
+ hasWriteConfigPermission = true;
+ } catch (AuthException e) {
+ // Do nothing.
+ }
+
+ if (!hasWriteConfigPermission) {
+ try {
+ permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
+ } catch (AuthException e1) {
+ reject(inputCommand, ONLY_CHANGE_OWNER_OR_PROJECT_OWNER_CAN_MODIFY_WIP);
+ return false;
+ }
+ }
}
if (magicBranch != null && (magicBranch.edit || magicBranch.draft)) {
diff --git a/java/com/google/gerrit/server/git/validators/CommitValidators.java b/java/com/google/gerrit/server/git/validators/CommitValidators.java
index 57786a6..e4c7b35 100644
--- a/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -335,27 +335,26 @@
StringBuilder sb = new StringBuilder();
sb.append("ERROR: ").append(errMsg);
+ boolean hinted = false;
if (c.getFullMessage().contains(CHANGE_ID_PREFIX)) {
String lastLine = Iterables.getLast(Splitter.on('\n').split(c.getFullMessage()), "");
if (!lastLine.contains(CHANGE_ID_PREFIX)) {
- sb.append('\n');
- sb.append('\n');
- sb.append("Hint: A potential ");
- sb.append(FooterConstants.CHANGE_ID.getName());
- sb.append(" was found, but it was not in the ");
- sb.append("footer (last paragraph) of the commit message.");
+ hinted = true;
+ sb.append("\n\n")
+ .append("Hint: run\n")
+ .append(" git commit --amend\n")
+ .append("and move 'Change-Id: Ixxx..' to the bottom on a separate line\n");
}
}
- sb.append('\n');
- sb.append('\n');
- sb.append("Hint: To automatically insert ");
- sb.append(FooterConstants.CHANGE_ID.getName());
- sb.append(", install the hook:\n");
- sb.append(getCommitMessageHookInstallationHint());
- sb.append('\n');
- sb.append("And then amend the commit:\n");
- sb.append(" git commit --amend\n");
+ // Print only one hint to avoid overwhelming the user.
+ if (!hinted) {
+ sb.append("Hint: to automatically insert a Change-Id, install the hook:\n")
+ .append(getCommitMessageHookInstallationHint())
+ .append("\n")
+ .append("and then amend the commit:\n")
+ .append(" git commit --amend\n");
+ }
return new CommitValidationMessage(sb.toString(), false);
}
diff --git a/java/com/google/gerrit/server/group/GroupAuditService.java b/java/com/google/gerrit/server/group/GroupAuditService.java
new file mode 100644
index 0000000..c543a6e
--- /dev/null
+++ b/java/com/google/gerrit/server/group/GroupAuditService.java
@@ -0,0 +1,48 @@
+// Copyright (C) 2018 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.group;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Account.Id;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import java.sql.Timestamp;
+
+public interface GroupAuditService {
+
+ void dispatchAddMembers(
+ Account.Id actor,
+ AccountGroup.UUID updatedGroup,
+ ImmutableSet<Id> addedMembers,
+ Timestamp addedOn);
+
+ void dispatchDeleteMembers(
+ Account.Id actor,
+ AccountGroup.UUID updatedGroup,
+ ImmutableSet<Account.Id> deletedMembers,
+ Timestamp deletedOn);
+
+ void dispatchAddSubgroups(
+ Account.Id actor,
+ AccountGroup.UUID updatedGroup,
+ ImmutableSet<AccountGroup.UUID> addedSubgroups,
+ Timestamp addedOn);
+
+ void dispatchDeleteSubgroups(
+ Account.Id actor,
+ AccountGroup.UUID updatedGroup,
+ ImmutableSet<AccountGroup.UUID> deletedSubgroups,
+ Timestamp deletedOn);
+}
diff --git a/java/com/google/gerrit/server/group/db/GroupsUpdate.java b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
index 38db2e6..cd38c6a 100644
--- a/java/com/google/gerrit/server/group/db/GroupsUpdate.java
+++ b/java/com/google/gerrit/server/group/db/GroupsUpdate.java
@@ -31,13 +31,13 @@
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupIncludeCache;
-import com.google.gerrit.server.audit.AuditService;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LockFailureException;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.group.GroupAuditService;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.update.RefUpdateUtil;
@@ -89,7 +89,7 @@
private final GroupCache groupCache;
private final GroupIncludeCache groupIncludeCache;
private final Provider<GroupIndexer> indexer;
- private final AuditService auditService;
+ private final GroupAuditService groupAuditService;
private final RenameGroupOp.Factory renameGroupOpFactory;
@Nullable private final IdentifiedUser currentUser;
private final AuditLogFormatter auditLogFormatter;
@@ -106,7 +106,7 @@
GroupCache groupCache,
GroupIncludeCache groupIncludeCache,
Provider<GroupIndexer> indexer,
- AuditService auditService,
+ GroupAuditService auditService,
AccountCache accountCache,
RenameGroupOp.Factory renameGroupOpFactory,
@GerritServerId String serverId,
@@ -120,7 +120,7 @@
this.groupCache = groupCache;
this.groupIncludeCache = groupIncludeCache;
this.indexer = indexer;
- this.auditService = auditService;
+ this.groupAuditService = auditService;
this.renameGroupOpFactory = renameGroupOpFactory;
this.gitRefUpdated = gitRefUpdated;
this.retryHelper = retryHelper;
@@ -384,14 +384,14 @@
}
if (!createdGroup.getMembers().isEmpty()) {
- auditService.dispatchAddMembers(
+ groupAuditService.dispatchAddMembers(
currentUser.getAccountId(),
createdGroup.getGroupUUID(),
createdGroup.getMembers(),
createdGroup.getCreatedOn());
}
if (!createdGroup.getSubgroups().isEmpty()) {
- auditService.dispatchAddSubgroups(
+ groupAuditService.dispatchAddSubgroups(
currentUser.getAccountId(),
createdGroup.getGroupUUID(),
createdGroup.getSubgroups(),
@@ -405,19 +405,19 @@
}
if (!result.getAddedMembers().isEmpty()) {
- auditService.dispatchAddMembers(
+ groupAuditService.dispatchAddMembers(
currentUser.getAccountId(), result.getGroupUuid(), result.getAddedMembers(), updatedOn);
}
if (!result.getDeletedMembers().isEmpty()) {
- auditService.dispatchDeleteMembers(
+ groupAuditService.dispatchDeleteMembers(
currentUser.getAccountId(), result.getGroupUuid(), result.getDeletedMembers(), updatedOn);
}
if (!result.getAddedSubgroups().isEmpty()) {
- auditService.dispatchAddSubgroups(
+ groupAuditService.dispatchAddSubgroups(
currentUser.getAccountId(), result.getGroupUuid(), result.getAddedSubgroups(), updatedOn);
}
if (!result.getDeletedSubgroups().isEmpty()) {
- auditService.dispatchDeleteSubgroups(
+ groupAuditService.dispatchDeleteSubgroups(
currentUser.getAccountId(),
result.getGroupUuid(),
result.getDeletedSubgroups(),
diff --git a/java/com/google/gerrit/server/index/account/AccountField.java b/java/com/google/gerrit/server/index/account/AccountField.java
index 31e2ada..111991c 100644
--- a/java/com/google/gerrit/server/index/account/AccountField.java
+++ b/java/com/google/gerrit/server/index/account/AccountField.java
@@ -27,11 +27,11 @@
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.index.FieldDef;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.index.SchemaUtil;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.index.RefState;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Collections;
diff --git a/java/com/google/gerrit/server/index/account/StalenessChecker.java b/java/com/google/gerrit/server/index/account/StalenessChecker.java
index 6403d3d..0c3e329 100644
--- a/java/com/google/gerrit/server/index/account/StalenessChecker.java
+++ b/java/com/google/gerrit/server/index/account/StalenessChecker.java
@@ -24,6 +24,7 @@
import com.google.common.collect.MultimapBuilder;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.index.query.FieldBundle;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
@@ -33,7 +34,6 @@
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.IndexUtils;
-import com.google.gerrit.server.index.RefState;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index 405e6fc..5d12e79 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -43,7 +43,9 @@
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.data.SubmitRequirement;
import com.google.gerrit.index.FieldDef;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.index.SchemaUtil;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -56,9 +58,7 @@
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.index.RefState;
import com.google.gerrit.server.index.change.StalenessChecker.RefStatePattern;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
diff --git a/java/com/google/gerrit/server/index/change/StalenessChecker.java b/java/com/google/gerrit/server/index/change/StalenessChecker.java
index 642385c..0508b60 100644
--- a/java/com/google/gerrit/server/index/change/StalenessChecker.java
+++ b/java/com/google/gerrit/server/index/change/StalenessChecker.java
@@ -31,12 +31,12 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.UsedAt;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.index.RefState;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.query.change.ChangeData;
diff --git a/java/com/google/gerrit/server/index/project/StalenessChecker.java b/java/com/google/gerrit/server/index/project/StalenessChecker.java
new file mode 100644
index 0000000..5603f08
--- /dev/null
+++ b/java/com/google/gerrit/server/index/project/StalenessChecker.java
@@ -0,0 +1,81 @@
+// Copyright (C) 2018 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.index.project;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.MultimapBuilder;
+import com.google.common.collect.SetMultimap;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.RefState;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.project.ProjectField;
+import com.google.gerrit.index.project.ProjectIndex;
+import com.google.gerrit.index.project.ProjectIndexCollection;
+import com.google.gerrit.index.query.FieldBundle;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.server.project.ProjectCache;
+import java.io.IOException;
+import java.util.Optional;
+import javax.inject.Inject;
+
+public class StalenessChecker {
+ private static final ImmutableSet<String> FIELDS =
+ ImmutableSet.of(ProjectField.NAME.getName(), ProjectField.REF_STATE.getName());
+
+ private final ProjectCache projectCache;
+ private final ProjectIndexCollection indexes;
+ private final IndexConfig indexConfig;
+
+ @Inject
+ StalenessChecker(
+ ProjectCache projectCache, ProjectIndexCollection indexes, IndexConfig indexConfig) {
+ this.projectCache = projectCache;
+ this.indexes = indexes;
+ this.indexConfig = indexConfig;
+ }
+
+ public boolean isStale(Project.NameKey project) throws IOException {
+ ProjectData projectData = projectCache.get(project).toProjectData();
+ ProjectIndex i = indexes.getSearchIndex();
+ if (i == null) {
+ return false; // No index; caller couldn't do anything if it is stale.
+ }
+
+ Optional<FieldBundle> result =
+ i.getRaw(project, QueryOptions.create(indexConfig, 0, 1, FIELDS));
+ if (!result.isPresent()) {
+ return true;
+ }
+
+ SetMultimap<Project.NameKey, RefState> indexedRefStates =
+ RefState.parseStates(result.get().getValue(ProjectField.REF_STATE));
+
+ SetMultimap<Project.NameKey, RefState> currentRefStates =
+ MultimapBuilder.hashKeys().hashSetValues().build();
+ projectData
+ .tree()
+ .stream()
+ .filter(p -> p.getProject().getConfigRefState() != null)
+ .forEach(
+ p ->
+ currentRefStates.put(
+ p.getProject().getNameKey(),
+ RefState.create(RefNames.REFS_CONFIG, p.getProject().getConfigRefState())));
+
+ return !currentRefStates.equals(indexedRefStates);
+ }
+}
diff --git a/java/com/google/gerrit/server/ioutil/HexFormat.java b/java/com/google/gerrit/server/ioutil/HexFormat.java
new file mode 100644
index 0000000..fd9c17a
--- /dev/null
+++ b/java/com/google/gerrit/server/ioutil/HexFormat.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 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.ioutil;
+
+public class HexFormat {
+ public static String fromInt(int id) {
+ final char[] r = new char[8];
+ for (int p = 7; 0 <= p; p--) {
+ final int h = id & 0xf;
+ r[p] = h < 10 ? (char) ('0' + h) : (char) ('a' + (h - 10));
+ id >>= 4;
+ }
+ return new String(r);
+ }
+}
diff --git a/java/com/google/gerrit/server/mail/AutoReplyMailFilter.java b/java/com/google/gerrit/server/mail/AutoReplyMailFilter.java
index 9032932..e18fd42 100644
--- a/java/com/google/gerrit/server/mail/AutoReplyMailFilter.java
+++ b/java/com/google/gerrit/server/mail/AutoReplyMailFilter.java
@@ -15,7 +15,8 @@
package com.google.gerrit.server.mail;
import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailHeader;
+import com.google.gerrit.mail.MailMessage;
import com.google.inject.Singleton;
/** Filters out auto-reply messages according to RFC 3834. */
diff --git a/java/com/google/gerrit/server/mail/ListMailFilter.java b/java/com/google/gerrit/server/mail/ListMailFilter.java
index 5a41c77..eee8c60 100644
--- a/java/com/google/gerrit/server/mail/ListMailFilter.java
+++ b/java/com/google/gerrit/server/mail/ListMailFilter.java
@@ -17,8 +17,8 @@
import static java.util.stream.Collectors.joining;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.mail.MailMessage;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.mail.receive.MailMessage;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.Arrays;
@@ -52,7 +52,7 @@
return true;
}
- boolean match = mailPattern.matcher(message.from().email).find();
+ boolean match = mailPattern.matcher(message.from().getEmail()).find();
if (mode == ListFilterMode.WHITELIST && !match || mode == ListFilterMode.BLACKLIST && match) {
logger.atInfo().log("Mail message from %s rejected by list filter", message.from());
return false;
diff --git a/java/com/google/gerrit/server/mail/MailFilter.java b/java/com/google/gerrit/server/mail/MailFilter.java
index d50064d..5fff8a3 100644
--- a/java/com/google/gerrit/server/mail/MailFilter.java
+++ b/java/com/google/gerrit/server/mail/MailFilter.java
@@ -15,7 +15,7 @@
package com.google.gerrit.server.mail;
import com.google.gerrit.extensions.annotations.ExtensionPoint;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
/**
* Listener to filter incoming email.
diff --git a/java/com/google/gerrit/server/mail/MailUtil.java b/java/com/google/gerrit/server/mail/MailUtil.java
index 0487cc0..507b53f 100644
--- a/java/com/google/gerrit/server/mail/MailUtil.java
+++ b/java/com/google/gerrit/server/mail/MailUtil.java
@@ -24,7 +24,6 @@
import com.google.gerrit.server.account.AccountResolver;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
-import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -34,8 +33,6 @@
import org.eclipse.jgit.revwalk.FooterLine;
public class MailUtil {
- public static DateTimeFormatter rfcDateformatter =
- DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss ZZZ");
public static MailRecipients getRecipientsFromFooters(
AccountResolver accountResolver, List<FooterLine> footerLines)
diff --git a/java/com/google/gerrit/server/mail/receive/ImapMailReceiver.java b/java/com/google/gerrit/server/mail/receive/ImapMailReceiver.java
index 169b41e..648006d 100644
--- a/java/com/google/gerrit/server/mail/receive/ImapMailReceiver.java
+++ b/java/com/google/gerrit/server/mail/receive/ImapMailReceiver.java
@@ -15,6 +15,9 @@
package com.google.gerrit.server.mail.receive;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.mail.MailMessage;
+import com.google.gerrit.mail.MailParsingException;
+import com.google.gerrit.mail.RawMailParser;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.mail.EmailSettings;
import com.google.gerrit.server.mail.Encryption;
diff --git a/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index bf76bde..75053c8 100644
--- a/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -26,6 +26,12 @@
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.mail.HtmlParser;
+import com.google.gerrit.mail.MailComment;
+import com.google.gerrit.mail.MailHeaderParser;
+import com.google.gerrit.mail.MailMessage;
+import com.google.gerrit.mail.MailMetadata;
+import com.google.gerrit.mail.TextParser;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -283,7 +289,7 @@
comments = new ArrayList<>();
for (MailComment c : parsedComments) {
- if (c.type == MailComment.CommentType.CHANGE_MESSAGE) {
+ if (c.getType() == MailComment.CommentType.CHANGE_MESSAGE) {
continue;
}
comments.add(
@@ -301,8 +307,8 @@
@Override
public void postUpdate(Context ctx) throws Exception {
String patchSetComment = null;
- if (parsedComments.get(0).type == MailComment.CommentType.CHANGE_MESSAGE) {
- patchSetComment = parsedComments.get(0).message;
+ if (parsedComments.get(0).getType() == MailComment.CommentType.CHANGE_MESSAGE) {
+ patchSetComment = parsedComments.get(0).getMessage();
}
// Send email notifications
outgoingMailFactory
@@ -342,12 +348,12 @@
private ChangeMessage generateChangeMessage(ChangeContext ctx) {
String changeMsg = "Patch Set " + psId.get() + ":";
- if (parsedComments.get(0).type == MailComment.CommentType.CHANGE_MESSAGE) {
+ if (parsedComments.get(0).getType() == MailComment.CommentType.CHANGE_MESSAGE) {
// Add a blank line after Patch Set to follow the default format
if (parsedComments.size() > 1) {
changeMsg += "\n\n" + numComments(parsedComments.size() - 1);
}
- changeMsg += "\n\n" + parsedComments.get(0).message;
+ changeMsg += "\n\n" + parsedComments.get(0).getMessage();
} else {
changeMsg += "\n\n" + numComments(parsedComments.size());
}
@@ -356,11 +362,11 @@
private PatchSet targetPatchSetForComment(
ChangeContext ctx, MailComment mailComment, PatchSet current) throws OrmException {
- if (mailComment.inReplyTo != null) {
+ if (mailComment.getInReplyTo() != null) {
return psUtil.get(
ctx.getDb(),
ctx.getNotes(),
- new PatchSet.Id(ctx.getChange().getId(), mailComment.inReplyTo.key.patchSetId));
+ new PatchSet.Id(ctx.getChange().getId(), mailComment.getInReplyTo().key.patchSetId));
}
return current;
}
@@ -372,11 +378,11 @@
// The patch set that this comment is based on is different if this
// comment was sent in reply to a comment on a previous patch set.
Side side;
- if (mailComment.inReplyTo != null) {
- fileName = mailComment.inReplyTo.key.filename;
- side = Side.fromShort(mailComment.inReplyTo.side);
+ if (mailComment.getInReplyTo() != null) {
+ fileName = mailComment.getInReplyTo().key.filename;
+ side = Side.fromShort(mailComment.getInReplyTo().side);
} else {
- fileName = mailComment.fileName;
+ fileName = mailComment.getFileName();
side = Side.REVISION;
}
@@ -386,16 +392,16 @@
fileName,
patchSetForComment.getId(),
(short) side.ordinal(),
- mailComment.message,
+ mailComment.getMessage(),
false,
null);
comment.tag = tag;
- if (mailComment.inReplyTo != null) {
- comment.parentUuid = mailComment.inReplyTo.key.uuid;
- comment.lineNbr = mailComment.inReplyTo.lineNbr;
- comment.range = mailComment.inReplyTo.range;
- comment.unresolved = mailComment.inReplyTo.unresolved;
+ if (mailComment.getInReplyTo() != null) {
+ comment.parentUuid = mailComment.getInReplyTo().key.uuid;
+ comment.lineNbr = mailComment.getInReplyTo().lineNbr;
+ comment.range = mailComment.getInReplyTo().range;
+ comment.unresolved = mailComment.getInReplyTo().unresolved;
}
CommentsUtil.setCommentRevId(comment, patchListCache, ctx.getChange(), patchSetForComment);
return comment;
diff --git a/java/com/google/gerrit/server/mail/receive/MailReceiver.java b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
index e4ad969..dc99b46 100644
--- a/java/com/google/gerrit/server/mail/receive/MailReceiver.java
+++ b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
@@ -19,6 +19,7 @@
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.mail.MailMessage;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.mail.EmailSettings;
import com.google.gerrit.server.update.UpdateException;
diff --git a/java/com/google/gerrit/server/mail/receive/Pop3MailReceiver.java b/java/com/google/gerrit/server/mail/receive/Pop3MailReceiver.java
index a3ea265..54971c4 100644
--- a/java/com/google/gerrit/server/mail/receive/Pop3MailReceiver.java
+++ b/java/com/google/gerrit/server/mail/receive/Pop3MailReceiver.java
@@ -16,6 +16,9 @@
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
+import com.google.gerrit.mail.MailMessage;
+import com.google.gerrit.mail.MailParsingException;
+import com.google.gerrit.mail.RawMailParser;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.mail.EmailSettings;
import com.google.gerrit.server.mail.Encryption;
diff --git a/java/com/google/gerrit/server/mail/send/AddKeySender.java b/java/com/google/gerrit/server/mail/send/AddKeySender.java
index ae8ac31..433bd9b 100644
--- a/java/com/google/gerrit/server/mail/send/AddKeySender.java
+++ b/java/com/google/gerrit/server/mail/send/AddKeySender.java
@@ -18,9 +18,9 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountSshKey;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
diff --git a/java/com/google/gerrit/server/mail/send/ChangeEmail.java b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
index 503fbd0..00a496a2 100644
--- a/java/com/google/gerrit/server/mail/send/ChangeEmail.java
+++ b/java/com/google/gerrit/server/mail/send/ChangeEmail.java
@@ -21,6 +21,7 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.mail.MailHeader;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
@@ -30,7 +31,6 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.mail.MailHeader;
import com.google.gerrit.server.mail.send.ProjectWatch.Watchers;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.patch.PatchList;
@@ -403,12 +403,19 @@
@Override
protected boolean isVisibleTo(Account.Id to) throws PermissionBackendException {
- return projectState.statePermitsRead()
- && args.permissionBackend
- .absentUser(to)
- .change(changeData)
- .database(args.db)
- .test(ChangePermission.READ);
+ if (!projectState.statePermitsRead()) {
+ return false;
+ }
+ try {
+ args.permissionBackend
+ .absentUser(to)
+ .change(changeData)
+ .database(args.db)
+ .check(ChangePermission.READ);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
/** Find all users who are authors of any part of this change. */
diff --git a/java/com/google/gerrit/server/mail/send/CommentSender.java b/java/com/google/gerrit/server/mail/send/CommentSender.java
index 0095fc1..54176e2 100644
--- a/java/com/google/gerrit/server/mail/send/CommentSender.java
+++ b/java/com/google/gerrit/server/mail/send/CommentSender.java
@@ -23,6 +23,8 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
+import com.google.gerrit.mail.MailHeader;
+import com.google.gerrit.mail.MailProcessingUtil;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
@@ -32,8 +34,6 @@
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.mail.MailHeader;
-import com.google.gerrit.server.mail.MailUtil;
import com.google.gerrit.server.mail.receive.Protocol;
import com.google.gerrit.server.patch.PatchFile;
import com.google.gerrit.server.patch.PatchList;
@@ -566,7 +566,7 @@
private String getCommentTimestamp() {
// Grouping is currently done by timestamp.
- return MailUtil.rfcDateformatter.format(
+ return MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of("UTC")));
}
diff --git a/java/com/google/gerrit/server/mail/send/DeleteReviewerSender.java b/java/com/google/gerrit/server/mail/send/DeleteReviewerSender.java
index c434d06..576d506 100644
--- a/java/com/google/gerrit/server/mail/send/DeleteReviewerSender.java
+++ b/java/com/google/gerrit/server/mail/send/DeleteReviewerSender.java
@@ -16,11 +16,11 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.mail.Address;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
diff --git a/java/com/google/gerrit/server/mail/send/EmailSender.java b/java/com/google/gerrit/server/mail/send/EmailSender.java
index 23fa1fe..ce4964d 100644
--- a/java/com/google/gerrit/server/mail/send/EmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/EmailSender.java
@@ -16,7 +16,8 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.errors.EmailException;
-import com.google.gerrit.server.mail.Address;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
import java.util.Collection;
import java.util.Map;
diff --git a/java/com/google/gerrit/server/mail/send/FromAddressGenerator.java b/java/com/google/gerrit/server/mail/send/FromAddressGenerator.java
index 2489063..5baabe9 100644
--- a/java/com/google/gerrit/server/mail/send/FromAddressGenerator.java
+++ b/java/com/google/gerrit/server/mail/send/FromAddressGenerator.java
@@ -14,8 +14,8 @@
package com.google.gerrit.server.mail.send;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.server.mail.Address;
/** Constructs an address to send email from. */
public interface FromAddressGenerator {
diff --git a/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java b/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
index 500eef3..b77909e 100644
--- a/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
+++ b/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
@@ -17,13 +17,13 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.gerrit.common.data.ParameterizedString;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.MailUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
diff --git a/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java b/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
index 5143dc7..65ce128 100644
--- a/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
+++ b/java/com/google/gerrit/server/mail/send/InboundEmailRejectionSender.java
@@ -18,8 +18,8 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.MailHeader;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailHeader;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.apache.james.mime4j.dom.field.FieldName;
diff --git a/java/com/google/gerrit/server/mail/send/NewChangeSender.java b/java/com/google/gerrit/server/mail/send/NewChangeSender.java
index 9f94fa3..f94f1ca 100644
--- a/java/com/google/gerrit/server/mail/send/NewChangeSender.java
+++ b/java/com/google/gerrit/server/mail/send/NewChangeSender.java
@@ -16,8 +16,8 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import java.util.ArrayList;
diff --git a/java/com/google/gerrit/server/mail/send/NotificationEmail.java b/java/com/google/gerrit/server/mail/send/NotificationEmail.java
index 0cc7a1d..032bcbf 100644
--- a/java/com/google/gerrit/server/mail/send/NotificationEmail.java
+++ b/java/com/google/gerrit/server/mail/send/NotificationEmail.java
@@ -19,11 +19,11 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailHeader;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.MailHeader;
import com.google.gerrit.server.mail.send.ProjectWatch.Watchers;
import com.google.gwtorm.server.OrmException;
import java.util.HashMap;
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index 0612237..fe9b446 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -26,12 +26,13 @@
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailFormat;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
+import com.google.gerrit.mail.EmailHeader.AddressList;
+import com.google.gerrit.mail.MailHeader;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.MailHeader;
-import com.google.gerrit.server.mail.send.EmailHeader.AddressList;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.validators.OutgoingEmailValidationListener;
import com.google.gerrit.server.validators.ValidationException;
diff --git a/java/com/google/gerrit/server/mail/send/ProjectWatch.java b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
index 15197ef..9a86fdb 100644
--- a/java/com/google/gerrit/server/mail/send/ProjectWatch.java
+++ b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
@@ -21,6 +21,7 @@
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
@@ -30,7 +31,6 @@
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
import com.google.gerrit.server.git.NotifyConfig;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
diff --git a/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java b/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
index c667026..0dbfb60 100644
--- a/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
@@ -18,8 +18,8 @@
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.EmailTokenVerifier;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
diff --git a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
index 10e8b0b..2262b5c 100644
--- a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
@@ -22,9 +22,10 @@
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.Version;
import com.google.gerrit.common.errors.EmailException;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.Encryption;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index 5f2593b..5810c64 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -55,6 +55,7 @@
import com.google.common.primitives.Ints;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
@@ -70,7 +71,6 @@
import com.google.gerrit.server.ReviewerByEmailSet;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gerrit.server.util.LabelVote;
import java.io.IOException;
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesState.java b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
index 3eb06b2..3543202 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesState.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesState.java
@@ -39,6 +39,7 @@
import com.google.common.collect.Table;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
@@ -61,7 +62,6 @@
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerStatusUpdateProto;
import com.google.gerrit.server.index.change.ChangeField.StoredSubmitRecord;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gson.Gson;
import java.io.IOException;
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index 69fbfe1..903a982 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -52,6 +52,7 @@
import com.google.common.collect.TreeBasedTable;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
@@ -62,7 +63,6 @@
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.RequestId;
diff --git a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
index 9a9a211..b250a34 100644
--- a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
+++ b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
@@ -14,20 +14,27 @@
package com.google.gerrit.server.notedb;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.server.notedb.RevisionNote.MAX_NOTE_SZ;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerIdProvider;
+import com.google.gerrit.server.update.RefUpdateUtil;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
+import java.util.List;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.internal.storage.file.PackInserter;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
@@ -47,22 +54,65 @@
public class CommentJsonMigrator {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ public static class ProjectMigrationResult {
+ public int skipped;
+ public boolean ok;
+ public List<String> refsUpdated;
+ }
+
private final LegacyChangeNoteRead legacyChangeNoteRead;
private final ChangeNoteJson changeNoteJson;
+ private final AllUsersName allUsers;
@Inject
CommentJsonMigrator(
- ChangeNoteJson changeNoteJson, GerritServerIdProvider gerritServerIdProvider) {
+ ChangeNoteJson changeNoteJson,
+ GerritServerIdProvider gerritServerIdProvider,
+ AllUsersName allUsers) {
this.changeNoteJson = changeNoteJson;
+ this.allUsers = allUsers;
this.legacyChangeNoteRead = new LegacyChangeNoteRead(gerritServerIdProvider.get());
}
- CommentJsonMigrator(ChangeNoteJson changeNoteJson, String serverId) {
+ CommentJsonMigrator(ChangeNoteJson changeNoteJson, String serverId, AllUsersName allUsers) {
this.changeNoteJson = changeNoteJson;
this.legacyChangeNoteRead = new LegacyChangeNoteRead(serverId);
+ this.allUsers = allUsers;
}
- public boolean migrateChanges(
+ public ProjectMigrationResult migrateProject(
+ Project.NameKey project, Repository repo, boolean dryRun) {
+ ProjectMigrationResult progress = new ProjectMigrationResult();
+ progress.ok = true;
+ progress.skipped = 0;
+ progress.refsUpdated = ImmutableList.of();
+ try (RevWalk rw = new RevWalk(repo);
+ ObjectInserter ins = newPackInserter(repo)) {
+ BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
+ bru.setAllowNonFastForwards(true);
+ progress.ok &= migrateChanges(project, repo, rw, ins, bru);
+ if (project.equals(allUsers)) {
+ progress.ok &= migrateDrafts(allUsers, repo, rw, ins, bru);
+ }
+
+ progress.refsUpdated =
+ bru.getCommands().stream().map(c -> c.getRefName()).collect(toImmutableList());
+ if (!bru.getCommands().isEmpty()) {
+ if (!dryRun) {
+ ins.flush();
+ RefUpdateUtil.executeChecked(bru, rw);
+ }
+ } else {
+ progress.skipped++;
+ }
+ } catch (IOException e) {
+ progress.ok = false;
+ }
+
+ return progress;
+ }
+
+ private boolean migrateChanges(
Project.NameKey project, Repository repo, RevWalk rw, ObjectInserter ins, BatchRefUpdate bru)
throws IOException {
boolean ok = true;
@@ -76,7 +126,7 @@
return ok;
}
- public boolean migrateDrafts(
+ private boolean migrateDrafts(
Project.NameKey allUsers,
Repository allUsersRepo,
RevWalk rw,
@@ -187,4 +237,13 @@
rw.sort(RevSort.REVERSE);
rw.markStart(rw.parseCommit(id));
}
+
+ private static ObjectInserter newPackInserter(Repository repo) {
+ if (!(repo instanceof FileRepository)) {
+ return repo.newObjectInserter();
+ }
+ PackInserter ins = ((FileRepository) repo).getObjectDatabase().newPackInserter();
+ ins.checkExisting(false);
+ return ins;
+ }
}
diff --git a/java/com/google/gerrit/server/patch/PatchScriptBuilder.java b/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
index 6f3e055..b4f7251 100644
--- a/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
+++ b/java/com/google/gerrit/server/patch/PatchScriptBuilder.java
@@ -37,6 +37,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Optional;
import org.eclipse.jgit.diff.Edit;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
@@ -172,6 +173,8 @@
}
}
+ correctForDifferencesInNewlineAtEnd();
+
if (comments != null) {
ensureCommentsVisible(comments);
}
@@ -277,6 +280,43 @@
}
}
+ private void correctForDifferencesInNewlineAtEnd() {
+ // a.src.size() is the size ignoring a newline at the end whereas a.size() considers it.
+ int aSize = a.src.size();
+ int bSize = b.src.size();
+
+ Optional<Edit> lastEdit = getLast(edits);
+ if (isNewlineAtEndDeleted()) {
+ Optional<Edit> lastLineEdit = lastEdit.filter(edit -> edit.getEndA() == aSize);
+ if (lastLineEdit.isPresent()) {
+ lastLineEdit.get().extendA();
+ } else {
+ Edit newlineEdit = new Edit(aSize, aSize + 1, bSize, bSize);
+ edits.add(newlineEdit);
+ }
+ } else if (isNewlineAtEndAdded()) {
+ Optional<Edit> lastLineEdit = lastEdit.filter(edit -> edit.getEndB() == bSize);
+ if (lastLineEdit.isPresent()) {
+ lastLineEdit.get().extendB();
+ } else {
+ Edit newlineEdit = new Edit(aSize, aSize, bSize, bSize + 1);
+ edits.add(newlineEdit);
+ }
+ }
+ }
+
+ private static <T> Optional<T> getLast(List<T> list) {
+ return list.isEmpty() ? Optional.empty() : Optional.ofNullable(list.get(list.size() - 1));
+ }
+
+ private boolean isNewlineAtEndDeleted() {
+ return !a.src.isMissingNewlineAtEnd() && b.src.isMissingNewlineAtEnd();
+ }
+
+ private boolean isNewlineAtEndAdded() {
+ return a.src.isMissingNewlineAtEnd() && !b.src.isMissingNewlineAtEnd();
+ }
+
private void ensureCommentsVisible(CommentDetail comments) {
if (comments.getCommentsA().isEmpty() && comments.getCommentsB().isEmpty()) {
// No comments, no additional dummy edits are required.
@@ -396,14 +436,14 @@
for (EditList.Hunk hunk : list.getHunks()) {
while (hunk.next()) {
if (hunk.isContextLine()) {
- final String lineA = a.src.getString(hunk.getCurA());
+ String lineA = a.getSourceLine(hunk.getCurA());
a.dst.addLine(hunk.getCurA(), lineA);
if (ignoredWhitespace) {
// If we ignored whitespace in some form, also get the line
// from b when it does not exactly match the line from a.
//
- final String lineB = b.src.getString(hunk.getCurB());
+ String lineB = b.getSourceLine(hunk.getCurB());
if (!lineA.equals(lineB)) {
b.dst.addLine(hunk.getCurB(), lineB);
}
@@ -437,11 +477,22 @@
final SparseFileContent dst = new SparseFileContent();
int size() {
- return src != null ? src.size() : 0;
+ if (src == null) {
+ return 0;
+ }
+ if (src.isMissingNewlineAtEnd()) {
+ return src.size();
+ }
+ return src.size() + 1;
}
- void addLine(int line) {
- dst.addLine(line, src.getString(line));
+ void addLine(int lineNumber) {
+ String lineContent = getSourceLine(lineNumber);
+ dst.addLine(lineNumber, lineContent);
+ }
+
+ String getSourceLine(int lineNumber) {
+ return lineNumber >= src.size() ? "" : src.getString(lineNumber);
}
void resolve(Side other, ObjectId within) throws IOException {
diff --git a/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java b/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
index bf68026..136b4ae 100644
--- a/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
+++ b/java/com/google/gerrit/server/permissions/DefaultPermissionBackend.java
@@ -33,7 +33,6 @@
import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.account.CapabilityCollection;
import com.google.gerrit.server.cache.PerThreadCache;
-import com.google.gerrit.server.permissions.PermissionBackendCondition.WithUser;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
index 3b88080..1e5b3c8 100644
--- a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
+++ b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
@@ -299,9 +299,14 @@
Map<Change.Id, Branch.NameKey> visibleChanges = new HashMap<>();
for (ChangeData cd : changeCache.getChangeData(db.get(), project)) {
ChangeNotes notes = changeNotesFactory.createFromIndexedChange(cd.change());
- if (projectState.statePermitsRead()
- && permissionBackendForProject.indexedChange(cd, notes).test(ChangePermission.READ)) {
+ if (!projectState.statePermitsRead()) {
+ continue;
+ }
+ try {
+ permissionBackendForProject.indexedChange(cd, notes).check(ChangePermission.READ);
visibleChanges.put(cd.getId(), cd.change().getDest());
+ } catch (AuthException e) {
+ // Do nothing.
}
}
return visibleChanges;
@@ -334,11 +339,16 @@
"Failed to load change %s in %s", r.id(), projectState.getName());
return null;
}
+
+ if (!projectState.statePermitsRead()) {
+ return null;
+ }
+
try {
- if (projectState.statePermitsRead()
- && permissionBackendForProject.change(r.notes()).test(ChangePermission.READ)) {
- return r.notes();
- }
+ permissionBackendForProject.change(r.notes()).check(ChangePermission.READ);
+ return r.notes();
+ } catch (AuthException e) {
+ // Skip.
} catch (PermissionBackendException e) {
logger.atSevere().withCause(e).log(
"Failed to check permission for %s in %s", r.id(), projectState.getName());
diff --git a/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java b/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
index 61a7ef2..79eccbb 100644
--- a/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
+++ b/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
@@ -68,6 +68,9 @@
.put(
BooleanProjectConfig.REJECT_EMPTY_COMMIT,
new Mapper(i -> i.rejectEmptyCommit, (i, v) -> i.rejectEmptyCommit = v))
+ .put(
+ BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT,
+ new Mapper(i -> i.workInProgressByDefault, (i, v) -> i.workInProgressByDefault = v))
.build();
static {
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index d42b652..e3638b6 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -41,6 +41,7 @@
import com.google.gerrit.common.errors.InvalidNameException;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ProjectState;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
import com.google.gerrit.reviewdb.client.Branch;
@@ -55,7 +56,6 @@
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
-import com.google.gerrit.server.mail.Address;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -402,10 +402,6 @@
return mimeTypes;
}
- public GroupReference resolve(AccountGroup group) {
- return resolve(GroupReference.forGroup(group));
- }
-
public GroupReference resolve(GroupReference group) {
GroupReference groupRef = groupList.resolve(group);
if (groupRef != null
@@ -503,6 +499,9 @@
if (p.getDescription() == null) {
p.setDescription("");
}
+ if (revision != null) {
+ p.setConfigRefState(revision.toObjectId().name());
+ }
if (rc.getStringList(ACCESS, null, KEY_INHERIT_FROM).length > 1) {
// The config must not contain more than one parent to inherit from
diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java
index 87dbcfc..e36ca4f 100644
--- a/java/com/google/gerrit/server/project/ProjectState.java
+++ b/java/com/google/gerrit/server/project/ProjectState.java
@@ -62,6 +62,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Ref;
@@ -538,7 +539,11 @@
}
public ProjectData toProjectData() {
- return new ProjectData(getProject(), parents().transform(s -> s.getProject().getNameKey()));
+ ProjectData project = null;
+ for (ProjectState state : treeInOrder()) {
+ project = new ProjectData(state.getProject(), Optional.ofNullable(project));
+ }
+ return project;
}
private String readFile(Path p) throws IOException {
diff --git a/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java b/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
index e7ffd5e..41d53a2 100644
--- a/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
@@ -19,6 +19,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.errors.NotSignedInException;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.Schema;
import com.google.gerrit.index.query.LimitPredicate;
@@ -120,12 +121,17 @@
public Predicate<AccountState> cansee(String change)
throws QueryParseException, OrmException, PermissionBackendException {
ChangeNotes changeNotes = args.changeFinder.findOne(change);
- if (changeNotes == null
- || !args.permissionBackend
- .user(args.getUser())
- .database(args.db)
- .change(changeNotes)
- .test(ChangePermission.READ)) {
+ if (changeNotes == null) {
+ throw error(String.format("change %s not found", change));
+ }
+
+ try {
+ args.permissionBackend
+ .user(args.getUser())
+ .database(args.db)
+ .change(changeNotes)
+ .check(ChangePermission.READ);
+ } catch (AuthException e) {
throw error(String.format("change %s not found", change));
}
@@ -218,7 +224,12 @@
}
private boolean canSeeSecondaryEmails() throws PermissionBackendException, QueryParseException {
- return args.permissionBackend.user(args.getUser()).test(GlobalPermission.MODIFY_ACCOUNT);
+ try {
+ args.permissionBackend.user(args.getUser()).check(GlobalPermission.MODIFY_ACCOUNT);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
private boolean checkedCanSeeSecondaryEmails() {
diff --git a/java/com/google/gerrit/server/query/account/CanSeeChangePredicate.java b/java/com/google/gerrit/server/query/account/CanSeeChangePredicate.java
index b008092..fb3549c 100644
--- a/java/com/google/gerrit/server/query/account/CanSeeChangePredicate.java
+++ b/java/com/google/gerrit/server/query/account/CanSeeChangePredicate.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.account;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.index.query.PostFilterPredicate;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountState;
@@ -40,13 +41,16 @@
@Override
public boolean match(AccountState accountState) throws OrmException {
try {
- return permissionBackend
+ permissionBackend
.absentUser(accountState.getAccount().getId())
.database(db)
.change(changeNotes)
- .test(ChangePermission.READ);
+ .check(ChangePermission.READ);
+ return true;
} catch (PermissionBackendException e) {
throw new OrmException("Failed to check if account can see change", e);
+ } catch (AuthException e) {
+ return false;
}
}
diff --git a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
index 346ac8e..27baef1 100644
--- a/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
+++ b/java/com/google/gerrit/server/query/change/ChangeIsVisibleToPredicate.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.query.change;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.index.query.IsVisibleToPredicate;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -83,13 +84,12 @@
throw new OrmException("unable to read project state", e);
}
- boolean visible;
PermissionBackend.WithUser withUser =
user.isIdentifiedUser()
? permissionBackend.absentUser(user.getAccountId())
: permissionBackend.user(anonymousUserProvider.get());
try {
- visible = withUser.indexedChange(cd, notes).database(db).test(ChangePermission.READ);
+ withUser.indexedChange(cd, notes).database(db).check(ChangePermission.READ);
} catch (PermissionBackendException e) {
Throwable cause = e.getCause();
if (cause instanceof RepositoryNotFoundException) {
@@ -98,12 +98,12 @@
return false;
}
throw new OrmException("unable to check permissions on change " + cd.getId(), e);
+ } catch (AuthException e) {
+ return false;
}
- if (visible) {
- cd.cacheVisibleTo(user);
- return true;
- }
- return false;
+
+ cd.cacheVisibleTo(user);
+ return true;
}
@Override
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 3113504..5855404 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -39,6 +39,7 @@
import com.google.gerrit.index.query.QueryBuilder;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryRequiresAuthException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Branch;
@@ -65,7 +66,6 @@
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
diff --git a/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java b/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
index 19fd4a1..54e22f3 100644
--- a/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
+++ b/java/com/google/gerrit/server/query/change/EqualsLabelPredicate.java
@@ -16,6 +16,7 @@
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
@@ -125,10 +126,13 @@
PermissionBackend.ForChange perm =
permissionBackend.absentUser(approver).database(dbProvider).change(cd);
ProjectState projectState = projectCache.checkedGet(cd.project());
- return projectState != null
- && projectState.statePermitsRead()
- && perm.test(ChangePermission.READ);
- } catch (PermissionBackendException | IOException e) {
+ if (projectState == null || !projectState.statePermitsRead()) {
+ return false;
+ }
+
+ perm.check(ChangePermission.READ);
+ return true;
+ } catch (PermissionBackendException | IOException | AuthException e) {
return false;
}
}
diff --git a/java/com/google/gerrit/server/query/change/ReviewerByEmailPredicate.java b/java/com/google/gerrit/server/query/change/ReviewerByEmailPredicate.java
index f4e979c..667c630 100644
--- a/java/com/google/gerrit/server/query/change/ReviewerByEmailPredicate.java
+++ b/java/com/google/gerrit/server/query/change/ReviewerByEmailPredicate.java
@@ -17,8 +17,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.server.index.change.ChangeField;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gwtorm.server.OrmException;
diff --git a/java/com/google/gerrit/server/query/project/ProjectPredicates.java b/java/com/google/gerrit/server/query/project/ProjectPredicates.java
index b4f56d4..2e406aa 100644
--- a/java/com/google/gerrit/server/query/project/ProjectPredicates.java
+++ b/java/com/google/gerrit/server/query/project/ProjectPredicates.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.project;
+import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.index.project.ProjectData;
import com.google.gerrit.index.project.ProjectField;
import com.google.gerrit.index.project.ProjectPredicate;
@@ -34,5 +35,9 @@
return new ProjectPredicate(ProjectField.DESCRIPTION, description);
}
+ public static Predicate<ProjectData> state(ProjectState state) {
+ return new ProjectPredicate(ProjectField.STATE, state.name());
+ }
+
private ProjectPredicates() {}
}
diff --git a/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java b/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
index be7ea22..872d3e0 100644
--- a/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/project/ProjectQueryBuilder.java
@@ -17,6 +17,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
+import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.index.project.ProjectData;
import com.google.gerrit.index.query.LimitPredicate;
import com.google.gerrit.index.query.Predicate;
@@ -60,6 +61,23 @@
return ProjectPredicates.description(description);
}
+ @Operator
+ public Predicate<ProjectData> state(String state) throws QueryParseException {
+ if (Strings.isNullOrEmpty(state)) {
+ throw error("state operator requires a value");
+ }
+ ProjectState parsedState;
+ try {
+ parsedState = ProjectState.valueOf(state.replace('-', '_').toUpperCase());
+ } catch (IllegalArgumentException e) {
+ throw error("state operator must be either 'active' or 'read-only'");
+ }
+ if (parsedState == ProjectState.HIDDEN) {
+ throw error("state operator must be either 'active' or 'read-only'");
+ }
+ return ProjectPredicates.state(parsedState);
+ }
+
@Override
protected Predicate<ProjectData> defaultField(String query) throws QueryParseException {
// Adapt the capacity of this list when adding more default predicates.
diff --git a/java/com/google/gerrit/server/restapi/BUILD b/java/com/google/gerrit/server/restapi/BUILD
index ff114fae..1207c71 100644
--- a/java/com/google/gerrit/server/restapi/BUILD
+++ b/java/com/google/gerrit/server/restapi/BUILD
@@ -12,6 +12,7 @@
"//java/com/google/gerrit/index",
"//java/com/google/gerrit/index:query_exception",
"//java/com/google/gerrit/index/project",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/prettify:server",
"//java/com/google/gerrit/reviewdb:server",
diff --git a/java/com/google/gerrit/server/restapi/account/Capabilities.java b/java/com/google/gerrit/server/restapi/account/Capabilities.java
index ec16e2b..85f9da0 100644
--- a/java/com/google/gerrit/server/restapi/account/Capabilities.java
+++ b/java/com/google/gerrit/server/restapi/account/Capabilities.java
@@ -71,10 +71,12 @@
}
GlobalOrPluginPermission perm = parse(id);
- if (permissionBackend.user(target).test(perm)) {
+ try {
+ permissionBackend.user(target).check(perm);
return new AccountResource.Capability(target, globalOrPluginPermissionName(perm));
+ } catch (AuthException e) {
+ throw new ResourceNotFoundException(id);
}
- throw new ResourceNotFoundException(id);
}
private GlobalOrPluginPermission parse(IdString id) throws ResourceNotFoundException {
diff --git a/java/com/google/gerrit/server/restapi/account/CreateAccount.java b/java/com/google/gerrit/server/restapi/account/CreateAccount.java
index b1581abb..3e43082 100644
--- a/java/com/google/gerrit/server/restapi/account/CreateAccount.java
+++ b/java/com/google/gerrit/server/restapi/account/CreateAccount.java
@@ -49,6 +49,7 @@
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
import com.google.gerrit.server.mail.send.OutgoingEmailValidator;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.GroupsCollection;
import com.google.gerrit.server.ssh.SshKeyCache;
import com.google.gwtorm.server.OrmException;
@@ -100,13 +101,13 @@
public Response<AccountInfo> apply(
TopLevelResource rsrc, IdString id, @Nullable AccountInput input)
throws BadRequestException, ResourceConflictException, UnprocessableEntityException,
- OrmException, IOException, ConfigInvalidException {
+ OrmException, IOException, ConfigInvalidException, PermissionBackendException {
return apply(id, input != null ? input : new AccountInput());
}
public Response<AccountInfo> apply(IdString id, AccountInput input)
throws BadRequestException, ResourceConflictException, UnprocessableEntityException,
- OrmException, IOException, ConfigInvalidException {
+ OrmException, IOException, ConfigInvalidException, PermissionBackendException {
String username = id.get();
if (input.username != null && !username.equals(input.username)) {
throw new BadRequestException("username must match URL");
diff --git a/java/com/google/gerrit/server/restapi/account/GetAccount.java b/java/com/google/gerrit/server/restapi/account/GetAccount.java
index 0d8e25e..6b73ae3b 100644
--- a/java/com/google/gerrit/server/restapi/account/GetAccount.java
+++ b/java/com/google/gerrit/server/restapi/account/GetAccount.java
@@ -18,6 +18,7 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.account.AccountResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -32,7 +33,7 @@
}
@Override
- public AccountInfo apply(AccountResource rsrc) throws OrmException {
+ public AccountInfo apply(AccountResource rsrc) throws OrmException, PermissionBackendException {
AccountLoader loader = infoFactory.create(true);
AccountInfo info = loader.get(rsrc.getUser().getAccountId());
loader.fill();
diff --git a/java/com/google/gerrit/server/restapi/account/GetAgreements.java b/java/com/google/gerrit/server/restapi/account/GetAgreements.java
index dced4d7..edcbc35 100644
--- a/java/com/google/gerrit/server/restapi/account/GetAgreements.java
+++ b/java/com/google/gerrit/server/restapi/account/GetAgreements.java
@@ -28,6 +28,7 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.restapi.config.AgreementJson;
import com.google.inject.Inject;
@@ -60,7 +61,8 @@
}
@Override
- public List<AgreementInfo> apply(AccountResource resource) throws RestApiException {
+ public List<AgreementInfo> apply(AccountResource resource)
+ throws RestApiException, PermissionBackendException {
if (!agreementsEnabled) {
throw new MethodNotAllowedException("contributor agreements disabled");
}
diff --git a/java/com/google/gerrit/server/restapi/account/GetDetail.java b/java/com/google/gerrit/server/restapi/account/GetDetail.java
index c8f99b3..97d0c60 100644
--- a/java/com/google/gerrit/server/restapi/account/GetDetail.java
+++ b/java/com/google/gerrit/server/restapi/account/GetDetail.java
@@ -14,38 +14,25 @@
package com.google.gerrit.server.restapi.account;
-import com.google.common.collect.Sets;
import com.google.gerrit.extensions.common.AccountDetailInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountDirectory.FillOptions;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.InternalAccountDirectory;
-import com.google.gerrit.server.permissions.GlobalPermission;
-import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.Set;
@Singleton
public class GetDetail implements RestReadView<AccountResource> {
- private final Provider<CurrentUser> self;
- private final PermissionBackend permissionBackend;
private final InternalAccountDirectory directory;
@Inject
- public GetDetail(
- Provider<CurrentUser> self,
- PermissionBackend permissionBackend,
- InternalAccountDirectory directory) {
- this.self = self;
- this.permissionBackend = permissionBackend;
+ public GetDetail(InternalAccountDirectory directory) {
this.directory = directory;
}
@@ -56,13 +43,7 @@
AccountDetailInfo info = new AccountDetailInfo(a.getId().get());
info.registeredOn = a.getRegisteredOn();
info.inactive = !a.isActive() ? true : null;
- Set<FillOptions> fillOptions =
- self.get().hasSameAccountId(rsrc.getUser())
- || permissionBackend.currentUser().test(GlobalPermission.MODIFY_ACCOUNT)
- ? EnumSet.allOf(FillOptions.class)
- : Sets.difference(
- EnumSet.allOf(FillOptions.class), EnumSet.of(FillOptions.SECONDARY_EMAILS));
- directory.fillAccountInfo(Collections.singleton(info), fillOptions);
+ directory.fillAccountInfo(Collections.singleton(info), EnumSet.allOf(FillOptions.class));
return info;
}
}
diff --git a/java/com/google/gerrit/server/restapi/account/GetDiffPreferences.java b/java/com/google/gerrit/server/restapi/account/GetDiffPreferences.java
index a8d14f6..40201a8 100644
--- a/java/com/google/gerrit/server/restapi/account/GetDiffPreferences.java
+++ b/java/com/google/gerrit/server/restapi/account/GetDiffPreferences.java
@@ -50,7 +50,7 @@
@Override
public DiffPreferencesInfo apply(AccountResource rsrc)
throws RestApiException, ConfigInvalidException, IOException, PermissionBackendException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
}
diff --git a/java/com/google/gerrit/server/restapi/account/GetEmails.java b/java/com/google/gerrit/server/restapi/account/GetEmails.java
index 63d042c..85262ee 100644
--- a/java/com/google/gerrit/server/restapi/account/GetEmails.java
+++ b/java/com/google/gerrit/server/restapi/account/GetEmails.java
@@ -44,7 +44,7 @@
@Override
public List<EmailInfo> apply(AccountResource rsrc)
throws AuthException, PermissionBackendException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
}
diff --git a/java/com/google/gerrit/server/restapi/account/GetGroups.java b/java/com/google/gerrit/server/restapi/account/GetGroups.java
index 486a151..ad9746e 100644
--- a/java/com/google/gerrit/server/restapi/account/GetGroups.java
+++ b/java/com/google/gerrit/server/restapi/account/GetGroups.java
@@ -22,6 +22,7 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.GroupControl;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.GroupJson;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -42,7 +43,8 @@
}
@Override
- public List<GroupInfo> apply(AccountResource resource) throws OrmException {
+ public List<GroupInfo> apply(AccountResource resource)
+ throws OrmException, PermissionBackendException {
IdentifiedUser user = resource.getUser();
Account.Id userId = user.getAccountId();
Set<AccountGroup.UUID> knownGroups = user.getEffectiveGroups().getKnownGroups();
diff --git a/java/com/google/gerrit/server/restapi/account/PutPreferred.java b/java/com/google/gerrit/server/restapi/account/PutPreferred.java
index 51d28ed..a828987 100644
--- a/java/com/google/gerrit/server/restapi/account/PutPreferred.java
+++ b/java/com/google/gerrit/server/restapi/account/PutPreferred.java
@@ -71,7 +71,7 @@
public Response<String> apply(AccountResource.Email rsrc, Input input)
throws RestApiException, OrmException, IOException, PermissionBackendException,
ConfigInvalidException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
}
return apply(rsrc.getUser(), rsrc.getEmail());
diff --git a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
index 8784d23..2c0512c 100644
--- a/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
+++ b/java/com/google/gerrit/server/restapi/account/QueryAccounts.java
@@ -19,6 +19,7 @@
import com.google.gerrit.extensions.client.ListAccountsOption;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.AccountVisibility;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -171,9 +172,15 @@
fillOptions.addAll(AccountLoader.DETAILED_OPTIONS);
fillOptions.add(FillOptions.EMAIL);
- if (modifyAccountCapabilityChecked
- || permissionBackend.currentUser().test(GlobalPermission.MODIFY_ACCOUNT)) {
+ if (modifyAccountCapabilityChecked) {
fillOptions.add(FillOptions.SECONDARY_EMAILS);
+ } else {
+ try {
+ permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
+ fillOptions.add(FillOptions.SECONDARY_EMAILS);
+ } catch (AuthException e) {
+ // Do nothing.
+ }
}
}
accountLoader = accountLoaderFactory.create(fillOptions);
diff --git a/java/com/google/gerrit/server/restapi/account/SetDiffPreferences.java b/java/com/google/gerrit/server/restapi/account/SetDiffPreferences.java
index 6aa88de..f4fa354 100644
--- a/java/com/google/gerrit/server/restapi/account/SetDiffPreferences.java
+++ b/java/com/google/gerrit/server/restapi/account/SetDiffPreferences.java
@@ -57,7 +57,7 @@
public DiffPreferencesInfo apply(AccountResource rsrc, DiffPreferencesInfo input)
throws RestApiException, ConfigInvalidException, RepositoryNotFoundException, IOException,
PermissionBackendException, OrmException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
}
diff --git a/java/com/google/gerrit/server/restapi/account/SetEditPreferences.java b/java/com/google/gerrit/server/restapi/account/SetEditPreferences.java
index dad6e0f..4e3f1d5 100644
--- a/java/com/google/gerrit/server/restapi/account/SetEditPreferences.java
+++ b/java/com/google/gerrit/server/restapi/account/SetEditPreferences.java
@@ -58,7 +58,7 @@
public EditPreferencesInfo apply(AccountResource rsrc, EditPreferencesInfo input)
throws RestApiException, RepositoryNotFoundException, IOException, ConfigInvalidException,
PermissionBackendException, OrmException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
}
diff --git a/java/com/google/gerrit/server/restapi/account/SetPreferences.java b/java/com/google/gerrit/server/restapi/account/SetPreferences.java
index 11ecfdb..fccdabe 100644
--- a/java/com/google/gerrit/server/restapi/account/SetPreferences.java
+++ b/java/com/google/gerrit/server/restapi/account/SetPreferences.java
@@ -63,7 +63,7 @@
public GeneralPreferencesInfo apply(AccountResource rsrc, GeneralPreferencesInfo input)
throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException,
OrmException {
- if (self.get() != rsrc.getUser()) {
+ if (!self.get().hasSameAccountId(rsrc.getUser())) {
permissionBackend.currentUser().check(GlobalPermission.MODIFY_ACCOUNT);
}
diff --git a/java/com/google/gerrit/server/restapi/account/StarredChanges.java b/java/com/google/gerrit/server/restapi/account/StarredChanges.java
index e049539..5d4044c5 100644
--- a/java/com/google/gerrit/server/restapi/account/StarredChanges.java
+++ b/java/com/google/gerrit/server/restapi/account/StarredChanges.java
@@ -89,7 +89,7 @@
return new RestReadView<AccountResource>() {
@Override
public Object apply(AccountResource self)
- throws BadRequestException, AuthException, OrmException {
+ throws BadRequestException, AuthException, OrmException, PermissionBackendException {
QueryChanges query = changes.list();
query.addQuery("starredby:" + self.getUser().getAccountId().get());
return query.apply(TopLevelResource.INSTANCE);
diff --git a/java/com/google/gerrit/server/restapi/account/Stars.java b/java/com/google/gerrit/server/restapi/account/Stars.java
index fb809ee..5c4c4d5 100644
--- a/java/com/google/gerrit/server/restapi/account/Stars.java
+++ b/java/com/google/gerrit/server/restapi/account/Stars.java
@@ -99,7 +99,7 @@
@Override
@SuppressWarnings("unchecked")
public List<ChangeInfo> apply(AccountResource rsrc)
- throws BadRequestException, AuthException, OrmException {
+ throws BadRequestException, AuthException, OrmException, PermissionBackendException {
if (!self.get().hasSameAccountId(rsrc.getUser())) {
throw new AuthException("not allowed to list stars of another account");
}
diff --git a/java/com/google/gerrit/server/restapi/change/ChangeMessages.java b/java/com/google/gerrit/server/restapi/change/ChangeMessages.java
index 251c66d..25fc350 100644
--- a/java/com/google/gerrit/server/restapi/change/ChangeMessages.java
+++ b/java/com/google/gerrit/server/restapi/change/ChangeMessages.java
@@ -22,6 +22,7 @@
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.change.ChangeMessageResource;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -51,7 +52,7 @@
@Override
public ChangeMessageResource parse(ChangeResource parent, IdString id)
- throws OrmException, ResourceNotFoundException {
+ throws OrmException, ResourceNotFoundException, PermissionBackendException {
String uuid = id.get();
List<ChangeMessageInfo> changeMessages = listChangeMessages.apply(parent);
diff --git a/java/com/google/gerrit/server/restapi/change/CommentJson.java b/java/com/google/gerrit/server/restapi/change/CommentJson.java
index e90ce18..e92abe1 100644
--- a/java/com/google/gerrit/server/restapi/change/CommentJson.java
+++ b/java/com/google/gerrit/server/restapi/change/CommentJson.java
@@ -32,6 +32,7 @@
import com.google.gerrit.reviewdb.client.FixSuggestion;
import com.google.gerrit.reviewdb.client.RobotComment;
import com.google.gerrit.server.account.AccountLoader;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
@@ -70,7 +71,7 @@
}
private abstract class BaseCommentFormatter<F extends Comment, T extends CommentInfo> {
- public T format(F comment) {
+ public T format(F comment) throws PermissionBackendException {
AccountLoader loader = fillAccounts ? accountLoaderFactory.create(true) : null;
T info = toInfo(comment, loader);
if (loader != null) {
@@ -79,7 +80,7 @@
return info;
}
- public Map<String, List<T>> format(Iterable<F> comments) {
+ public Map<String, List<T>> format(Iterable<F> comments) throws PermissionBackendException {
AccountLoader loader = fillAccounts ? accountLoaderFactory.create(true) : null;
Map<String, List<T>> out = new TreeMap<>();
@@ -105,7 +106,7 @@
return out;
}
- public List<T> formatAsList(Iterable<F> comments) {
+ public List<T> formatAsList(Iterable<F> comments) throws PermissionBackendException {
AccountLoader loader = fillAccounts ? accountLoaderFactory.create(true) : null;
List<T> out =
diff --git a/java/com/google/gerrit/server/restapi/change/CreateChange.java b/java/com/google/gerrit/server/restapi/change/CreateChange.java
index 0dcbeb0..a04716d 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateChange.java
@@ -266,6 +266,12 @@
AccountState accountState = me.state();
GeneralPreferencesInfo info = accountState.getGeneralPreferences();
+ boolean isWorkInProgress =
+ input.workInProgress == null
+ ? rsrc.getProjectState().is(BooleanProjectConfig.WORK_IN_PROGRESS_BY_DEFAULT)
+ || MoreObjects.firstNonNull(info.workInProgressByDefault, false)
+ : input.workInProgress;
+
// Add a Change-Id line if there isn't already one
String commitMessage = subject;
if (ChangeIdUtil.indexOfChangeId(commitMessage, "\n") == -1) {
@@ -309,7 +315,7 @@
}
ins.setTopic(topic);
ins.setPrivate(isPrivate);
- ins.setWorkInProgress(input.workInProgress != null && input.workInProgress);
+ ins.setWorkInProgress(isWorkInProgress);
ins.setGroups(groups);
ins.setNotify(input.notify);
ins.setAccountsToNotify(notifyUtil.resolveAccounts(input.notifyDetails));
diff --git a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
index be689ca..c22fb1e 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
@@ -35,6 +35,7 @@
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -75,7 +76,7 @@
@Override
protected Response<CommentInfo> applyImpl(
BatchUpdate.Factory updateFactory, RevisionResource rsrc, DraftInput in)
- throws RestApiException, UpdateException, OrmException {
+ throws RestApiException, UpdateException, OrmException, PermissionBackendException {
if (Strings.isNullOrEmpty(in.path)) {
throw new BadRequestException("path must be non-empty");
} else if (in.message == null || in.message.trim().isEmpty()) {
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteReviewerByEmailOp.java b/java/com/google/gerrit/server/restapi/change/DeleteReviewerByEmailOp.java
index fac1003..3231d16 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteReviewerByEmailOp.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteReviewerByEmailOp.java
@@ -17,12 +17,12 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.api.changes.DeleteReviewerInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.NotifyUtil;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.send.DeleteReviewerSender;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
diff --git a/java/com/google/gerrit/server/restapi/change/GetAssignee.java b/java/com/google/gerrit/server/restapi/change/GetAssignee.java
index f78fae2..e95f8d8 100644
--- a/java/com/google/gerrit/server/restapi/change/GetAssignee.java
+++ b/java/com/google/gerrit/server/restapi/change/GetAssignee.java
@@ -20,6 +20,7 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -35,7 +36,8 @@
}
@Override
- public Response<AccountInfo> apply(ChangeResource rsrc) throws OrmException {
+ public Response<AccountInfo> apply(ChangeResource rsrc)
+ throws OrmException, PermissionBackendException {
Optional<Account.Id> assignee = Optional.ofNullable(rsrc.getChange().getAssignee());
if (assignee.isPresent()) {
return Response.ok(accountLoaderFactory.create(true).fillOne(assignee.get()));
diff --git a/java/com/google/gerrit/server/restapi/change/GetComment.java b/java/com/google/gerrit/server/restapi/change/GetComment.java
index b8db6a5..d067dff 100644
--- a/java/com/google/gerrit/server/restapi/change/GetComment.java
+++ b/java/com/google/gerrit/server/restapi/change/GetComment.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.change.CommentResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -33,7 +34,7 @@
}
@Override
- public CommentInfo apply(CommentResource rsrc) throws OrmException {
+ public CommentInfo apply(CommentResource rsrc) throws OrmException, PermissionBackendException {
return commentJson.get().newCommentFormatter().format(rsrc.getComment());
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/GetDraftComment.java b/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
index 787c93e..6049607 100644
--- a/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/GetDraftComment.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.change.DraftCommentResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -33,7 +34,8 @@
}
@Override
- public CommentInfo apply(DraftCommentResource rsrc) throws OrmException {
+ public CommentInfo apply(DraftCommentResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson.get().newCommentFormatter().format(rsrc.getComment());
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/GetPastAssignees.java b/java/com/google/gerrit/server/restapi/change/GetPastAssignees.java
index 354558b..279cfe3 100644
--- a/java/com/google/gerrit/server/restapi/change/GetPastAssignees.java
+++ b/java/com/google/gerrit/server/restapi/change/GetPastAssignees.java
@@ -22,6 +22,7 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -39,7 +40,8 @@
}
@Override
- public Response<List<AccountInfo>> apply(ChangeResource rsrc) throws OrmException {
+ public Response<List<AccountInfo>> apply(ChangeResource rsrc)
+ throws OrmException, PermissionBackendException {
Set<Account.Id> pastAssignees = rsrc.getNotes().load().getPastAssignees();
if (pastAssignees == null) {
diff --git a/java/com/google/gerrit/server/restapi/change/GetRobotComment.java b/java/com/google/gerrit/server/restapi/change/GetRobotComment.java
index bd1f66a..0197068 100644
--- a/java/com/google/gerrit/server/restapi/change/GetRobotComment.java
+++ b/java/com/google/gerrit/server/restapi/change/GetRobotComment.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.common.RobotCommentInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.change.RobotCommentResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -33,7 +34,8 @@
}
@Override
- public RobotCommentInfo apply(RobotCommentResource rsrc) throws OrmException {
+ public RobotCommentInfo apply(RobotCommentResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson.get().newRobotCommentFormatter().format(rsrc.getComment());
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
index 37dc207..40f4642 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
@@ -20,6 +20,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -49,7 +50,7 @@
@Override
public Map<String, List<CommentInfo>> apply(ChangeResource rsrc)
- throws AuthException, OrmException {
+ throws AuthException, OrmException, PermissionBackendException {
ChangeData cd = changeDataFactory.create(db.get(), rsrc.getNotes());
return commentJson
.get()
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
index d7a102a..a524f6d 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
@@ -21,6 +21,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -50,7 +51,7 @@
@Override
public Map<String, List<CommentInfo>> apply(ChangeResource rsrc)
- throws AuthException, OrmException {
+ throws AuthException, OrmException, PermissionBackendException {
if (!rsrc.getUser().isIdentifiedUser()) {
throw new AuthException("Authentication required");
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java b/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
index cf76ef1..39c12f7 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
@@ -23,6 +23,7 @@
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -47,7 +48,8 @@
}
@Override
- public List<ChangeMessageInfo> apply(ChangeResource resource) throws OrmException {
+ public List<ChangeMessageInfo> apply(ChangeResource resource)
+ throws OrmException, PermissionBackendException {
List<ChangeMessage> messages =
changeMessagesUtil.byChange(dbProvider.get(), resource.getNotes());
List<ChangeMessageInfo> messageInfos =
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeRobotComments.java b/java/com/google/gerrit/server/restapi/change/ListChangeRobotComments.java
index dd8de6f..dc92ced 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeRobotComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeRobotComments.java
@@ -20,6 +20,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -47,7 +48,7 @@
@Override
public Map<String, List<RobotCommentInfo>> apply(ChangeResource rsrc)
- throws AuthException, OrmException {
+ throws AuthException, OrmException, PermissionBackendException {
ChangeData cd = changeDataFactory.create(db.get(), rsrc.getNotes());
return commentJson
.get()
diff --git a/java/com/google/gerrit/server/restapi/change/ListReviewers.java b/java/com/google/gerrit/server/restapi/change/ListReviewers.java
index 750e74f..46bb33f 100644
--- a/java/com/google/gerrit/server/restapi/change/ListReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/ListReviewers.java
@@ -16,12 +16,12 @@
import com.google.gerrit.extensions.api.changes.ReviewerInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ReviewerResource;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
index b7dc553..db8ef0c 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
@@ -20,6 +20,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -51,7 +52,8 @@
}
@Override
- public Map<String, List<CommentInfo>> apply(RevisionResource rsrc) throws OrmException {
+ public Map<String, List<CommentInfo>> apply(RevisionResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson
.get()
.setFillAccounts(includeAuthorInfo())
@@ -59,7 +61,8 @@
.format(listComments(rsrc));
}
- public List<CommentInfo> getComments(RevisionResource rsrc) throws OrmException {
+ public List<CommentInfo> getComments(RevisionResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson
.get()
.setFillAccounts(includeAuthorInfo())
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java b/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
index d0630b7..32c4ea3 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
@@ -17,12 +17,12 @@
import com.google.gerrit.extensions.api.changes.ReviewerInfo;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.RevisionResource;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/restapi/change/ListRobotComments.java b/java/com/google/gerrit/server/restapi/change/ListRobotComments.java
index 61219d3..66138ab 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRobotComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRobotComments.java
@@ -20,6 +20,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -42,7 +43,8 @@
}
@Override
- public Map<String, List<RobotCommentInfo>> apply(RevisionResource rsrc) throws OrmException {
+ public Map<String, List<RobotCommentInfo>> apply(RevisionResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson
.get()
.setFillAccounts(true)
@@ -50,7 +52,8 @@
.format(listComments(rsrc));
}
- public List<RobotCommentInfo> getComments(RevisionResource rsrc) throws OrmException {
+ public List<RobotCommentInfo> getComments(RevisionResource rsrc)
+ throws OrmException, PermissionBackendException {
return commentJson
.get()
.setFillAccounts(true)
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index 622e06b..20f3d8a 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -64,6 +64,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.extensions.restapi.Url;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -94,7 +95,6 @@
import com.google.gerrit.server.change.WorkInProgressOp;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.CommentAdded;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
diff --git a/java/com/google/gerrit/server/restapi/change/PostReviewers.java b/java/com/google/gerrit/server/restapi/change/PostReviewers.java
index 87e6163..0df86d1 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReviewers.java
@@ -37,6 +37,7 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
@@ -56,7 +57,6 @@
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.send.OutgoingEmailValidator;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
@@ -349,14 +349,17 @@
NotifyHandling notify,
ListMultimap<RecipientType, Account.Id> accountsToNotify)
throws PermissionBackendException {
- if (!permissionBackend
- .user(anonymousProvider.get())
- .change(rsrc.getNotes())
- .database(dbProvider)
- .test(ChangePermission.READ)) {
+ try {
+ permissionBackend
+ .user(anonymousProvider.get())
+ .change(rsrc.getNotes())
+ .database(dbProvider)
+ .check(ChangePermission.READ);
+ } catch (AuthException e) {
return fail(
reviewer, MessageFormat.format(ChangeMessages.get().reviewerCantSeeChange, reviewer));
}
+
if (!migration.readChanges()) {
// addByEmail depends on NoteDb.
return fail(
diff --git a/java/com/google/gerrit/server/restapi/change/PostReviewersOp.java b/java/com/google/gerrit/server/restapi/change/PostReviewersOp.java
index 3cb6136..08b66aa 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReviewersOp.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReviewersOp.java
@@ -30,6 +30,7 @@
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -42,7 +43,6 @@
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.extensions.events.ReviewerAdded;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.mail.send.AddReviewerSender;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
diff --git a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
index e6ede34..76ef106 100644
--- a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
@@ -34,6 +34,7 @@
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -80,7 +81,7 @@
@Override
protected Response<CommentInfo> applyImpl(
BatchUpdate.Factory updateFactory, DraftCommentResource rsrc, DraftInput in)
- throws RestApiException, UpdateException, OrmException {
+ throws RestApiException, UpdateException, OrmException, PermissionBackendException {
if (in == null || in.message == null || in.message.trim().isEmpty()) {
return delete.applyImpl(updateFactory, rsrc, null);
} else if (in.id != null && !rsrc.getId().equals(in.id)) {
diff --git a/java/com/google/gerrit/server/restapi/change/QueryChanges.java b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
index 1c9e420..b53c4e6 100644
--- a/java/com/google/gerrit/server/restapi/change/QueryChanges.java
+++ b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
@@ -28,6 +28,7 @@
import com.google.gerrit.index.query.QueryRequiresAuthException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.server.change.ChangeJson;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
@@ -104,7 +105,7 @@
@Override
public List<?> apply(TopLevelResource rsrc)
- throws BadRequestException, AuthException, OrmException {
+ throws BadRequestException, AuthException, OrmException, PermissionBackendException {
List<List<ChangeInfo>> out;
try {
out = query();
@@ -117,7 +118,8 @@
return out.size() == 1 ? out.get(0) : out;
}
- private List<List<ChangeInfo>> query() throws OrmException, QueryParseException {
+ private List<List<ChangeInfo>> query()
+ throws OrmException, QueryParseException, PermissionBackendException {
if (imp.isDisabled()) {
throw new QueryParseException("query disabled");
}
diff --git a/java/com/google/gerrit/server/restapi/change/ReviewerJson.java b/java/com/google/gerrit/server/restapi/change/ReviewerJson.java
index c891a65..29c5649 100644
--- a/java/com/google/gerrit/server/restapi/change/ReviewerJson.java
+++ b/java/com/google/gerrit/server/restapi/change/ReviewerJson.java
@@ -22,6 +22,7 @@
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.extensions.api.changes.ReviewerInfo;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
@@ -132,10 +133,15 @@
for (SubmitRecord.Label label : rec.labels) {
String name = label.label;
LabelType type = labelTypes.byLabel(name);
- if (!out.approvals.containsKey(name)
- && type != null
- && perm.test(new LabelPermission(type))) {
+ if (out.approvals.containsKey(name) || type == null) {
+ continue;
+ }
+
+ try {
+ perm.check(new LabelPermission(type));
out.approvals.put(name, formatValue((short) 0));
+ } catch (AuthException e) {
+ // Do nothing.
}
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/Reviewers.java b/java/com/google/gerrit/server/restapi/change/Reviewers.java
index a4cfbd2..f0aef13 100644
--- a/java/com/google/gerrit/server/restapi/change/Reviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/Reviewers.java
@@ -21,12 +21,12 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ReviewerResource;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.restapi.account.AccountsCollection;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java b/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
index 779ee5a..57ff0a3 100644
--- a/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
+++ b/java/com/google/gerrit/server/restapi/change/ReviewersUtil.java
@@ -22,6 +22,7 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GroupReference;
@@ -48,8 +49,6 @@
import com.google.gerrit.server.index.account.AccountField;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.permissions.GlobalPermission;
-import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectState;
@@ -129,7 +128,6 @@
private final IndexConfig indexConfig;
private final AccountControl.Factory accountControlFactory;
private final Provider<CurrentUser> self;
- private final PermissionBackend permissionBackend;
@Inject
ReviewersUtil(
@@ -142,8 +140,7 @@
AccountIndexCollection accountIndexes,
IndexConfig indexConfig,
AccountControl.Factory accountControlFactory,
- Provider<CurrentUser> self,
- PermissionBackend permissionBackend) {
+ Provider<CurrentUser> self) {
this.accountLoaderFactory = accountLoaderFactory;
this.accountQueryBuilder = accountQueryBuilder;
this.groupBackend = groupBackend;
@@ -154,7 +151,6 @@
this.indexConfig = indexConfig;
this.accountControlFactory = accountControlFactory;
this.self = self;
- this.permissionBackend = permissionBackend;
}
public interface VisibilityControl {
@@ -301,10 +297,7 @@
private List<SuggestedReviewerInfo> loadAccounts(List<Account.Id> accountIds)
throws PermissionBackendException {
Set<FillOptions> fillOptions =
- permissionBackend.currentUser().test(GlobalPermission.MODIFY_ACCOUNT)
- ? EnumSet.of(FillOptions.SECONDARY_EMAILS)
- : EnumSet.noneOf(FillOptions.class);
- fillOptions.addAll(AccountLoader.DETAILED_OPTIONS);
+ Sets.union(AccountLoader.DETAILED_OPTIONS, EnumSet.of(FillOptions.SECONDARY_EMAILS));
AccountLoader accountLoader = accountLoaderFactory.create(fillOptions);
try (Timer0.Context ctx = metrics.loadAccountsLatency.start()) {
diff --git a/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java b/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
index 7cf30e2..b9b7a4f 100644
--- a/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
@@ -22,12 +22,12 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.RevisionResource;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.restapi.account.AccountsCollection;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/server/restapi/change/SetReadyForReview.java b/java/com/google/gerrit/server/restapi/change/SetReadyForReview.java
index 8fe5612..faf946f 100644
--- a/java/com/google/gerrit/server/restapi/change/SetReadyForReview.java
+++ b/java/com/google/gerrit/server/restapi/change/SetReadyForReview.java
@@ -65,16 +65,28 @@
protected Response<?> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
- Change change = rsrc.getChange();
- if (!rsrc.isUserOwner()
- && !permissionBackend.currentUser().test(GlobalPermission.ADMINISTRATE_SERVER)
- && !permissionBackend
- .currentUser()
- .project(rsrc.getProject())
- .test(ProjectPermission.WRITE_CONFIG)) {
- throw new AuthException("not allowed to set ready for review");
+ if (!rsrc.isUserOwner()) {
+ boolean hasAdministrateServerPermission = false;
+ try {
+ permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
+ hasAdministrateServerPermission = true;
+ } catch (AuthException e) {
+ // Skip.
+ }
+
+ if (!hasAdministrateServerPermission) {
+ try {
+ permissionBackend
+ .currentUser()
+ .project(rsrc.getProject())
+ .check(ProjectPermission.WRITE_CONFIG);
+ } catch (AuthException exp) {
+ throw new AuthException("not allowed to set ready for review");
+ }
+ }
}
+ Change change = rsrc.getChange();
if (change.getStatus() != Status.NEW) {
throw new ResourceConflictException("change is " + ChangeUtil.status(change));
}
diff --git a/java/com/google/gerrit/server/restapi/change/SetWorkInProgress.java b/java/com/google/gerrit/server/restapi/change/SetWorkInProgress.java
index 9524903..1f9d81f 100644
--- a/java/com/google/gerrit/server/restapi/change/SetWorkInProgress.java
+++ b/java/com/google/gerrit/server/restapi/change/SetWorkInProgress.java
@@ -65,17 +65,28 @@
protected Response<?> applyImpl(
BatchUpdate.Factory updateFactory, ChangeResource rsrc, Input input)
throws RestApiException, UpdateException, PermissionBackendException {
- Change change = rsrc.getChange();
+ if (!rsrc.isUserOwner()) {
+ boolean hasAdministrateServerPermission = false;
+ try {
+ permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
+ hasAdministrateServerPermission = true;
+ } catch (AuthException e) {
+ // Skip.
+ }
- if (!rsrc.isUserOwner()
- && !permissionBackend.currentUser().test(GlobalPermission.ADMINISTRATE_SERVER)
- && !permissionBackend
- .currentUser()
- .project(rsrc.getProject())
- .test(ProjectPermission.WRITE_CONFIG)) {
- throw new AuthException("not allowed to set work in progress");
+ if (!hasAdministrateServerPermission) {
+ try {
+ permissionBackend
+ .currentUser()
+ .project(rsrc.getProject())
+ .check(ProjectPermission.WRITE_CONFIG);
+ } catch (AuthException exp) {
+ throw new AuthException("not allowed to set work in progress");
+ }
+ }
}
+ Change change = rsrc.getChange();
if (change.getStatus() != Status.NEW) {
throw new ResourceConflictException("change is " + ChangeUtil.status(change));
}
diff --git a/java/com/google/gerrit/server/restapi/change/TestSubmitRule.java b/java/com/google/gerrit/server/restapi/change/TestSubmitRule.java
index 2a18612..cdd7426 100644
--- a/java/com/google/gerrit/server/restapi/change/TestSubmitRule.java
+++ b/java/com/google/gerrit/server/restapi/change/TestSubmitRule.java
@@ -25,6 +25,7 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
@@ -63,7 +64,7 @@
@Override
public List<Record> apply(RevisionResource rsrc, TestSubmitRuleInput input)
- throws AuthException, OrmException {
+ throws AuthException, OrmException, PermissionBackendException {
if (input == null) {
input = new TestSubmitRuleInput();
}
diff --git a/java/com/google/gerrit/server/restapi/config/AgreementJson.java b/java/com/google/gerrit/server/restapi/config/AgreementJson.java
index 548bc03..02e5f68 100644
--- a/java/com/google/gerrit/server/restapi/config/AgreementJson.java
+++ b/java/com/google/gerrit/server/restapi/config/AgreementJson.java
@@ -23,6 +23,7 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.GroupJson;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -48,7 +49,7 @@
this.groupJson = groupJson;
}
- public AgreementInfo format(ContributorAgreement ca) {
+ public AgreementInfo format(ContributorAgreement ca) throws PermissionBackendException {
AgreementInfo info = new AgreementInfo();
info.name = ca.getName();
info.description = ca.getDescription();
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index 70db0f9..b7931bd 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -59,6 +59,7 @@
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.restapi.change.AllowedFormats;
import com.google.gerrit.server.submit.MergeSuperSet;
@@ -148,7 +149,8 @@
}
@Override
- public ServerInfo apply(ConfigResource rsrc) throws MalformedURLException {
+ public ServerInfo apply(ConfigResource rsrc)
+ throws MalformedURLException, PermissionBackendException {
ServerInfo info = new ServerInfo();
info.accounts = getAccountsInfo(accountVisibilityProvider);
info.auth = getAuthInfo(authConfig, realm);
@@ -178,7 +180,7 @@
return info;
}
- private AuthInfo getAuthInfo(AuthConfig cfg, Realm realm) {
+ private AuthInfo getAuthInfo(AuthConfig cfg, Realm realm) throws PermissionBackendException {
AuthInfo info = new AuthInfo();
info.authType = cfg.getAuthType();
info.useContributorAgreements = toBoolean(cfg.isUseContributorAgreements());
diff --git a/java/com/google/gerrit/server/restapi/config/ListTasks.java b/java/com/google/gerrit/server/restapi/config/ListTasks.java
index d700028..7b69831 100644
--- a/java/com/google/gerrit/server/restapi/config/ListTasks.java
+++ b/java/com/google/gerrit/server/restapi/config/ListTasks.java
@@ -23,13 +23,13 @@
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.WorkQueue.ProjectTask;
import com.google.gerrit.server.git.WorkQueue.Task;
+import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.util.IdGenerator;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -133,7 +133,7 @@
public String queueName;
public TaskInfo(Task<?> task) {
- this.id = IdGenerator.format(task.getTaskId());
+ this.id = HexFormat.fromInt(task.getTaskId());
this.state = task.getState();
this.startTime = new Timestamp(task.getStartTime().getTime());
this.delay = task.getDelay(TimeUnit.MILLISECONDS);
diff --git a/java/com/google/gerrit/server/restapi/group/AddMembers.java b/java/com/google/gerrit/server/restapi/group/AddMembers.java
index 3e2d1e7..733b6bd 100644
--- a/java/com/google/gerrit/server/restapi/group/AddMembers.java
+++ b/java/com/google/gerrit/server/restapi/group/AddMembers.java
@@ -46,6 +46,7 @@
import com.google.gerrit.server.group.MemberResource;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.account.AccountsCollection;
import com.google.gerrit.server.restapi.group.AddMembers.Input;
import com.google.gwtorm.server.OrmException;
@@ -116,7 +117,8 @@
@Override
public List<AccountInfo> apply(GroupResource resource, Input input)
throws AuthException, NotInternalGroupException, UnprocessableEntityException, OrmException,
- IOException, ConfigInvalidException, ResourceNotFoundException {
+ IOException, ConfigInvalidException, ResourceNotFoundException,
+ PermissionBackendException {
GroupDescription.Internal internalGroup =
resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
input = Input.init(input);
@@ -203,7 +205,8 @@
}
}
- private List<AccountInfo> toAccountInfoList(Set<Account.Id> accountIds) {
+ private List<AccountInfo> toAccountInfoList(Set<Account.Id> accountIds)
+ throws PermissionBackendException {
List<AccountInfo> result = new ArrayList<>();
AccountLoader loader = infoFactory.create(true);
for (Account.Id accId : accountIds) {
@@ -224,7 +227,7 @@
@Override
public AccountInfo apply(GroupResource resource, IdString id, Input input)
throws AuthException, MethodNotAllowedException, ResourceNotFoundException, OrmException,
- IOException, ConfigInvalidException {
+ IOException, ConfigInvalidException, PermissionBackendException {
AddMembers.Input in = new AddMembers.Input();
in._oneMember = id.get();
try {
@@ -249,7 +252,8 @@
}
@Override
- public AccountInfo apply(MemberResource resource, Input input) throws OrmException {
+ public AccountInfo apply(MemberResource resource, Input input)
+ throws OrmException, PermissionBackendException {
// Do nothing, the user is already a member.
return get.apply(resource);
}
diff --git a/java/com/google/gerrit/server/restapi/group/AddSubgroups.java b/java/com/google/gerrit/server/restapi/group/AddSubgroups.java
index 21b6981..1474e19 100644
--- a/java/com/google/gerrit/server/restapi/group/AddSubgroups.java
+++ b/java/com/google/gerrit/server/restapi/group/AddSubgroups.java
@@ -36,6 +36,7 @@
import com.google.gerrit.server.group.SubgroupResource;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.AddSubgroups.Input;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -92,7 +93,8 @@
@Override
public List<GroupInfo> apply(GroupResource resource, Input input)
throws NotInternalGroupException, AuthException, UnprocessableEntityException, OrmException,
- ResourceNotFoundException, IOException, ConfigInvalidException {
+ ResourceNotFoundException, IOException, ConfigInvalidException,
+ PermissionBackendException {
GroupDescription.Internal group =
resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
input = Input.init(input);
@@ -141,7 +143,7 @@
@Override
public GroupInfo apply(GroupResource resource, IdString id, Input input)
throws AuthException, MethodNotAllowedException, ResourceNotFoundException, OrmException,
- IOException, ConfigInvalidException {
+ IOException, ConfigInvalidException, PermissionBackendException {
AddSubgroups.Input in = new AddSubgroups.Input();
in.groups = ImmutableList.of(id.get());
try {
@@ -166,7 +168,8 @@
}
@Override
- public GroupInfo apply(SubgroupResource resource, Input input) throws OrmException {
+ public GroupInfo apply(SubgroupResource resource, Input input)
+ throws OrmException, PermissionBackendException {
// Do nothing, the group is already included.
return get.get().apply(resource);
}
diff --git a/java/com/google/gerrit/server/restapi/group/CreateGroup.java b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
index 6ecb5aa..1014a99 100644
--- a/java/com/google/gerrit/server/restapi/group/CreateGroup.java
+++ b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
@@ -50,6 +50,7 @@
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupCreation;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.validators.GroupCreationValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gwtorm.server.OrmDuplicateKeyException;
@@ -121,7 +122,7 @@
public GroupInfo apply(TopLevelResource resource, IdString id, GroupInput input)
throws AuthException, BadRequestException, UnprocessableEntityException,
ResourceConflictException, OrmException, IOException, ConfigInvalidException,
- ResourceNotFoundException {
+ ResourceNotFoundException, PermissionBackendException {
String name = id.get();
if (input == null) {
input = new GroupInput();
diff --git a/java/com/google/gerrit/server/restapi/group/GetAuditLog.java b/java/com/google/gerrit/server/restapi/group/GetAuditLog.java
index eb66a37..7af4284 100644
--- a/java/com/google/gerrit/server/restapi/group/GetAuditLog.java
+++ b/java/com/google/gerrit/server/restapi/group/GetAuditLog.java
@@ -35,6 +35,7 @@
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.InternalGroupDescription;
import com.google.gerrit.server.group.db.Groups;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -77,7 +78,7 @@
@Override
public List<? extends GroupAuditEventInfo> apply(GroupResource rsrc)
throws AuthException, NotInternalGroupException, OrmException, IOException,
- ConfigInvalidException {
+ ConfigInvalidException, PermissionBackendException {
GroupDescription.Internal group =
rsrc.asInternalGroup().orElseThrow(NotInternalGroupException::new);
if (!rsrc.getControl().isOwner()) {
diff --git a/java/com/google/gerrit/server/restapi/group/GetDetail.java b/java/com/google/gerrit/server/restapi/group/GetDetail.java
index e7b240e..75d1e34 100644
--- a/java/com/google/gerrit/server/restapi/group/GetDetail.java
+++ b/java/com/google/gerrit/server/restapi/group/GetDetail.java
@@ -18,6 +18,7 @@
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -32,7 +33,7 @@
}
@Override
- public GroupInfo apply(GroupResource rsrc) throws OrmException {
+ public GroupInfo apply(GroupResource rsrc) throws OrmException, PermissionBackendException {
return json.format(rsrc);
}
}
diff --git a/java/com/google/gerrit/server/restapi/group/GetGroup.java b/java/com/google/gerrit/server/restapi/group/GetGroup.java
index 81057fd..c6cddb6 100644
--- a/java/com/google/gerrit/server/restapi/group/GetGroup.java
+++ b/java/com/google/gerrit/server/restapi/group/GetGroup.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -31,7 +32,7 @@
}
@Override
- public GroupInfo apply(GroupResource resource) throws OrmException {
+ public GroupInfo apply(GroupResource resource) throws OrmException, PermissionBackendException {
return json.format(resource.getGroup());
}
}
diff --git a/java/com/google/gerrit/server/restapi/group/GetMember.java b/java/com/google/gerrit/server/restapi/group/GetMember.java
index db33785..95063de 100644
--- a/java/com/google/gerrit/server/restapi/group/GetMember.java
+++ b/java/com/google/gerrit/server/restapi/group/GetMember.java
@@ -18,6 +18,7 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.group.MemberResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -32,7 +33,7 @@
}
@Override
- public AccountInfo apply(MemberResource rsrc) throws OrmException {
+ public AccountInfo apply(MemberResource rsrc) throws OrmException, PermissionBackendException {
AccountLoader loader = infoFactory.create(true);
AccountInfo info = loader.get(rsrc.getMember().getAccountId());
loader.fill();
diff --git a/java/com/google/gerrit/server/restapi/group/GetOwner.java b/java/com/google/gerrit/server/restapi/group/GetOwner.java
index be19a24..0906ce6 100644
--- a/java/com/google/gerrit/server/restapi/group/GetOwner.java
+++ b/java/com/google/gerrit/server/restapi/group/GetOwner.java
@@ -21,6 +21,7 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -39,7 +40,8 @@
@Override
public GroupInfo apply(GroupResource resource)
- throws NotInternalGroupException, ResourceNotFoundException, OrmException {
+ throws NotInternalGroupException, ResourceNotFoundException, OrmException,
+ PermissionBackendException {
GroupDescription.Internal group =
resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
try {
diff --git a/java/com/google/gerrit/server/restapi/group/GetSubgroup.java b/java/com/google/gerrit/server/restapi/group/GetSubgroup.java
index 98e6ce5..16e2739 100644
--- a/java/com/google/gerrit/server/restapi/group/GetSubgroup.java
+++ b/java/com/google/gerrit/server/restapi/group/GetSubgroup.java
@@ -17,6 +17,7 @@
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.group.SubgroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -31,7 +32,7 @@
}
@Override
- public GroupInfo apply(SubgroupResource rsrc) throws OrmException {
+ public GroupInfo apply(SubgroupResource rsrc) throws OrmException, PermissionBackendException {
return json.format(rsrc.getMemberDescription());
}
}
diff --git a/java/com/google/gerrit/server/restapi/group/GroupJson.java b/java/com/google/gerrit/server/restapi/group/GroupJson.java
index 3c7799b..a51fad2 100644
--- a/java/com/google/gerrit/server/restapi/group/GroupJson.java
+++ b/java/com/google/gerrit/server/restapi/group/GroupJson.java
@@ -28,6 +28,7 @@
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -75,17 +76,18 @@
return this;
}
- public GroupInfo format(GroupResource rsrc) throws OrmException {
+ public GroupInfo format(GroupResource rsrc) throws OrmException, PermissionBackendException {
return createGroupInfo(rsrc.getGroup(), rsrc::getControl);
}
- public GroupInfo format(GroupDescription.Basic group) throws OrmException {
+ public GroupInfo format(GroupDescription.Basic group)
+ throws OrmException, PermissionBackendException {
return createGroupInfo(group, Suppliers.memoize(() -> groupControlFactory.controlFor(group)));
}
private GroupInfo createGroupInfo(
GroupDescription.Basic group, Supplier<GroupControl> groupControlSupplier)
- throws OrmException {
+ throws OrmException, PermissionBackendException {
GroupInfo info = createBasicGroupInfo(group);
if (group instanceof GroupDescription.Internal) {
@@ -108,7 +110,7 @@
GroupInfo info,
GroupDescription.Internal internalGroup,
Supplier<GroupControl> groupControlSupplier)
- throws OrmException {
+ throws OrmException, PermissionBackendException {
info.description = Strings.emptyToNull(internalGroup.getDescription());
info.groupId = internalGroup.getId().get();
diff --git a/java/com/google/gerrit/server/restapi/group/ListGroups.java b/java/com/google/gerrit/server/restapi/group/ListGroups.java
index c7f1d5e..bae5eff 100644
--- a/java/com/google/gerrit/server/restapi/group/ListGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/ListGroups.java
@@ -41,6 +41,7 @@
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.InternalGroupDescription;
import com.google.gerrit.server.group.db.Groups;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.restapi.account.GetGroups;
import com.google.gwtorm.server.OrmException;
@@ -246,7 +247,8 @@
@Override
public SortedMap<String, GroupInfo> apply(TopLevelResource resource)
- throws OrmException, RestApiException, IOException, ConfigInvalidException {
+ throws OrmException, RestApiException, IOException, ConfigInvalidException,
+ PermissionBackendException {
SortedMap<String, GroupInfo> output = new TreeMap<>();
for (GroupInfo info : get()) {
output.put(MoreObjects.firstNonNull(info.name, "Group " + Url.decode(info.id)), info);
@@ -256,7 +258,8 @@
}
public List<GroupInfo> get()
- throws OrmException, RestApiException, IOException, ConfigInvalidException {
+ throws OrmException, RestApiException, IOException, ConfigInvalidException,
+ PermissionBackendException {
if (!Strings.isNullOrEmpty(suggest)) {
return suggestGroups();
}
@@ -280,7 +283,8 @@
return getAllGroups();
}
- private List<GroupInfo> getAllGroups() throws OrmException, IOException, ConfigInvalidException {
+ private List<GroupInfo> getAllGroups()
+ throws OrmException, IOException, ConfigInvalidException, PermissionBackendException {
Pattern pattern = getRegexPattern();
Stream<GroupDescription.Internal> existingGroups =
getAllExistingGroups()
@@ -312,7 +316,8 @@
return groups.getAllGroupReferences();
}
- private List<GroupInfo> suggestGroups() throws OrmException, BadRequestException {
+ private List<GroupInfo> suggestGroups()
+ throws OrmException, BadRequestException, PermissionBackendException {
if (conflictingSuggestParameters()) {
throw new BadRequestException(
"You should only have no more than one --project and -n with --suggest");
@@ -368,7 +373,7 @@
}
private List<GroupInfo> filterGroupsOwnedBy(Predicate<GroupDescription.Internal> filter)
- throws OrmException, IOException, ConfigInvalidException {
+ throws OrmException, IOException, ConfigInvalidException, PermissionBackendException {
Pattern pattern = getRegexPattern();
Stream<? extends GroupDescription.Internal> foundGroups =
groups
@@ -396,13 +401,14 @@
}
private List<GroupInfo> getGroupsOwnedBy(String id)
- throws OrmException, RestApiException, IOException, ConfigInvalidException {
+ throws OrmException, RestApiException, IOException, ConfigInvalidException,
+ PermissionBackendException {
String uuid = groupsCollection.parse(id).getGroupUUID().get();
return filterGroupsOwnedBy(group -> group.getOwnerGroupUUID().get().equals(uuid));
}
private List<GroupInfo> getGroupsOwnedBy(IdentifiedUser user)
- throws OrmException, IOException, ConfigInvalidException {
+ throws OrmException, IOException, ConfigInvalidException, PermissionBackendException {
return filterGroupsOwnedBy(group -> isOwner(user, group));
}
diff --git a/java/com/google/gerrit/server/restapi/group/ListMembers.java b/java/com/google/gerrit/server/restapi/group/ListMembers.java
index 634e029..4742644 100644
--- a/java/com/google/gerrit/server/restapi/group/ListMembers.java
+++ b/java/com/google/gerrit/server/restapi/group/ListMembers.java
@@ -32,6 +32,7 @@
import com.google.gerrit.server.group.GroupResource;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.InternalGroupDescription;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.util.ArrayList;
@@ -66,7 +67,7 @@
@Override
public List<AccountInfo> apply(GroupResource resource)
- throws NotInternalGroupException, OrmException {
+ throws NotInternalGroupException, OrmException, PermissionBackendException {
GroupDescription.Internal group =
resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
if (recursive) {
@@ -75,7 +76,8 @@
return getDirectMembers(group, resource.getControl());
}
- public List<AccountInfo> getTransitiveMembers(AccountGroup.UUID groupUuid) {
+ public List<AccountInfo> getTransitiveMembers(AccountGroup.UUID groupUuid)
+ throws PermissionBackendException {
Optional<InternalGroup> group = groupCache.get(groupUuid);
if (group.isPresent()) {
InternalGroupDescription internalGroup = new InternalGroupDescription(group.get());
@@ -86,7 +88,8 @@
}
private List<AccountInfo> getTransitiveMembers(
- GroupDescription.Internal group, GroupControl groupControl) {
+ GroupDescription.Internal group, GroupControl groupControl)
+ throws PermissionBackendException {
checkSameGroup(group, groupControl);
Set<Account.Id> members =
getTransitiveMemberIds(
@@ -94,19 +97,21 @@
return toAccountInfos(members);
}
- public List<AccountInfo> getDirectMembers(InternalGroup group) {
+ public List<AccountInfo> getDirectMembers(InternalGroup group) throws PermissionBackendException {
InternalGroupDescription internalGroup = new InternalGroupDescription(group);
return getDirectMembers(internalGroup, groupControlFactory.controlFor(internalGroup));
}
public List<AccountInfo> getDirectMembers(
- GroupDescription.Internal group, GroupControl groupControl) {
+ GroupDescription.Internal group, GroupControl groupControl)
+ throws PermissionBackendException {
checkSameGroup(group, groupControl);
Set<Account.Id> directMembers = getDirectMemberIds(group, groupControl);
return toAccountInfos(directMembers);
}
- private List<AccountInfo> toAccountInfos(Set<Account.Id> members) {
+ private List<AccountInfo> toAccountInfos(Set<Account.Id> members)
+ throws PermissionBackendException {
List<AccountInfo> memberInfos = new ArrayList<>(members.size());
for (Account.Id member : members) {
memberInfos.add(accountLoader.get(member));
diff --git a/java/com/google/gerrit/server/restapi/group/ListSubgroups.java b/java/com/google/gerrit/server/restapi/group/ListSubgroups.java
index 835a613..97a260e 100644
--- a/java/com/google/gerrit/server/restapi/group/ListSubgroups.java
+++ b/java/com/google/gerrit/server/restapi/group/ListSubgroups.java
@@ -24,6 +24,7 @@
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -46,7 +47,8 @@
}
@Override
- public List<GroupInfo> apply(GroupResource rsrc) throws NotInternalGroupException, OrmException {
+ public List<GroupInfo> apply(GroupResource rsrc)
+ throws NotInternalGroupException, OrmException, PermissionBackendException {
GroupDescription.Internal group =
rsrc.asInternalGroup().orElseThrow(NotInternalGroupException::new);
@@ -54,7 +56,8 @@
}
public List<GroupInfo> getDirectSubgroups(
- GroupDescription.Internal group, GroupControl groupControl) throws OrmException {
+ GroupDescription.Internal group, GroupControl groupControl)
+ throws OrmException, PermissionBackendException {
boolean ownerOfParent = groupControl.isOwner();
List<GroupInfo> included = new ArrayList<>();
for (AccountGroup.UUID subgroupUuid : group.getSubgroups()) {
diff --git a/java/com/google/gerrit/server/restapi/group/PutOwner.java b/java/com/google/gerrit/server/restapi/group/PutOwner.java
index 5e7563e..56f856d 100644
--- a/java/com/google/gerrit/server/restapi/group/PutOwner.java
+++ b/java/com/google/gerrit/server/restapi/group/PutOwner.java
@@ -29,6 +29,7 @@
import com.google.gerrit.server.group.GroupResource;
import com.google.gerrit.server.group.db.GroupsUpdate;
import com.google.gerrit.server.group.db.InternalGroupUpdate;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -56,7 +57,7 @@
public GroupInfo apply(GroupResource resource, OwnerInput input)
throws ResourceNotFoundException, NotInternalGroupException, AuthException,
BadRequestException, UnprocessableEntityException, OrmException, IOException,
- ConfigInvalidException {
+ ConfigInvalidException, PermissionBackendException {
GroupDescription.Internal internalGroup =
resource.asInternalGroup().orElseThrow(NotInternalGroupException::new);
if (!resource.getControl().isOwner()) {
diff --git a/java/com/google/gerrit/server/restapi/group/QueryGroups.java b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
index c262003..fa9285d 100644
--- a/java/com/google/gerrit/server/restapi/group/QueryGroups.java
+++ b/java/com/google/gerrit/server/restapi/group/QueryGroups.java
@@ -26,6 +26,7 @@
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.group.InternalGroupDescription;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.group.GroupQueryBuilder;
import com.google.gerrit.server.query.group.GroupQueryProcessor;
import com.google.gwtorm.server.OrmException;
@@ -94,7 +95,8 @@
@Override
public List<GroupInfo> apply(TopLevelResource resource)
- throws BadRequestException, MethodNotAllowedException, OrmException {
+ throws BadRequestException, MethodNotAllowedException, OrmException,
+ PermissionBackendException {
if (Strings.isNullOrEmpty(query)) {
throw new BadRequestException("missing query field");
}
diff --git a/java/com/google/gerrit/server/restapi/project/GarbageCollect.java b/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
index ea1620b..3b7f3e3 100644
--- a/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
+++ b/java/com/google/gerrit/server/restapi/project/GarbageCollect.java
@@ -29,9 +29,9 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
+import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.server.project.ProjectResource;
import com.google.gerrit.server.restapi.project.GarbageCollect.Input;
-import com.google.gerrit.server.util.IdGenerator;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -98,7 +98,7 @@
WorkQueue.Task<Void> task = (WorkQueue.Task<Void>) workQueue.getDefaultQueue().submit(job);
String location =
- canonicalUrl.get() + "a/config/server/tasks/" + IdGenerator.format(task.getTaskId());
+ canonicalUrl.get() + "a/config/server/tasks/" + HexFormat.fromInt(task.getTaskId());
return Response.accepted(location);
}
diff --git a/java/com/google/gerrit/server/restapi/project/GetAccess.java b/java/com/google/gerrit/server/restapi/project/GetAccess.java
index 6a50c2f..d545f92 100644
--- a/java/com/google/gerrit/server/restapi/project/GetAccess.java
+++ b/java/com/google/gerrit/server/restapi/project/GetAccess.java
@@ -237,11 +237,15 @@
}
}
- if (info.ownerOf.isEmpty()
- && permissionBackend.currentUser().test(GlobalPermission.ADMINISTRATE_SERVER)) {
- // Special case: If the section list is empty, this project has no current
- // access control information. Fall back to site administrators.
- info.ownerOf.add(AccessSection.ALL);
+ if (info.ownerOf.isEmpty()) {
+ try {
+ permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
+ // Special case: If the section list is empty, this project has no current
+ // access control information. Fall back to site administrators.
+ info.ownerOf.add(AccessSection.ALL);
+ } catch (AuthException e) {
+ // Do nothing.
+ }
}
if (config.getRevision() != null) {
diff --git a/java/com/google/gerrit/server/restapi/project/ListBranches.java b/java/com/google/gerrit/server/restapi/project/ListBranches.java
index 0bdf979..bf4a547 100644
--- a/java/com/google/gerrit/server/restapi/project/ListBranches.java
+++ b/java/com/google/gerrit/server/restapi/project/ListBranches.java
@@ -24,6 +24,7 @@
import com.google.gerrit.extensions.common.ActionInfo;
import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
@@ -185,9 +186,13 @@
// showing the resolved value, show the name it references.
//
String target = ref.getTarget().getName();
- if (!perm.ref(target).test(RefPermission.READ)) {
+
+ try {
+ perm.ref(target).check(RefPermission.READ);
+ } catch (AuthException e) {
continue;
}
+
if (target.startsWith(Constants.R_HEADS)) {
target = target.substring(Constants.R_HEADS.length());
}
@@ -212,10 +217,13 @@
continue;
}
- if (perm.ref(ref.getName()).test(RefPermission.READ)) {
+ try {
+ perm.ref(ref.getName()).check(RefPermission.READ);
branches.add(
createBranchInfo(
perm.ref(ref.getName()), ref, rsrc.getProjectState(), rsrc.getUser(), targets));
+ } catch (AuthException e) {
+ // Do nothing.
}
}
Collections.sort(branches, new BranchComparator());
diff --git a/java/com/google/gerrit/server/restapi/project/ListDashboards.java b/java/com/google/gerrit/server/restapi/project/ListDashboards.java
index 4ff46cf..06dbdb0 100644
--- a/java/com/google/gerrit/server/restapi/project/ListDashboards.java
+++ b/java/com/google/gerrit/server/restapi/project/ListDashboards.java
@@ -18,6 +18,7 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.api.projects.DashboardInfo;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Project;
@@ -104,8 +105,15 @@
RevWalk rw = new RevWalk(git)) {
List<DashboardInfo> all = new ArrayList<>();
for (Ref ref : git.getRefDatabase().getRefsByPrefix(REFS_DASHBOARDS)) {
- if (perm.ref(ref.getName()).test(RefPermission.READ) && state.statePermitsRead()) {
+ if (!state.statePermitsRead()) {
+ continue;
+ }
+
+ try {
+ perm.ref(ref.getName()).check(RefPermission.READ);
all.addAll(scanDashboards(state.getProject(), git, rw, ref, project, setDefault));
+ } catch (AuthException e) {
+ // Do nothing.
}
}
return all;
diff --git a/java/com/google/gerrit/server/schema/Schema_169.java b/java/com/google/gerrit/server/schema/Schema_169.java
index 11aebdd..2779d47 100644
--- a/java/com/google/gerrit/server/schema/Schema_169.java
+++ b/java/com/google/gerrit/server/schema/Schema_169.java
@@ -18,32 +18,25 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.CommentJsonMigrator;
+import com.google.gerrit.server.notedb.CommentJsonMigrator.ProjectMigrationResult;
import com.google.gerrit.server.notedb.MutableNotesMigration;
import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.update.RefUpdateUtil;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.SortedSet;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.PackInserter;
-import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.revwalk.RevWalk;
/** Migrate NoteDb inline comments to JSON format. */
public class Schema_169 extends SchemaVersion {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- private final AllUsersName allUsers;
private final CommentJsonMigrator migrator;
private final GitRepositoryManager repoManager;
private final NotesMigration notesMigration;
@@ -51,12 +44,10 @@
@Inject
Schema_169(
Provider<Schema_168> prior,
- AllUsersName allUsers,
CommentJsonMigrator migrator,
GitRepositoryManager repoManager,
@GerritServerConfig Config config) {
super(prior);
- this.allUsers = allUsers;
this.migrator = migrator;
this.repoManager = repoManager;
this.notesMigration = MutableNotesMigration.fromConfig(config);
@@ -67,15 +58,6 @@
migrateData(ui);
}
- private static ObjectInserter newPackInserter(Repository repo) {
- if (!(repo instanceof FileRepository)) {
- return repo.newObjectInserter();
- }
- PackInserter ins = ((FileRepository) repo).getObjectDatabase().newPackInserter();
- ins.checkExisting(false);
- return ins;
- }
-
@VisibleForTesting
protected void migrateData(UpdateUI ui) throws OrmException {
// If the migration hasn't started, no need to look for non-JSON
@@ -89,28 +71,16 @@
pm.beginTask("Migrating projects", projects.size());
int skipped = 0;
for (Project.NameKey project : projects) {
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo);
- ObjectInserter ins = newPackInserter(repo)) {
- BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
- bru.setAllowNonFastForwards(true);
- ok &= migrator.migrateChanges(project, repo, rw, ins, bru);
- if (project.equals(allUsers)) {
- ok &= migrator.migrateDrafts(allUsers, repo, rw, ins, bru);
- }
-
- if (!bru.getCommands().isEmpty()) {
- ins.flush();
- RefUpdateUtil.executeChecked(bru, rw);
- } else {
- skipped++;
- }
+ try (Repository repo = repoManager.openRepository(project)) {
+ ProjectMigrationResult progress = migrator.migrateProject(project, repo, false);
+ skipped += progress.skipped;
} catch (IOException e) {
- logger.atWarning().log("Error migrating project " + project, e);
ok = false;
+ logger.atWarning().log("Error migrating project " + project, e);
}
pm.update(1);
}
+
pm.endTask();
ui.message(
"Skipped " + skipped + " project" + (skipped == 1 ? "" : "s") + " with no legacy comments");
diff --git a/java/com/google/gerrit/server/submit/GitModules.java b/java/com/google/gerrit/server/submit/GitModules.java
index 00ce7b2..bf56fd5 100644
--- a/java/com/google/gerrit/server/submit/GitModules.java
+++ b/java/com/google/gerrit/server/submit/GitModules.java
@@ -23,7 +23,7 @@
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
import com.google.gerrit.server.util.RequestId;
-import com.google.gerrit.server.util.SubmoduleSectionParser;
+import com.google.gerrit.server.util.git.SubmoduleSectionParser;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
diff --git a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
index 06f57b5..9efb976 100644
--- a/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
+++ b/java/com/google/gerrit/server/submit/LocalMergeSuperSetComputation.java
@@ -25,6 +25,7 @@
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -182,14 +183,19 @@
changeSet.ids().contains(cd.getId())
&& (projectState != null)
&& projectState.statePermitsRead();
- if (visible
- && !permissionBackend.user(user).change(cd).database(db).test(ChangePermission.READ)) {
+ if (!visible) {
+ return false;
+ }
+
+ try {
+ permissionBackend.user(user).change(cd).database(db).check(ChangePermission.READ);
+ return true;
+ } catch (AuthException e) {
// We thought the change was visible, but it isn't.
// This can happen if the ACL changes during the
// completeChangeSet computation, for example.
- visible = false;
+ return false;
}
- return visible;
}
private SubmitType submitType(ChangeData cd) throws OrmException {
diff --git a/java/com/google/gerrit/server/submit/MergeSuperSet.java b/java/com/google/gerrit/server/submit/MergeSuperSet.java
index 3e9f068..31bcc2a 100644
--- a/java/com/google/gerrit/server/submit/MergeSuperSet.java
+++ b/java/com/google/gerrit/server/submit/MergeSuperSet.java
@@ -20,6 +20,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
@@ -100,17 +101,22 @@
List<ChangeData> cds = queryProvider.get().byLegacyChangeId(change.getId());
checkState(cds.size() == 1, "Expected exactly one ChangeData, got " + cds.size());
ChangeData cd = Iterables.getFirst(cds, null);
- ProjectState projectState = projectCache.checkedGet(cd.project());
- ChangeSet changeSet =
- new ChangeSet(
- cd,
- projectState != null
- && projectState.statePermitsRead()
- && permissionBackend
- .user(user)
- .change(cd)
- .database(db)
- .test(ChangePermission.READ));
+
+ boolean visible = false;
+ if (cd != null) {
+ ProjectState projectState = projectCache.checkedGet(cd.project());
+
+ if (projectState.statePermitsRead()) {
+ try {
+ permissionBackend.user(user).change(cd).database(db).check(ChangePermission.READ);
+ visible = true;
+ } catch (AuthException e) {
+ // Do nothing.
+ }
+ }
+ }
+
+ ChangeSet changeSet = new ChangeSet(cd, visible);
if (wholeTopicEnabled(cfg)) {
return completeChangeSetIncludingTopics(db, changeSet, user);
}
@@ -203,8 +209,15 @@
private boolean canRead(ReviewDb db, CurrentUser user, ChangeData cd)
throws PermissionBackendException, IOException {
ProjectState projectState = projectCache.checkedGet(cd.project());
- return projectState != null
- && projectState.statePermitsRead()
- && permissionBackend.user(user).change(cd).database(db).test(ChangePermission.READ);
+ if (projectState == null || !projectState.statePermitsRead()) {
+ return false;
+ }
+
+ try {
+ permissionBackend.user(user).change(cd).database(db).check(ChangePermission.READ);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
}
diff --git a/java/com/google/gerrit/server/util/IdGenerator.java b/java/com/google/gerrit/server/util/IdGenerator.java
index a9a22d9..276df06 100644
--- a/java/com/google/gerrit/server/util/IdGenerator.java
+++ b/java/com/google/gerrit/server/util/IdGenerator.java
@@ -22,16 +22,6 @@
/** Simple class to produce 4 billion keys randomly distributed. */
@Singleton
public class IdGenerator {
- /** Format an id created by this class as a hex string. */
- public static String format(int id) {
- final char[] r = new char[8];
- for (int p = 7; 0 <= p; p--) {
- final int h = id & 0xf;
- r[p] = h < 10 ? (char) ('0' + h) : (char) ('a' + (h - 10));
- id >>= 4;
- }
- return new String(r);
- }
private final AtomicInteger gen;
diff --git a/java/com/google/gerrit/server/util/git/BUILD b/java/com/google/gerrit/server/util/git/BUILD
new file mode 100644
index 0000000..81ca9cd
--- /dev/null
+++ b/java/com/google/gerrit/server/util/git/BUILD
@@ -0,0 +1,9 @@
+java_library(
+ name = "git",
+ srcs = glob(["**/*.java"]),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/reviewdb:server",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ ],
+)
diff --git a/java/com/google/gerrit/server/util/SubmoduleSectionParser.java b/java/com/google/gerrit/server/util/git/SubmoduleSectionParser.java
similarity index 97%
rename from java/com/google/gerrit/server/util/SubmoduleSectionParser.java
rename to java/com/google/gerrit/server/util/git/SubmoduleSectionParser.java
index 6de2fef..a92b7fd 100644
--- a/java/com/google/gerrit/server/util/SubmoduleSectionParser.java
+++ b/java/com/google/gerrit/server/util/git/SubmoduleSectionParser.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2011 The Android Open Source Project
+// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.util;
+package com.google.gerrit.server.util.git;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
diff --git a/java/com/google/gerrit/server/validators/OutgoingEmailValidationListener.java b/java/com/google/gerrit/server/validators/OutgoingEmailValidationListener.java
index 9f152a5..996ad87 100644
--- a/java/com/google/gerrit/server/validators/OutgoingEmailValidationListener.java
+++ b/java/com/google/gerrit/server/validators/OutgoingEmailValidationListener.java
@@ -16,8 +16,8 @@
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.annotations.ExtensionPoint;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.send.EmailHeader;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
import java.util.Map;
import java.util.Set;
diff --git a/java/com/google/gerrit/sshd/BUILD b/java/com/google/gerrit/sshd/BUILD
index 6c810a3..4743b35 100644
--- a/java/com/google/gerrit/sshd/BUILD
+++ b/java/com/google/gerrit/sshd/BUILD
@@ -11,6 +11,7 @@
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/audit",
"//java/com/google/gerrit/server/cache/h2",
"//java/com/google/gerrit/server/git/receive",
"//java/com/google/gerrit/server/ioutil",
diff --git a/java/com/google/gerrit/sshd/ChangeArgumentParser.java b/java/com/google/gerrit/sshd/ChangeArgumentParser.java
index 9fc4cda..2ab13ee 100644
--- a/java/com/google/gerrit/sshd/ChangeArgumentParser.java
+++ b/java/com/google/gerrit/sshd/ChangeArgumentParser.java
@@ -86,15 +86,22 @@
}
for (ChangeNotes notes : matched) {
if (!changes.containsKey(notes.getChangeId())
- && inProject(projectState, notes.getProjectName())
- && (canMaintainServer
- || (permissionBackend
- .currentUser()
- .change(notes)
- .database(db)
- .test(ChangePermission.READ)
- && projectState.statePermitsRead()))) {
- toAdd.add(notes);
+ && inProject(projectState, notes.getProjectName())) {
+ if (canMaintainServer) {
+ toAdd.add(notes);
+ continue;
+ }
+
+ if (!projectState.statePermitsRead()) {
+ continue;
+ }
+
+ try {
+ permissionBackend.currentUser().change(notes).database(db).check(ChangePermission.READ);
+ toAdd.add(notes);
+ } catch (AuthException e) {
+ // Do nothing.
+ }
}
}
diff --git a/java/com/google/gerrit/sshd/SshLog.java b/java/com/google/gerrit/sshd/SshLog.java
index b6c2d19..98c649d 100644
--- a/java/com/google/gerrit/sshd/SshLog.java
+++ b/java/com/google/gerrit/sshd/SshLog.java
@@ -27,7 +27,7 @@
import com.google.gerrit.server.config.ConfigUpdatedEvent;
import com.google.gerrit.server.config.GerritConfigListener;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.util.IdGenerator;
+import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.server.util.SystemLog;
import com.google.gerrit.sshd.SshScope.Context;
import com.google.inject.Inject;
@@ -277,7 +277,7 @@
}
private static String id(int id) {
- return IdGenerator.format(id);
+ return HexFormat.fromInt(id);
}
void audit(Context ctx, Object result, String cmd) {
@@ -298,7 +298,7 @@
created = TimeUtil.nowMs();
} else {
SshSession session = ctx.getSession();
- sessionId = IdGenerator.format(session.getSessionId());
+ sessionId = HexFormat.fromInt(session.getSessionId());
currentUser = session.getUser();
created = ctx.created;
}
diff --git a/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java b/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
index c83660d..8a37cce 100644
--- a/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
+++ b/java/com/google/gerrit/sshd/commands/CreateAccountCommand.java
@@ -24,6 +24,7 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.account.CreateAccount;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
@@ -70,7 +71,9 @@
@Inject private CreateAccount createAccount;
@Override
- protected void run() throws OrmException, IOException, ConfigInvalidException, UnloggedFailure {
+ protected void run()
+ throws OrmException, IOException, ConfigInvalidException, UnloggedFailure,
+ PermissionBackendException {
AccountInput input = new AccountInput();
input.username = username;
input.email = email;
diff --git a/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java b/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
index 03f9616..917c138 100644
--- a/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
+++ b/java/com/google/gerrit/sshd/commands/CreateGroupCommand.java
@@ -26,6 +26,7 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.group.GroupResource;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.AddMembers;
import com.google.gerrit.server.restapi.group.AddSubgroups;
import com.google.gerrit.server.restapi.group.CreateGroup;
@@ -100,7 +101,9 @@
@Inject private AddSubgroups addSubgroups;
@Override
- protected void run() throws Failure, OrmException, IOException, ConfigInvalidException {
+ protected void run()
+ throws Failure, OrmException, IOException, ConfigInvalidException,
+ PermissionBackendException {
try {
GroupResource rsrc = createGroup();
@@ -117,7 +120,8 @@
}
private GroupResource createGroup()
- throws RestApiException, OrmException, IOException, ConfigInvalidException {
+ throws RestApiException, OrmException, IOException, ConfigInvalidException,
+ PermissionBackendException {
GroupInput input = new GroupInput();
input.description = groupDescription;
input.visibleToAll = visibleToAll;
@@ -132,7 +136,8 @@
}
private void addMembers(GroupResource rsrc)
- throws RestApiException, OrmException, IOException, ConfigInvalidException {
+ throws RestApiException, OrmException, IOException, ConfigInvalidException,
+ PermissionBackendException {
AddMembers.Input input =
AddMembers.Input.fromMembers(
initialMembers.stream().map(Object::toString).collect(toList()));
@@ -140,7 +145,8 @@
}
private void addSubgroups(GroupResource rsrc)
- throws RestApiException, OrmException, IOException, ConfigInvalidException {
+ throws RestApiException, OrmException, IOException, ConfigInvalidException,
+ PermissionBackendException {
AddSubgroups.Input input =
AddSubgroups.Input.fromGroups(
initialGroups.stream().map(AccountGroup.UUID::get).collect(toList()));
diff --git a/java/com/google/gerrit/sshd/commands/ListMembersCommand.java b/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
index cfd0a37..1565ecb 100644
--- a/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
+++ b/java/com/google/gerrit/sshd/commands/ListMembersCommand.java
@@ -25,6 +25,7 @@
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.ioutil.ColumnFormatter;
+import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.restapi.group.ListMembers;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
@@ -67,7 +68,7 @@
this.groupCache = groupCache;
}
- void display(PrintWriter writer) {
+ void display(PrintWriter writer) throws PermissionBackendException {
Optional<InternalGroup> group = groupCache.get(new AccountGroup.NameKey(name));
String errorText = "Group not found or not visible\n";
diff --git a/java/com/google/gerrit/sshd/commands/ShowConnections.java b/java/com/google/gerrit/sshd/commands/ShowConnections.java
index b30799b..9b517c6 100644
--- a/java/com/google/gerrit/sshd/commands/ShowConnections.java
+++ b/java/com/google/gerrit/sshd/commands/ShowConnections.java
@@ -22,7 +22,7 @@
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.util.IdGenerator;
+import com.google.gerrit.server.ioutil.HexFormat;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gerrit.sshd.SshDaemon;
@@ -168,7 +168,7 @@
}
private static String id(SshSession sd) {
- return sd != null ? IdGenerator.format(sd.getSessionId()) : "";
+ return sd != null ? HexFormat.fromInt(sd.getSessionId()) : "";
}
private static String time(long now, long time) {
diff --git a/java/com/google/gerrit/testing/BUILD b/java/com/google/gerrit/testing/BUILD
index 43aa978..cf65908 100644
--- a/java/com/google/gerrit/testing/BUILD
+++ b/java/com/google/gerrit/testing/BUILD
@@ -19,12 +19,14 @@
"//java/com/google/gerrit/index",
"//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/pgm/init",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
"//java/com/google/gerrit/server:module",
"//java/com/google/gerrit/server/api",
+ "//java/com/google/gerrit/server/audit",
"//java/com/google/gerrit/server/cache/h2",
"//java/com/google/gerrit/server/cache/mem",
"//java/com/google/gerrit/server/restapi",
diff --git a/java/com/google/gerrit/testing/FakeEmailSender.java b/java/com/google/gerrit/testing/FakeEmailSender.java
index 28946dc..e81d0f4 100644
--- a/java/com/google/gerrit/testing/FakeEmailSender.java
+++ b/java/com/google/gerrit/testing/FakeEmailSender.java
@@ -22,10 +22,10 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.errors.EmailException;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.EmailHeader;
+import com.google.gerrit.mail.MailHeader;
import com.google.gerrit.server.git.WorkQueue;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.MailHeader;
-import com.google.gerrit.server.mail.send.EmailHeader;
import com.google.gerrit.server.mail.send.EmailSender;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index b3f6222..8f9aa14 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -35,6 +35,7 @@
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.api.GerritApiModule;
import com.google.gerrit.server.api.PluginApiModule;
+import com.google.gerrit.server.audit.AuditModule;
import com.google.gerrit.server.cache.h2.H2CacheModule;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
import com.google.gerrit.server.config.AllProjectsName;
@@ -178,6 +179,7 @@
install(new DefaultPermissionBackendModule());
install(new SearchingChangeCacheImpl.Module());
factory(GarbageCollection.Factory.class);
+ install(new AuditModule());
bindScope(RequestScoped.class, PerThreadRequestScope.REQUEST);
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 0bcf02b..aa9ef80 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -90,6 +90,7 @@
import com.google.gerrit.gpg.Fingerprint;
import com.google.gerrit.gpg.PublicKeyStore;
import com.google.gerrit.gpg.testing.TestKey;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
@@ -111,7 +112,6 @@
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.account.StalenessChecker;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.RefPattern;
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
index b52efe7..9bc30ba 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/BUILD
@@ -8,4 +8,5 @@
"noci",
"no_windows",
],
+ deps = ["//java/com/google/gerrit/mail"],
)
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index f9284bd..0a42b1e 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -126,6 +126,7 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Branch;
@@ -140,7 +141,6 @@
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.git.ChangeMessageModifier;
import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.restapi.change.PostReview;
@@ -449,6 +449,16 @@
}
@Test
+ public void createWipChangeWithWorkInProgressByDefaultForProject() throws Exception {
+ ConfigInput input = new ConfigInput();
+ input.workInProgressByDefault = InheritableBoolean.TRUE;
+ gApi.projects().name(project.get()).config(input);
+ String changeId =
+ gApi.changes().create(new ChangeInput(project.get(), "master", "Test Change")).get().id;
+ assertThat(gApi.changes().id(changeId).get().workInProgress).isTrue();
+ }
+
+ @Test
public void setReadyForReviewNotAllowedWithoutPermission() throws Exception {
PushOneCommit.Result rready = createChange();
String changeId = rready.getChangeId();
diff --git a/javatests/com/google/gerrit/acceptance/api/project/BUILD b/javatests/com/google/gerrit/acceptance/api/project/BUILD
index 768c20b..97c6f33 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/BUILD
+++ b/javatests/com/google/gerrit/acceptance/api/project/BUILD
@@ -4,4 +4,5 @@
srcs = glob(["*IT.java"]),
group = "api_project",
labels = ["api"],
+ deps = ["//java/com/google/gerrit/index/project"],
)
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIndexerIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIndexerIT.java
new file mode 100644
index 0000000..6fde012
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIndexerIT.java
@@ -0,0 +1,129 @@
+// Copyright (C) 2018 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.acceptance.api.project;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.acceptance.GitUtil.fetch;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.index.IndexConfig;
+import com.google.gerrit.index.QueryOptions;
+import com.google.gerrit.index.RefState;
+import com.google.gerrit.index.project.ProjectField;
+import com.google.gerrit.index.project.ProjectIndex;
+import com.google.gerrit.index.project.ProjectIndexCollection;
+import com.google.gerrit.index.project.ProjectIndexer;
+import com.google.gerrit.index.query.FieldBundle;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.index.project.StalenessChecker;
+import com.google.gerrit.server.project.ProjectConfig;
+import com.google.inject.Inject;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Consumer;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Ref;
+import org.junit.Test;
+
+public class ProjectIndexerIT extends AbstractDaemonTest {
+ @Inject private ProjectIndexer projectIndexer;
+ @Inject private ProjectIndexCollection indexes;
+ @Inject private IndexConfig indexConfig;
+ @Inject private StalenessChecker stalenessChecker;
+
+ private static final ImmutableSet<String> FIELDS =
+ ImmutableSet.of(ProjectField.NAME.getName(), ProjectField.REF_STATE.getName());
+
+ @Test
+ public void indexProject_indexesRefStateOfProjectAndParents() throws Exception {
+ projectIndexer.index(project);
+ ProjectIndex i = indexes.getSearchIndex();
+ assertThat(i.getSchema().hasField(ProjectField.REF_STATE)).isTrue();
+
+ Optional<FieldBundle> result =
+ i.getRaw(project, QueryOptions.create(indexConfig, 0, 1, FIELDS));
+
+ assertThat(result.isPresent()).isTrue();
+ Iterable<byte[]> refState = result.get().getValue(ProjectField.REF_STATE);
+ assertThat(refState).isNotEmpty();
+
+ Map<Project.NameKey, Collection<RefState>> states = RefState.parseStates(refState).asMap();
+
+ fetch(testRepo, "refs/meta/config:refs/meta/config");
+ Ref projectConfigRef = testRepo.getRepository().exactRef("refs/meta/config");
+ TestRepository<InMemoryRepository> allProjectsRepo = cloneProject(allProjects, admin);
+ fetch(allProjectsRepo, "refs/meta/config:refs/meta/config");
+ Ref allProjectConfigRef = allProjectsRepo.getRepository().exactRef("refs/meta/config");
+ assertThat(states)
+ .containsExactly(
+ project,
+ ImmutableSet.of(RefState.of(projectConfigRef)),
+ allProjects,
+ ImmutableSet.of(RefState.of(allProjectConfigRef)));
+ }
+
+ @Test
+ public void stalenessChecker_currentProject_notStale() throws Exception {
+ assertThat(stalenessChecker.isStale(project)).isFalse();
+ }
+
+ @Test
+ public void stalenessChecker_currentProjectUpdates_isStale() throws Exception {
+ updateProjectConfigWithoutIndexUpdate(project);
+ assertThat(stalenessChecker.isStale(project)).isTrue();
+ }
+
+ @Test
+ public void stalenessChecker_parentProjectUpdates_isStale() throws Exception {
+ updateProjectConfigWithoutIndexUpdate(allProjects);
+ assertThat(stalenessChecker.isStale(project)).isTrue();
+ }
+
+ @Test
+ public void stalenessChecker_hierarchyChange_isStale() throws Exception {
+ Project.NameKey p1 = createProject("p1", allProjects);
+ Project.NameKey p2 = createProject("p2", allProjects);
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().getProject().setParentName(p1);
+ u.save();
+ }
+ assertThat(stalenessChecker.isStale(project)).isFalse();
+
+ updateProjectConfigWithoutIndexUpdate(p1, c -> c.getProject().setParentName(p2));
+ assertThat(stalenessChecker.isStale(project)).isTrue();
+ }
+
+ private void updateProjectConfigWithoutIndexUpdate(Project.NameKey project) throws Exception {
+ updateProjectConfigWithoutIndexUpdate(
+ project, c -> c.getProject().setDescription("making it stale"));
+ }
+
+ private void updateProjectConfigWithoutIndexUpdate(
+ Project.NameKey project, Consumer<ProjectConfig> update) throws Exception {
+ try (AutoCloseable ignored = disableProjectIndex()) {
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ update.accept(u.getConfig());
+ u.save();
+ }
+ } catch (UnsupportedOperationException e) {
+ // Drop, as we just wanted to drop the index update
+ return;
+ }
+ fail("should have a UnsupportedOperationException");
+ }
+}
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
index 51946e9..53cc5ad 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
@@ -32,6 +32,7 @@
import com.google.gerrit.common.RawInputUtil;
import com.google.gerrit.extensions.api.changes.FileApi;
import com.google.gerrit.extensions.api.changes.RebaseInput;
+import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.FileInfo;
@@ -112,16 +113,115 @@
}
@Test
- public void diffDeletedFile() throws Exception {
+ public void deletedFileIsIncludedInDiff() throws Exception {
gApi.changes().id(changeId).edit().deleteFile(FILE_NAME);
gApi.changes().id(changeId).edit().publish();
Map<String, FileInfo> changedFiles = gApi.changes().id(changeId).current().files();
assertThat(changedFiles.keySet()).containsExactly(COMMIT_MSG, FILE_NAME);
+ }
- DiffInfo diff = getDiffRequest(changeId, CURRENT, FILE_NAME).get();
- assertThat(diff.metaA.lines).isEqualTo(100);
- assertThat(diff.metaB).isNull();
+ @Test
+ public void numberOfLinesInDiffOfDeletedFileWithoutNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(3);
+ assertThat(diffInfo).metaB().isNull();
+ }
+
+ @Test
+ public void numberOfLinesInFileInfoOfDeletedFileWithoutNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ assertThat(changedFiles.get(filePath)).linesInserted().isNull();
+ assertThat(changedFiles.get(filePath)).linesDeleted().isEqualTo(3);
+ }
+
+ @Test
+ public void numberOfLinesInDiffOfDeletedFileWithNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(4);
+ assertThat(diffInfo).metaB().isNull();
+ }
+
+ @Test
+ public void numberOfLinesInFileInfoOfDeletedFileWithNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ assertThat(changedFiles.get(filePath)).linesInserted().isNull();
+ // Inherited from Git: An empty last line is ignored in the count.
+ assertThat(changedFiles.get(filePath)).linesDeleted().isEqualTo(3);
+ }
+
+ @Test
+ public void deletedFileWithoutNewlineAtEndResultsInOneDiffEntry() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo)
+ .content()
+ .onlyElement()
+ .linesOfA()
+ .containsExactly("Line 1", "Line 2", "Line 3");
+ }
+
+ @Test
+ public void deletedFileWithNewlineAtEndResultsInOneDiffEntry() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().deleteFile(filePath);
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo)
+ .content()
+ .onlyElement()
+ .linesOfA()
+ .containsExactly("Line 1", "Line 2", "Line 3", "");
}
@Test
@@ -136,6 +236,91 @@
}
@Test
+ public void numberOfLinesInDiffOfAddedFileWithoutNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).metaA().isNull();
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(3);
+ }
+
+ @Test
+ public void numberOfLinesInFileInfoOfAddedFileWithoutNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(filePath)).linesInserted().isEqualTo(3);
+ assertThat(changedFiles.get(filePath)).linesDeleted().isNull();
+ }
+
+ @Test
+ public void numberOfLinesInDiffOfAddedFileWithNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).metaA().isNull();
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(4);
+ }
+
+ @Test
+ public void numberOfLinesInFileInfoOfAddedFileWithNewlineAtEndIsCorrect() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ // Inherited from Git: An empty last line is ignored in the count.
+ assertThat(changedFiles.get(filePath)).linesInserted().isEqualTo(3);
+ assertThat(changedFiles.get(filePath)).linesDeleted().isNull();
+ }
+
+ @Test
+ public void addedFileWithoutNewlineAtEndResultsInOneDiffEntry() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(initialPatchSetId).get();
+ assertThat(diffInfo)
+ .content()
+ .onlyElement()
+ .linesOfB()
+ .containsExactly("Line 1", "Line 2", "Line 3");
+ }
+
+ @Test
+ public void addedFileWithNewlineAtEndResultsInOneDiffEntry() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(initialPatchSetId).get();
+ assertThat(diffInfo)
+ .content()
+ .onlyElement()
+ .linesOfB()
+ .containsExactly("Line 1", "Line 2", "Line 3", "");
+ }
+
+ @Test
public void renamedFileIsIncludedInDiff() throws Exception {
String newFilePath = "a_new_file.txt";
gApi.changes().id(changeId).edit().renameFile(FILE_NAME, newFilePath);
@@ -193,11 +378,11 @@
// automerge
diff = getDiffRequest(r.getChangeId(), r.getCommit().name(), "foo").get();
- assertThat(diff.metaA.lines).isEqualTo(5);
+ assertThat(diff.metaA.lines).isEqualTo(6);
assertThat(diff.metaB.lines).isEqualTo(1);
diff = getDiffRequest(r.getChangeId(), r.getCommit().name(), "bar").get();
- assertThat(diff.metaA.lines).isEqualTo(5);
+ assertThat(diff.metaA.lines).isEqualTo(6);
assertThat(diff.metaB.lines).isEqualTo(1);
// parent 1
@@ -212,6 +397,596 @@
}
@Test
+ public void diffOfUnmodifiedFileMarksAllLinesAsCommon() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().modifyCommitMessage("An unchanged patchset");
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo)
+ .content()
+ .onlyElement()
+ .commonLines()
+ .containsAllOf("Line 1", "Line 2", "Line 3")
+ .inOrder();
+ assertThat(diffInfo).content().onlyElement().linesOfA().isNull();
+ assertThat(diffInfo).content().onlyElement().linesOfB().isNull();
+ }
+
+ @Test
+ public void diffOfUnmodifiedFileWithNewlineAtEndHasEmptyLineAtEnd() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().modifyCommitMessage("An unchanged patchset");
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().onlyElement().commonLines().lastElement().isEqualTo("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(4);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(4);
+ }
+
+ @Test
+ public void diffOfUnmodifiedFileWithoutNewlineAtEndEndsWithLastLineContent() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ gApi.changes().id(changeId).edit().modifyCommitMessage("An unchanged patchset");
+ gApi.changes().id(changeId).edit().publish();
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().onlyElement().commonLines().lastElement().isEqualTo("Line 3");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(3);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(3);
+ }
+
+ @Test
+ public void diffOfModifiedFileWithNewlineAtEndHasEmptyLineAtEnd() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, filePath, content -> content.replace("Line 1\n", "Line one\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().lastElement().commonLines().lastElement().isEqualTo("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(4);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(4);
+ }
+
+ @Test
+ public void diffOfModifiedFileWithoutNewlineAtEndEndsWithLastLineContent() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, filePath, content -> content.replace("Line 1\n", "Line one\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().lastElement().commonLines().lastElement().isEqualTo("Line 3");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(3);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(3);
+ }
+
+ @Test
+ public void diffOfModifiedLastLineWithNewlineAtEndHasEmptyLineAtEnd() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3\n";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, filePath, content -> content.replace("Line 3\n", "Line three\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().lastElement().commonLines().lastElement().isEqualTo("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(4);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(4);
+ }
+
+ @Test
+ public void diffOfModifiedLastLineWithoutNewlineAtEndEndsWithLastLineContent() throws Exception {
+ String filePath = "a_new_file.txt";
+ String fileContent = "Line 1\nLine 2\nLine 3";
+ gApi.changes().id(changeId).edit().modifyFile(filePath, RawInputUtil.create(fileContent));
+ gApi.changes().id(changeId).edit().publish();
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, filePath, content -> content.replace("Line 3", "Line three"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, filePath).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().lastElement().linesOfA().containsExactly("Line 3");
+ assertThat(diffInfo).content().lastElement().linesOfB().containsExactly("Line three");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(3);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(3);
+ }
+
+ @Test
+ public void addedNewlineAtEndOfFileIsMarkedInDiffWhenWhitespaceIsConsidered() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .withBase(previousPatchSetId)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 101");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 101", "");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(102);
+ }
+
+ @Test
+ public void addedNewlineAtEndOfFileIsMarkedInDiffWhenWhitespaceIsIgnored() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_ALL)
+ .withBase(previousPatchSetId)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().isNull();
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(102);
+ }
+
+ @Test
+ public void addedNewlineAtEndOfFileMeansOneModifiedLine() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\n"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void addedLastLineWithoutNewlineBeforeAndAfterwardsIsMarkedInDiff() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\nLine 102"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .withBase(previousPatchSetId)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 101");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 101", "Line 102");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(102);
+ }
+
+ @Test
+ public void addedLastLineWithoutNewlineBeforeAndAfterwardsMeansTwoModifiedLines()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\nLine 102"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(2);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void addedLastLineWithoutNewlineBeforeButWithOneAfterwardsIsMarkedInDiff()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\nLine 102\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .withBase(previousPatchSetId)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 101");
+ assertThat(diffInfo)
+ .content()
+ .element(1)
+ .linesOfB()
+ .containsExactly("Line 101", "Line 102", "");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(103);
+ }
+
+ @Test
+ public void addedLastLineWithoutNewlineBeforeButWithOneAfterwardsMeansTwoModifiedLines()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("\nLine 102\n"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ // Inherited from Git: An empty last line is ignored in the count.
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(2);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void addedLastLineWithNewlineBeforeAndAfterwardsIsMarkedInDiff() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().isNull();
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 101");
+ assertThat(diffInfo).content().element(2).commonLines().containsExactly("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(102);
+ }
+
+ @Test
+ public void addedLastLineWithNewlineBeforeAndAfterwardsMeansOneInsertedLine() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101\n"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isNull();
+ }
+
+ @Test
+ public void addedLastLineWithNewlineBeforeButWithoutOneAfterwardsIsMarkedInDiff()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 101");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(101);
+ }
+
+ @Test
+ public void addedLastLineWithNewlineBeforeButWithoutOneAfterwardsMeansOneInsertedLine()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ // Inherited from Git: An empty last line is ignored in the count.
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isNull();
+ }
+
+ @Test
+ public void hunkForModifiedLastLineIsCombinedWithHunkForAddedNewlineAtEnd() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 101", "Line one oh one\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 101");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line one oh one", "");
+ }
+
+ @Test
+ public void intralineEditsForModifiedLastLineArePreservedWhenNewlineIsAlsoAddedAtEnd()
+ throws Exception {
+ assume().that(intraline).isTrue();
+
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 101", "Line one oh one\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo)
+ .content()
+ .element(1)
+ .intralineEditsOfA()
+ .containsExactly(ImmutableList.of(5, 3));
+ assertThat(diffInfo)
+ .content()
+ .element(1)
+ .intralineEditsOfB()
+ .containsExactly(ImmutableList.of(5, 11));
+ }
+
+ @Test
+ public void hunkForModifiedSecondToLastLineIsNotCombinedWithHunkForAddedNewlineAtEnd()
+ throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.concat("Line 101"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(
+ changeId,
+ FILE_NAME,
+ fileContent -> fileContent.replace("Line 100\n", "Line one hundred\n").concat("\n"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(previousPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 100");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line one hundred");
+ assertThat(diffInfo).content().element(2).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(3).linesOfA().isNull();
+ assertThat(diffInfo).content().element(3).linesOfB().containsExactly("");
+ }
+
+ @Test
+ public void deletedNewlineAtEndOfFileIsMarkedInDiffWhenWhitespaceIsConsidered() throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(initialPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 100", "");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 100");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(100);
+ }
+
+ @Test
+ public void deletedNewlineAtEndOfFileIsMarkedInDiffWhenWhitespaceIsIgnored() throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(initialPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_ALL)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("");
+ assertThat(diffInfo).content().element(1).linesOfB().isNull();
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(100);
+ }
+
+ @Test
+ public void deletedNewlineAtEndOfFileMeansOneModifiedLine() throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void deletedLastLineWithoutNewlineBeforeAndAfterwardsIsMarkedInDiff() throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("\nLine 100", ""));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(previousPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 99", "Line 100");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 99");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(100);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(99);
+ }
+
+ @Test
+ public void deletedLastLineWithoutNewlineBeforeAndAfterwardsMeansTwoModifiedLines()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("\nLine 100", ""));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(2);
+ }
+
+ @Test
+ public void deletedLastLineWithoutNewlineBeforeButWithOneAfterwardsIsMarkedInDiff()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100", ""));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(previousPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 100");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(100);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(100);
+ }
+
+ @Test
+ public void deletedLastLineWithoutNewlineBeforeButWithOneAfterwardsMeansOneDeletedLine()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line 100"));
+ String previousPatchSetId = gApi.changes().id(changeId).get().currentRevision;
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100", ""));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(previousPatchSetId);
+ // Inherited from Git: An empty last line is ignored in the count.
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isNull();
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void deletedLastLineWithNewlineBeforeAndAfterwardsIsMarkedInDiff() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", ""));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(initialPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 100");
+ assertThat(diffInfo).content().element(1).linesOfB().isNull();
+ assertThat(diffInfo).content().element(2).commonLines().containsExactly("");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(100);
+ }
+
+ @Test
+ public void deletedLastLineWithNewlineBeforeAndAfterwardsMeansOneDeletedLine() throws Exception {
+ addModifiedPatchSet(changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", ""));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isNull();
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(1);
+ }
+
+ @Test
+ public void deletedLastLineWithNewlineBeforeButWithoutOneAfterwardsIsMarkedInDiff()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("\nLine 100\n", ""));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME)
+ .withBase(initialPatchSetId)
+ .withWhitespace(DiffPreferencesInfo.Whitespace.IGNORE_NONE)
+ .get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 99", "Line 100", "");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line 99");
+
+ assertThat(diffInfo).metaA().totalLineCount().isEqualTo(101);
+ assertThat(diffInfo).metaB().totalLineCount().isEqualTo(99);
+ }
+
+ @Test
+ public void deletedLastLineWithNewlineBeforeButWithoutOneAfterwardsMeansTwoModifiedLines()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("\nLine 100\n", ""));
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(changeId).current().files(initialPatchSetId);
+ assertThat(changedFiles.get(FILE_NAME)).linesInserted().isEqualTo(1);
+ assertThat(changedFiles.get(FILE_NAME)).linesDeleted().isEqualTo(2);
+ }
+
+ @Test
+ public void hunkForModifiedLastLineIsCombinedWithHunkForDeletedNewlineAtEnd() throws Exception {
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line one hundred"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 100", "");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line one hundred");
+ }
+
+ @Test
+ public void intralineEditsForModifiedLastLineArePreservedWhenNewlineIsAlsoDeletedAtEnd()
+ throws Exception {
+ assume().that(intraline).isTrue();
+
+ addModifiedPatchSet(
+ changeId, FILE_NAME, fileContent -> fileContent.replace("Line 100\n", "Line one hundred"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo)
+ .content()
+ .element(1)
+ .intralineEditsOfA()
+ .containsExactly(ImmutableList.of(5, 4));
+ assertThat(diffInfo)
+ .content()
+ .element(1)
+ .intralineEditsOfB()
+ .containsExactly(ImmutableList.of(5, 11));
+ }
+
+ @Test
+ public void hunkForModifiedSecondToLastLineIsNotCombinedWithHunkForDeletedNewlineAtEnd()
+ throws Exception {
+ addModifiedPatchSet(
+ changeId,
+ FILE_NAME,
+ fileContent ->
+ fileContent
+ .replace("Line 99\n", "Line ninety-nine\n")
+ .replace("Line 100\n", "Line 100"));
+
+ DiffInfo diffInfo =
+ getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(initialPatchSetId).get();
+ assertThat(diffInfo).content().element(0).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(1).linesOfA().containsExactly("Line 99");
+ assertThat(diffInfo).content().element(1).linesOfB().containsExactly("Line ninety-nine");
+ assertThat(diffInfo).content().element(2).commonLines().isNotEmpty();
+ assertThat(diffInfo).content().element(3).linesOfA().containsExactly("");
+ assertThat(diffInfo).content().element(3).linesOfB().isNull();
+ }
+
+ @Test
public void addedUnrelatedFileIsIgnored_ForPatchSetDiffWithRebase() throws Exception {
ObjectId commit2 = addCommit(commit1, "file_added_in_another_commit.txt", "Some file content");
@@ -382,7 +1157,7 @@
.content()
.element(1)
.commonLines()
- .containsExactly("Line 2", "Line 3", "Line 4", "Line 5")
+ .containsExactly("Line 2", "Line 3", "Line 4", "Line 5", "")
.inOrder();
}
@@ -430,7 +1205,7 @@
.content()
.element(2)
.commonLines()
- .containsExactly("Line 4", "Line 5", "Line 6")
+ .containsExactly("Line 4", "Line 5", "Line 6", "")
.inOrder();
}
@@ -1027,7 +1802,7 @@
DiffInfo diffInfo =
getDiffRequest(changeId, CURRENT, FILE_NAME).withBase(previousPatchSetId).get();
assertThat(diffInfo).changeType().isEqualTo(ChangeType.DELETED);
- assertThat(diffInfo).content().element(0).linesOfA().hasSize(100);
+ assertThat(diffInfo).content().element(0).linesOfA().hasSize(101);
assertThat(diffInfo).content().element(0).linesOfB().isNull();
assertThat(diffInfo).content().element(0).isNotDueToRebase();
@@ -1050,7 +1825,7 @@
getDiffRequest(changeId, CURRENT, newFilePath).withBase(initialPatchSetId).get();
assertThat(diffInfo).changeType().isEqualTo(ChangeType.ADDED);
assertThat(diffInfo).content().element(0).linesOfA().isNull();
- assertThat(diffInfo).content().element(0).linesOfB().hasSize(3);
+ assertThat(diffInfo).content().element(0).linesOfB().hasSize(4);
assertThat(diffInfo).content().element(0).isNotDueToRebase();
Map<String, FileInfo> changedFiles =
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index cfa7ec4..b4ae8a2 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -71,6 +71,7 @@
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.common.testing.EditInfoSubject;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
import com.google.gerrit.reviewdb.client.Change;
@@ -84,7 +85,6 @@
import com.google.gerrit.server.git.receive.ReceiveConstants;
import com.google.gerrit.server.git.validators.CommitValidators.ChangeIdValidator;
import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testing.FakeEmailSender.Message;
diff --git a/javatests/com/google/gerrit/acceptance/git/BUILD b/javatests/com/google/gerrit/acceptance/git/BUILD
index 7a6a3c4..3541fec 100644
--- a/javatests/com/google/gerrit/acceptance/git/BUILD
+++ b/javatests/com/google/gerrit/acceptance/git/BUILD
@@ -16,6 +16,7 @@
srcs = ["AbstractPushForReview.java"],
deps = [
"//java/com/google/gerrit/acceptance:lib",
+ "//java/com/google/gerrit/mail",
],
)
diff --git a/javatests/com/google/gerrit/acceptance/pgm/BUILD b/javatests/com/google/gerrit/acceptance/pgm/BUILD
index 583ecc8..ea4c87d 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/BUILD
+++ b/javatests/com/google/gerrit/acceptance/pgm/BUILD
@@ -22,6 +22,7 @@
group = "elastic",
labels = [
"elastic",
+ "exclusive",
"flaky",
"pgm",
"no_windows",
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/BUILD b/javatests/com/google/gerrit/acceptance/rest/change/BUILD
index 6a4b4a7..46eb0ba 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/BUILD
+++ b/javatests/com/google/gerrit/acceptance/rest/change/BUILD
@@ -15,6 +15,7 @@
labels = ["rest"],
deps = [
":submit_util",
+ "//java/com/google/gerrit/mail",
],
)
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
index 84c9c03..06b67d8 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
@@ -32,7 +32,7 @@
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.server.mail.Address;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.testing.FakeEmailSender.Message;
import java.util.List;
import org.junit.Before;
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index 129d98a..2259999 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -46,8 +46,8 @@
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.ReviewerUpdateInfo;
import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.restapi.change.PostReviewers;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.gson.stream.JsonReader;
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/WorkInProgressByDefaultIT.java b/javatests/com/google/gerrit/acceptance/rest/change/WorkInProgressByDefaultIT.java
new file mode 100644
index 0000000..34d87d0
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/rest/change/WorkInProgressByDefaultIT.java
@@ -0,0 +1,158 @@
+// Copyright (C) 2018 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.acceptance.rest.change;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.extensions.api.projects.ConfigInput;
+import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
+import com.google.gerrit.extensions.client.InheritableBoolean;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.ChangeInput;
+import com.google.gerrit.reviewdb.client.Project;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class WorkInProgressByDefaultIT extends AbstractDaemonTest {
+ private Project.NameKey project1;
+ private Project.NameKey project2;
+
+ @Before
+ public void setUp() throws Exception {
+ project1 = createProject("project-1");
+ project2 = createProject("project-2", project1);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ setApiUser(admin);
+ GeneralPreferencesInfo prefs = gApi.accounts().id(admin.id.get()).getPreferences();
+ prefs.workInProgressByDefault = false;
+ gApi.accounts().id(admin.id.get()).setPreferences(prefs);
+ }
+
+ @Test
+ public void createChangeWithWorkInProgressByDefaultForProjectDisabled() throws Exception {
+ ChangeInfo info =
+ gApi.changes().create(new ChangeInput(project2.get(), "master", "empty change")).get();
+ assertThat(info.workInProgress).isNull();
+ }
+
+ @Test
+ public void createChangeWithWorkInProgressByDefaultForProjectEnabled() throws Exception {
+ setWorkInProgressByDefaultForProject(project2);
+ ChangeInput input = new ChangeInput(project2.get(), "master", "empty change");
+ assertThat(gApi.changes().create(input).get().workInProgress).isTrue();
+ }
+
+ @Test
+ public void createChangeWithWorkInProgressByDefaultForUserEnabled() throws Exception {
+ setWorkInProgressByDefaultForUser();
+ ChangeInput input = new ChangeInput(project2.get(), "master", "empty change");
+ assertThat(gApi.changes().create(input).get().workInProgress).isTrue();
+ }
+
+ @Test
+ public void createChangeBypassWorkInProgressByDefaultForProjectEnabled() throws Exception {
+ setWorkInProgressByDefaultForProject(project2);
+ ChangeInput input = new ChangeInput(project2.get(), "master", "empty change");
+ input.workInProgress = false;
+ assertThat(gApi.changes().create(input).get().workInProgress).isNull();
+ }
+
+ @Test
+ public void createChangeBypassWorkInProgressByDefaultForUserEnabled() throws Exception {
+ setWorkInProgressByDefaultForUser();
+ ChangeInput input = new ChangeInput(project2.get(), "master", "empty change");
+ input.workInProgress = false;
+ assertThat(gApi.changes().create(input).get().workInProgress).isNull();
+ }
+
+ @Test
+ public void createChangeWithWorkInProgressByDefaultForProjectInherited() throws Exception {
+ setWorkInProgressByDefaultForProject(project1);
+ ChangeInfo info =
+ gApi.changes().create(new ChangeInput(project2.get(), "master", "empty change")).get();
+ assertThat(info.workInProgress).isTrue();
+ }
+
+ @Test
+ public void pushWithWorkInProgressByDefaultForProjectEnabled() throws Exception {
+ setWorkInProgressByDefaultForProject(project2);
+ assertThat(createChange(project2).getChange().change().isWorkInProgress()).isTrue();
+ }
+
+ @Test
+ public void pushWithWorkInProgressByDefaultForUserEnabled() throws Exception {
+ setWorkInProgressByDefaultForUser();
+ assertThat(createChange(project2).getChange().change().isWorkInProgress()).isTrue();
+ }
+
+ @Test
+ public void pushBypassWorkInProgressByDefaultForProjectEnabled() throws Exception {
+ setWorkInProgressByDefaultForProject(project2);
+ assertThat(
+ createChange(project2, "refs/for/master%ready").getChange().change().isWorkInProgress())
+ .isFalse();
+ }
+
+ @Test
+ public void pushBypassWorkInProgressByDefaultForUserEnabled() throws Exception {
+ setWorkInProgressByDefaultForUser();
+ assertThat(
+ createChange(project2, "refs/for/master%ready").getChange().change().isWorkInProgress())
+ .isFalse();
+ }
+
+ @Test
+ public void pushWithWorkInProgressByDefaultForProjectDisabled() throws Exception {
+ assertThat(createChange(project2).getChange().change().isWorkInProgress()).isFalse();
+ }
+
+ @Test
+ public void pushWorkInProgressByDefaultForProjectInherited() throws Exception {
+ setWorkInProgressByDefaultForProject(project1);
+ assertThat(createChange(project2).getChange().change().isWorkInProgress()).isTrue();
+ }
+
+ private void setWorkInProgressByDefaultForProject(Project.NameKey p) throws Exception {
+ ConfigInput input = new ConfigInput();
+ input.workInProgressByDefault = InheritableBoolean.TRUE;
+ gApi.projects().name(p.get()).config(input);
+ }
+
+ private void setWorkInProgressByDefaultForUser() throws Exception {
+ GeneralPreferencesInfo prefs = gApi.accounts().id(admin.id.get()).getPreferences();
+ prefs.workInProgressByDefault = true;
+ gApi.accounts().id(admin.id.get()).setPreferences(prefs);
+ }
+
+ private PushOneCommit.Result createChange(Project.NameKey p) throws Exception {
+ return createChange(p, "refs/for/master");
+ }
+
+ private PushOneCommit.Result createChange(Project.NameKey p, String r) throws Exception {
+ TestRepository<InMemoryRepository> testRepo = cloneProject(p);
+ PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
+ PushOneCommit.Result result = push.to(r);
+ result.assertOkStatus();
+ return result;
+ }
+}
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/AbstractMailIT.java b/javatests/com/google/gerrit/acceptance/server/mail/AbstractMailIT.java
index 32f1ce5..c1b5cf4 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/AbstractMailIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/AbstractMailIT.java
@@ -22,7 +22,7 @@
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
import java.time.Instant;
import java.util.HashMap;
import org.junit.Ignore;
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/BUILD b/javatests/com/google/gerrit/acceptance/server/mail/BUILD
index 4175272..b5ad425 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/BUILD
+++ b/javatests/com/google/gerrit/acceptance/server/mail/BUILD
@@ -3,6 +3,7 @@
DEPS = [
"//lib/greenmail",
"//lib/mail",
+ "//java/com/google/gerrit/mail",
]
acceptance_tests(
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
index 7096581..9645a94 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
@@ -42,10 +42,14 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.SubmitInput;
+import com.google.gerrit.extensions.api.projects.ConfigInput;
+import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
+import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.extensions.common.CommitMessageInput;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.restapi.change.PostReview;
@@ -970,6 +974,38 @@
}
@Test
+ public void createWipChangeWithWorkInProgressByDefaultForProject() throws Exception {
+ setWorkInProgressByDefault(project, InheritableBoolean.TRUE);
+ StagedPreChange spc = stagePreChange("refs/for/master");
+ Truth.assertThat(gApi.changes().id(spc.changeId).get().workInProgress).isTrue();
+ assertThat(sender).notSent();
+ }
+
+ @Test
+ public void createWipChangeWithWorkInProgressByDefaultForUser() throws Exception {
+ // Make sure owner user is created
+ StagedChange sc = stageReviewableChange();
+ // All was cleaned already
+ assertThat(sender).notSent();
+
+ // Toggle workInProgress flag for owner
+ GeneralPreferencesInfo prefs = gApi.accounts().id(sc.owner.id.get()).getPreferences();
+ prefs.workInProgressByDefault = true;
+ gApi.accounts().id(sc.owner.id.get()).setPreferences(prefs);
+
+ // Create another change without notification that should be wip
+ StagedPreChange spc = stagePreChange("refs/for/master");
+ Truth.assertThat(gApi.changes().id(spc.changeId).get().workInProgress).isTrue();
+ assertThat(sender).notSent();
+
+ // Clean up workInProgressByDefault by owner
+ prefs = gApi.accounts().id(sc.owner.id.get()).getPreferences();
+ Truth.assertThat(prefs.workInProgressByDefault).isTrue();
+ prefs.workInProgressByDefault = false;
+ gApi.accounts().id(sc.owner.id.get()).setPreferences(prefs);
+ }
+
+ @Test
public void createReviewableChangeWithNotifyOwnerReviewers() throws Exception {
stagePreChange("refs/for/master%notify=OWNER_REVIEWERS");
assertThat(sender).notSent();
@@ -2646,4 +2682,11 @@
// PolyGerrit current immediately follows up with a review.
gApi.changes().id(sc.changeId).revision("current").review(ReviewInput.noScore());
}
+
+ private void setWorkInProgressByDefault(Project.NameKey p, InheritableBoolean v)
+ throws Exception {
+ ConfigInput input = new ConfigInput();
+ input.workInProgressByDefault = v;
+ gApi.projects().name(p.get()).config(input);
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java b/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
index 438954c..13f0416 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/ListMailFilterIT.java
@@ -21,8 +21,8 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.server.mail.MailUtil;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
+import com.google.gerrit.mail.MailProcessingUtil;
import com.google.gerrit.server.mail.receive.MailProcessor;
import com.google.inject.Inject;
import java.time.ZoneId;
@@ -100,7 +100,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
index 3315a33..988b051 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailMetadataIT.java
@@ -22,8 +22,8 @@
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
-import com.google.gerrit.server.mail.MailUtil;
-import com.google.gerrit.server.mail.send.EmailHeader;
+import com.google.gerrit.mail.EmailHeader;
+import com.google.gerrit.mail.MailProcessingUtil;
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.TestTimeUtil;
import java.sql.Timestamp;
@@ -147,7 +147,7 @@
.contains(
entry.getKey()
+ ": "
- + MailUtil.rfcDateformatter.format(
+ + MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(
((Timestamp) entry.getValue()).toInstant(), ZoneId.of("UTC"))));
} else {
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
index f34fe33..b9f30d6 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
@@ -20,8 +20,8 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.server.mail.MailUtil;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
+import com.google.gerrit.mail.MailProcessingUtil;
import com.google.gerrit.server.mail.receive.MailProcessor;
import com.google.gerrit.testing.FakeEmailSender.Message;
import com.google.inject.Inject;
@@ -40,7 +40,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
@@ -68,7 +68,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
@@ -104,7 +104,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
@@ -141,7 +141,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
@@ -171,7 +171,7 @@
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
assertThat(comments).hasSize(2);
@@ -206,7 +206,7 @@
List<CommentInfo> comments = gApi.changes().id(changeId).current().commentsAsList();
assertThat(comments).hasSize(2);
String ts =
- MailUtil.rfcDateformatter.format(
+ MailProcessingUtil.rfcDateformatter.format(
ZonedDateTime.ofInstant(comments.get(0).updated.toInstant(), ZoneId.of("UTC")));
// Build Message
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
index 4f51e1f..8d21b5b 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailSenderIT.java
@@ -17,7 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.acceptance.GerritConfig;
-import com.google.gerrit.server.mail.send.EmailHeader;
+import com.google.gerrit.mail.EmailHeader;
import java.net.URI;
import java.util.Map;
import org.junit.Test;
diff --git a/javatests/com/google/gerrit/acceptance/server/project/BUILD b/javatests/com/google/gerrit/acceptance/server/project/BUILD
index efa1cdb..42dfbac 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/BUILD
+++ b/javatests/com/google/gerrit/acceptance/server/project/BUILD
@@ -4,4 +4,5 @@
srcs = glob(["*IT.java"]),
group = "server_project",
labels = ["server"],
+ deps = ["//java/com/google/gerrit/mail"],
)
diff --git a/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java b/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
index ca0cae4..cfdd781 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
@@ -26,11 +26,11 @@
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.common.GroupInfo;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.ProjectWatches.NotifyType;
import com.google.gerrit.server.git.NotifyConfig;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.testing.FakeEmailSender.Message;
import java.util.EnumSet;
import java.util.List;
diff --git a/javatests/com/google/gerrit/acceptance/ssh/BUILD b/javatests/com/google/gerrit/acceptance/ssh/BUILD
index eefd9d3..b195ecc 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/BUILD
+++ b/javatests/com/google/gerrit/acceptance/ssh/BUILD
@@ -25,8 +25,9 @@
srcs = ["ElasticIndexIT.java"],
group = "elastic",
labels = [
- "elastic",
"docker",
+ "elastic",
+ "exclusive",
"ssh",
],
deps = [
diff --git a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
index 13bb2f2..95da5a6 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/ElasticIndexIT.java
@@ -24,16 +24,14 @@
import org.eclipse.jgit.lib.Config;
public class ElasticIndexIT extends AbstractIndexTests {
- private static ElasticContainer<?> container;
private static Config getConfig(ElasticVersion version) {
ElasticNodeInfo elasticNodeInfo;
- container = ElasticContainer.createAndStart(version);
+ ElasticContainer<?> container = ElasticContainer.createAndStart(version);
elasticNodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
String indicesPrefix = UUID.randomUUID().toString();
Config cfg = new Config();
- String password = version == ElasticVersion.V5_6 ? "changeme" : null;
- ElasticTestUtils.configure(cfg, elasticNodeInfo.port, indicesPrefix, password);
+ ElasticTestUtils.configure(cfg, elasticNodeInfo.port, indicesPrefix, version);
return cfg;
}
diff --git a/javatests/com/google/gerrit/acceptance/tests.bzl b/javatests/com/google/gerrit/acceptance/tests.bzl
index 4b3b802d..08556a0 100644
--- a/javatests/com/google/gerrit/acceptance/tests.bzl
+++ b/javatests/com/google/gerrit/acceptance/tests.bzl
@@ -1,21 +1,21 @@
load("//tools/bzl:junit.bzl", "junit_tests")
def acceptance_tests(
- group,
- deps = [],
- labels = [],
- vm_args = ['-Xmx256m'],
- **kwargs):
- junit_tests(
- name = group,
- deps = deps + [
- '//java/com/google/gerrit/acceptance:lib',
- ],
- tags = labels + [
- 'acceptance',
- 'slow',
- ],
- size = "large",
- jvm_flags = vm_args,
- **kwargs
- )
+ group,
+ deps = [],
+ labels = [],
+ vm_args = ["-Xmx256m"],
+ **kwargs):
+ junit_tests(
+ name = group,
+ deps = deps + [
+ "//java/com/google/gerrit/acceptance:lib",
+ ],
+ tags = labels + [
+ "acceptance",
+ "slow",
+ ],
+ size = "large",
+ jvm_flags = vm_args,
+ **kwargs
+ )
diff --git a/javatests/com/google/gerrit/common/BUILD b/javatests/com/google/gerrit/common/BUILD
index ba9a5bc..c4f2c0a 100644
--- a/javatests/com/google/gerrit/common/BUILD
+++ b/javatests/com/google/gerrit/common/BUILD
@@ -1,32 +1,14 @@
load("//tools/bzl:junit.bzl", "junit_tests")
-SERVER_TEST_SRCS = [
- "AutoValueTest.java",
- "VersionTest.java",
-]
-
junit_tests(
- name = "client_tests",
- srcs = glob(
- ["**/*.java"],
- exclude = SERVER_TEST_SRCS,
- ),
- deps = [
- "//java/com/google/gerrit/common:client",
- "//lib:guava",
- "//lib:junit",
- "//lib/truth",
- ],
-)
-
-junit_tests(
- name = "server_tests",
- srcs = SERVER_TEST_SRCS,
+ name = "common_tests",
+ srcs = glob(["**/*.java"]),
tags = ["no_windows"],
deps = [
"//java/com/google/gerrit/common:server",
"//java/com/google/gerrit/common:version",
"//java/com/google/gerrit/launcher",
+ "//java/com/google/gerrit/reviewdb:server",
"//lib:guava",
"//lib/auto:auto-value",
"//lib/auto:auto-value-annotations",
diff --git a/javatests/com/google/gerrit/common/data/GroupReferenceTest.java b/javatests/com/google/gerrit/common/data/GroupReferenceTest.java
new file mode 100644
index 0000000..717e122
--- /dev/null
+++ b/javatests/com/google/gerrit/common/data/GroupReferenceTest.java
@@ -0,0 +1,157 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.common.data;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.AccountGroup.UUID;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class GroupReferenceTest {
+ @Rule public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void forGroupDescription() {
+ String name = "foo";
+ AccountGroup.UUID uuid = new AccountGroup.UUID("uuid-foo");
+ GroupReference groupReference =
+ GroupReference.forGroup(
+ new GroupDescription.Basic() {
+
+ @Override
+ public String getUrl() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public UUID getGroupUUID() {
+ return uuid;
+ }
+
+ @Override
+ public String getEmailAddress() {
+ return null;
+ }
+ });
+ assertThat(groupReference.getName()).isEqualTo(name);
+ assertThat(groupReference.getUUID()).isEqualTo(uuid);
+ }
+
+ @Test
+ public void create() {
+ AccountGroup.UUID uuid = new AccountGroup.UUID("uuid");
+ String name = "foo";
+ GroupReference groupReference = new GroupReference(uuid, name);
+ assertThat(groupReference.getUUID()).isEqualTo(uuid);
+ assertThat(groupReference.getName()).isEqualTo(name);
+ }
+
+ @Test
+ public void createWithoutUuid() {
+ // GroupReferences where the UUID is null are used to represent groups from project.config that
+ // cannot be resolved.
+ String name = "foo";
+ GroupReference groupReference = new GroupReference(null, name);
+ assertThat(groupReference.getUUID()).isNull();
+ assertThat(groupReference.getName()).isEqualTo(name);
+ }
+
+ @Test
+ public void cannotCreateWithoutName() {
+ exception.expect(NullPointerException.class);
+ new GroupReference(new AccountGroup.UUID("uuid"), null);
+ }
+
+ @Test
+ public void isGroupReference() {
+ assertThat(GroupReference.isGroupReference("foo")).isFalse();
+ assertThat(GroupReference.isGroupReference("groupfoo")).isFalse();
+ assertThat(GroupReference.isGroupReference("group foo")).isTrue();
+ assertThat(GroupReference.isGroupReference("group foo-bar")).isTrue();
+ assertThat(GroupReference.isGroupReference("group foo bar")).isTrue();
+ }
+
+ @Test
+ public void extractGroupName() {
+ assertThat(GroupReference.extractGroupName("foo")).isNull();
+ assertThat(GroupReference.extractGroupName("groupfoo")).isNull();
+ assertThat(GroupReference.extractGroupName("group foo")).isEqualTo("foo");
+ assertThat(GroupReference.extractGroupName("group foo-bar")).isEqualTo("foo-bar");
+ assertThat(GroupReference.extractGroupName("group foo bar")).isEqualTo("foo bar");
+ }
+
+ @Test
+ public void getAndSetUuid() {
+ AccountGroup.UUID uuid = new AccountGroup.UUID("uuid-foo");
+ String name = "foo";
+ GroupReference groupReference = new GroupReference(uuid, name);
+ assertThat(groupReference.getUUID()).isEqualTo(uuid);
+
+ AccountGroup.UUID uuid2 = new AccountGroup.UUID("uuid-bar");
+ groupReference.setUUID(uuid2);
+ assertThat(groupReference.getUUID()).isEqualTo(uuid2);
+
+ // GroupReferences where the UUID is null are used to represent groups from project.config that
+ // cannot be resolved.
+ groupReference.setUUID(null);
+ assertThat(groupReference.getUUID()).isNull();
+ }
+
+ @Test
+ public void getAndSetName() {
+ AccountGroup.UUID uuid = new AccountGroup.UUID("uuid-foo");
+ String name = "foo";
+ GroupReference groupReference = new GroupReference(uuid, name);
+ assertThat(groupReference.getName()).isEqualTo(name);
+
+ String name2 = "bar";
+ groupReference.setName(name2);
+ assertThat(groupReference.getName()).isEqualTo(name2);
+
+ exception.expect(NullPointerException.class);
+ groupReference.setName(null);
+ }
+
+ @Test
+ public void toConfigValue() {
+ String name = "foo";
+ GroupReference groupReference = new GroupReference(new AccountGroup.UUID("uuid-foo"), name);
+ assertThat(groupReference.toConfigValue()).isEqualTo("group " + name);
+ }
+
+ @Test
+ public void testEquals() {
+ AccountGroup.UUID uuid1 = new AccountGroup.UUID("uuid-foo");
+ AccountGroup.UUID uuid2 = new AccountGroup.UUID("uuid-bar");
+ String name1 = "foo";
+ String name2 = "bar";
+
+ GroupReference groupReference1 = new GroupReference(uuid1, name1);
+ GroupReference groupReference2 = new GroupReference(uuid1, name2);
+ GroupReference groupReference3 = new GroupReference(uuid2, name1);
+
+ assertThat(groupReference1.equals(groupReference2)).isTrue();
+ assertThat(groupReference1.equals(groupReference3)).isFalse();
+ assertThat(groupReference2.equals(groupReference3)).isFalse();
+ }
+}
diff --git a/javatests/com/google/gerrit/elasticsearch/BUILD b/javatests/com/google/gerrit/elasticsearch/BUILD
index 595c887..cc849eb 100644
--- a/javatests/com/google/gerrit/elasticsearch/BUILD
+++ b/javatests/com/google/gerrit/elasticsearch/BUILD
@@ -49,10 +49,11 @@
ELASTICSEARCH_TAGS = [
"docker",
"elastic",
+ "exclusive",
]
[junit_tests(
- name = "elasticsearch_%ss_test" % name,
+ name = "elasticsearch_query_%ss_test" % name,
size = "large",
srcs = [src],
tags = ELASTICSEARCH_TAGS,
@@ -60,7 +61,7 @@
) for name, src in ELASTICSEARCH_TESTS.items()]
[junit_tests(
- name = "elasticsearch_%ss_test_V5" % name,
+ name = "elasticsearch_query_%ss_test_V5" % name,
size = "large",
srcs = [src],
tags = ELASTICSEARCH_TAGS,
@@ -68,14 +69,14 @@
) for name, src in ELASTICSEARCH_TESTS_V5.items()]
[junit_tests(
- name = "elasticsearch_%ss_test_V6" % name,
+ name = "elasticsearch_query_%ss_test_V6" % name,
size = "large",
srcs = [src],
tags = ELASTICSEARCH_TAGS + ["flaky"],
deps = ELASTICSEARCH_DEPS + [QUERY_TESTS_DEP % name],
) for name, src in ELASTICSEARCH_TESTS_V6.items()]
-[junit_tests(
+junit_tests(
name = "elasticsearch_tests",
size = "small",
srcs = glob(
@@ -90,4 +91,4 @@
"//lib/jgit/org.eclipse.jgit:jgit",
"//lib/truth",
],
-)]
+)
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java b/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
index 02e0ba2..b46e040 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticTestUtils.java
@@ -32,11 +32,12 @@
}
}
- public static void configure(Config config, int port, String prefix, String password) {
+ public static void configure(Config config, int port, String prefix, ElasticVersion version) {
config.setEnum("index", null, "type", IndexType.ELASTICSEARCH);
config.setString("elasticsearch", null, "server", "http://localhost:" + port);
config.setString("elasticsearch", null, "prefix", prefix);
config.setInt("index", null, "maxLimit", 10000);
+ String password = version == ElasticVersion.V5_6 ? "changeme" : null;
if (password != null) {
config.setString("elasticsearch", null, "password", password);
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
index 0fcdb20..5d2f944 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryAccountsTest.java
@@ -67,7 +67,8 @@
Config elasticsearchConfig = new Config(config);
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = testName();
- ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix, "changeme");
+ ElasticTestUtils.configure(
+ elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
index 4520020..5d76162 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryChangesTest.java
@@ -67,7 +67,8 @@
Config elasticsearchConfig = new Config(config);
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = testName();
- ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix, "changeme");
+ ElasticTestUtils.configure(
+ elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
index d953139..9ce2e93 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryGroupsTest.java
@@ -67,7 +67,8 @@
Config elasticsearchConfig = new Config(config);
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = testName();
- ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix, "changeme");
+ ElasticTestUtils.configure(
+ elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
}
}
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
index 7b49e1d..4184935 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticV5QueryProjectsTest.java
@@ -67,7 +67,8 @@
Config elasticsearchConfig = new Config(config);
InMemoryModule.setDefaults(elasticsearchConfig);
String indicesPrefix = testName();
- ElasticTestUtils.configure(elasticsearchConfig, nodeInfo.port, indicesPrefix);
+ ElasticTestUtils.configure(
+ elasticsearchConfig, nodeInfo.port, indicesPrefix, ElasticVersion.V5_6);
return Guice.createInjector(new InMemoryModule(elasticsearchConfig, notesMigration));
}
}
diff --git a/javatests/com/google/gerrit/server/mail/receive/AbstractParserTest.java b/javatests/com/google/gerrit/mail/AbstractParserTest.java
similarity index 97%
rename from javatests/com/google/gerrit/server/mail/receive/AbstractParserTest.java
rename to javatests/com/google/gerrit/mail/AbstractParserTest.java
index 0e894a6..5219ce8 100644
--- a/javatests/com/google/gerrit/server/mail/receive/AbstractParserTest.java
+++ b/javatests/com/google/gerrit/mail/AbstractParserTest.java
@@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.server.mail.Address;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.ArrayList;
diff --git a/javatests/com/google/gerrit/server/mail/AddressTest.java b/javatests/com/google/gerrit/mail/AddressTest.java
similarity index 81%
rename from javatests/com/google/gerrit/server/mail/AddressTest.java
rename to javatests/com/google/gerrit/mail/AddressTest.java
index 7dbd563..53ff1fe 100644
--- a/javatests/com/google/gerrit/server/mail/AddressTest.java
+++ b/javatests/com/google/gerrit/mail/AddressTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
@@ -24,57 +24,57 @@
@Test
public void parse_NameEmail1() {
final Address a = Address.parse("A U Thor <author@example.com>");
- assertThat(a.name).isEqualTo("A U Thor");
- assertThat(a.email).isEqualTo("author@example.com");
+ assertThat(a.getName()).isEqualTo("A U Thor");
+ assertThat(a.getEmail()).isEqualTo("author@example.com");
}
@Test
public void parse_NameEmail2() {
final Address a = Address.parse("A <a@b>");
- assertThat(a.name).isEqualTo("A");
- assertThat(a.email).isEqualTo("a@b");
+ assertThat(a.getName()).isEqualTo("A");
+ assertThat(a.getEmail()).isEqualTo("a@b");
}
@Test
public void parse_NameEmail3() {
final Address a = Address.parse("<a@b>");
- assertThat(a.name).isNull();
- assertThat(a.email).isEqualTo("a@b");
+ assertThat(a.getName()).isNull();
+ assertThat(a.getEmail()).isEqualTo("a@b");
}
@Test
public void parse_NameEmail4() {
final Address a = Address.parse("A U Thor<author@example.com>");
- assertThat(a.name).isEqualTo("A U Thor");
- assertThat(a.email).isEqualTo("author@example.com");
+ assertThat(a.getName()).isEqualTo("A U Thor");
+ assertThat(a.getEmail()).isEqualTo("author@example.com");
}
@Test
public void parse_NameEmail5() {
final Address a = Address.parse("A U Thor <author@example.com>");
- assertThat(a.name).isEqualTo("A U Thor");
- assertThat(a.email).isEqualTo("author@example.com");
+ assertThat(a.getName()).isEqualTo("A U Thor");
+ assertThat(a.getEmail()).isEqualTo("author@example.com");
}
@Test
public void parse_Email1() {
final Address a = Address.parse("author@example.com");
- assertThat(a.name).isNull();
- assertThat(a.email).isEqualTo("author@example.com");
+ assertThat(a.getName()).isNull();
+ assertThat(a.getEmail()).isEqualTo("author@example.com");
}
@Test
public void parse_Email2() {
final Address a = Address.parse("a@b");
- assertThat(a.name).isNull();
- assertThat(a.email).isEqualTo("a@b");
+ assertThat(a.getName()).isNull();
+ assertThat(a.getEmail()).isEqualTo("a@b");
}
@Test
public void parse_NewTLD() {
Address a = Address.parse("A U Thor <author@example.systems>");
- assertThat(a.name).isEqualTo("A U Thor");
- assertThat(a.email).isEqualTo("author@example.systems");
+ assertThat(a.getName()).isEqualTo("A U Thor");
+ assertThat(a.getEmail()).isEqualTo("author@example.systems");
}
@Test
diff --git a/javatests/com/google/gerrit/mail/BUILD b/javatests/com/google/gerrit/mail/BUILD
new file mode 100644
index 0000000..488bbcc
--- /dev/null
+++ b/javatests/com/google/gerrit/mail/BUILD
@@ -0,0 +1,36 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+junit_tests(
+ name = "maillib_tests",
+ size = "small",
+ srcs = glob(
+ ["**/*.java"],
+ ),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/common:annotations",
+ "//java/com/google/gerrit/common:server",
+ "//java/com/google/gerrit/extensions:api",
+ "//java/com/google/gerrit/extensions/common/testing:common-test-util",
+ "//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/index:query_exception",
+ "//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/mail",
+ "//java/com/google/gerrit/metrics",
+ "//java/com/google/gerrit/reviewdb:server",
+ "//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/project/testing:project-test-util",
+ "//java/com/google/gerrit/testing:gerrit-test-util",
+ "//java/org/eclipse/jgit:server",
+ "//lib:grappa",
+ "//lib:gson",
+ "//lib:guava-retrying",
+ "//lib:gwtorm",
+ "//lib/commons:codec",
+ "//lib/guice",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ "//lib/jgit/org.eclipse.jgit.junit:junit",
+ "//lib/truth",
+ "//lib/truth:truth-java8-extension",
+ ],
+)
diff --git a/javatests/com/google/gerrit/server/mail/receive/GenericHtmlParserTest.java b/javatests/com/google/gerrit/mail/GenericHtmlParserTest.java
similarity index 98%
rename from javatests/com/google/gerrit/server/mail/receive/GenericHtmlParserTest.java
rename to javatests/com/google/gerrit/mail/GenericHtmlParserTest.java
index f78953d..4718bad 100644
--- a/javatests/com/google/gerrit/server/mail/receive/GenericHtmlParserTest.java
+++ b/javatests/com/google/gerrit/mail/GenericHtmlParserTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
/** Test parser for a generic Html email client response */
public class GenericHtmlParserTest extends HtmlParserTest {
diff --git a/javatests/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java b/javatests/com/google/gerrit/mail/GmailHtmlParserTest.java
similarity index 98%
rename from javatests/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java
rename to javatests/com/google/gerrit/mail/GmailHtmlParserTest.java
index df71629..f597dee 100644
--- a/javatests/com/google/gerrit/server/mail/receive/GmailHtmlParserTest.java
+++ b/javatests/com/google/gerrit/mail/GmailHtmlParserTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
public class GmailHtmlParserTest extends HtmlParserTest {
@Override
diff --git a/javatests/com/google/gerrit/server/mail/receive/HtmlParserTest.java b/javatests/com/google/gerrit/mail/HtmlParserTest.java
similarity index 98%
rename from javatests/com/google/gerrit/server/mail/receive/HtmlParserTest.java
rename to javatests/com/google/gerrit/mail/HtmlParserTest.java
index d88e09f..d630bd6 100644
--- a/javatests/com/google/gerrit/server/mail/receive/HtmlParserTest.java
+++ b/javatests/com/google/gerrit/mail/HtmlParserTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
diff --git a/javatests/com/google/gerrit/server/mail/receive/MailHeaderParserTest.java b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
similarity index 96%
rename from javatests/com/google/gerrit/server/mail/receive/MailHeaderParserTest.java
rename to javatests/com/google/gerrit/mail/MailHeaderParserTest.java
index 071dc4b..2d2c2ea 100644
--- a/javatests/com/google/gerrit/server/mail/receive/MailHeaderParserTest.java
+++ b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
@@ -12,12 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.MailHeader;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Month;
diff --git a/javatests/com/google/gerrit/server/mail/receive/ParserUtilTest.java b/javatests/com/google/gerrit/mail/ParserUtilTest.java
similarity index 97%
rename from javatests/com/google/gerrit/server/mail/receive/ParserUtilTest.java
rename to javatests/com/google/gerrit/mail/ParserUtilTest.java
index dfa492c..47a5367 100644
--- a/javatests/com/google/gerrit/server/mail/receive/ParserUtilTest.java
+++ b/javatests/com/google/gerrit/mail/ParserUtilTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
diff --git a/javatests/com/google/gerrit/server/mail/receive/RawMailParserTest.java b/javatests/com/google/gerrit/mail/RawMailParserTest.java
similarity index 83%
rename from javatests/com/google/gerrit/server/mail/receive/RawMailParserTest.java
rename to javatests/com/google/gerrit/mail/RawMailParserTest.java
index fb52947..9049704 100644
--- a/javatests/com/google/gerrit/server/mail/receive/RawMailParserTest.java
+++ b/javatests/com/google/gerrit/mail/RawMailParserTest.java
@@ -12,17 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
-import com.google.gerrit.server.mail.receive.data.AttachmentMessage;
-import com.google.gerrit.server.mail.receive.data.Base64HeaderMessage;
-import com.google.gerrit.server.mail.receive.data.HtmlMimeMessage;
-import com.google.gerrit.server.mail.receive.data.NonUTF8Message;
-import com.google.gerrit.server.mail.receive.data.QuotedPrintableHeaderMessage;
-import com.google.gerrit.server.mail.receive.data.RawMailMessage;
-import com.google.gerrit.server.mail.receive.data.SimpleTextMessage;
+import com.google.gerrit.mail.data.AttachmentMessage;
+import com.google.gerrit.mail.data.Base64HeaderMessage;
+import com.google.gerrit.mail.data.HtmlMimeMessage;
+import com.google.gerrit.mail.data.NonUTF8Message;
+import com.google.gerrit.mail.data.QuotedPrintableHeaderMessage;
+import com.google.gerrit.mail.data.RawMailMessage;
+import com.google.gerrit.mail.data.SimpleTextMessage;
import com.google.gerrit.testing.GerritBaseTests;
import org.junit.Test;
diff --git a/javatests/com/google/gerrit/server/mail/receive/TextParserTest.java b/javatests/com/google/gerrit/mail/TextParserTest.java
similarity index 99%
rename from javatests/com/google/gerrit/server/mail/receive/TextParserTest.java
rename to javatests/com/google/gerrit/mail/TextParserTest.java
index 89e1f22..e11321a 100644
--- a/javatests/com/google/gerrit/server/mail/receive/TextParserTest.java
+++ b/javatests/com/google/gerrit/mail/TextParserTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive;
+package com.google.gerrit.mail;
import static com.google.common.truth.Truth.assertThat;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/AttachmentMessage.java b/javatests/com/google/gerrit/mail/data/AttachmentMessage.java
similarity index 95%
rename from javatests/com/google/gerrit/server/mail/receive/data/AttachmentMessage.java
rename to javatests/com/google/gerrit/mail/data/AttachmentMessage.java
index eb4d180..1d94d68 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/AttachmentMessage.java
+++ b/javatests/com/google/gerrit/mail/data/AttachmentMessage.java
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/Base64HeaderMessage.java b/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
similarity index 93%
rename from javatests/com/google/gerrit/server/mail/receive/data/Base64HeaderMessage.java
rename to javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
index 91dc6f1..aa19537 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/Base64HeaderMessage.java
+++ b/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/HtmlMimeMessage.java b/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
similarity index 96%
rename from javatests/com/google/gerrit/server/mail/receive/data/HtmlMimeMessage.java
rename to javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
index 756581f..1d68cc8 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/HtmlMimeMessage.java
+++ b/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/NonUTF8Message.java b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
similarity index 93%
rename from javatests/com/google/gerrit/server/mail/receive/data/NonUTF8Message.java
rename to javatests/com/google/gerrit/mail/data/NonUTF8Message.java
index 3fafd4b..32915e7 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/NonUTF8Message.java
+++ b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
@@ -11,10 +11,10 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/QuotedPrintableHeaderMessage.java b/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
similarity index 93%
rename from javatests/com/google/gerrit/server/mail/receive/data/QuotedPrintableHeaderMessage.java
rename to javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
index 2dc48b5..47e813a 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/QuotedPrintableHeaderMessage.java
+++ b/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/RawMailMessage.java b/javatests/com/google/gerrit/mail/data/RawMailMessage.java
similarity index 89%
rename from javatests/com/google/gerrit/server/mail/receive/data/RawMailMessage.java
rename to javatests/com/google/gerrit/mail/data/RawMailMessage.java
index 2af82ad..53c782c 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/RawMailMessage.java
+++ b/javatests/com/google/gerrit/mail/data/RawMailMessage.java
@@ -12,9 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.MailMessage;
import org.junit.Ignore;
/** Base class for all email parsing tests. */
diff --git a/javatests/com/google/gerrit/server/mail/receive/data/SimpleTextMessage.java b/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
similarity index 97%
rename from javatests/com/google/gerrit/server/mail/receive/data/SimpleTextMessage.java
rename to javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
index aa5b78a..a8f5b94 100644
--- a/javatests/com/google/gerrit/server/mail/receive/data/SimpleTextMessage.java
+++ b/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
@@ -12,10 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.mail.receive.data;
+package com.google.gerrit.mail.data;
-import com.google.gerrit.server.mail.Address;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
diff --git a/javatests/com/google/gerrit/server/BUILD b/javatests/com/google/gerrit/server/BUILD
index f405c28..569b0b9 100644
--- a/javatests/com/google/gerrit/server/BUILD
+++ b/javatests/com/google/gerrit/server/BUILD
@@ -41,6 +41,7 @@
"//java/com/google/gerrit/index",
"//java/com/google/gerrit/index:query_exception",
"//java/com/google/gerrit/lifecycle",
+ "//java/com/google/gerrit/mail",
"//java/com/google/gerrit/metrics",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
diff --git a/javatests/com/google/gerrit/server/index/change/StalenessCheckerTest.java b/javatests/com/google/gerrit/server/index/change/StalenessCheckerTest.java
index acb33e9..51bda66 100644
--- a/javatests/com/google/gerrit/server/index/change/StalenessCheckerTest.java
+++ b/javatests/com/google/gerrit/server/index/change/StalenessCheckerTest.java
@@ -24,11 +24,11 @@
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ListMultimap;
+import com.google.gerrit.index.RefState;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.index.RefState;
import com.google.gerrit.server.index.change.StalenessChecker.RefStatePattern;
import com.google.gerrit.server.notedb.NoteDbChangeState;
import com.google.gerrit.testing.GerritBaseTests;
diff --git a/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java b/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java
new file mode 100644
index 0000000..9bb6951
--- /dev/null
+++ b/javatests/com/google/gerrit/server/ioutil/HexFormatTest.java
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 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.ioutil;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class HexFormatTest {
+
+ @Test
+ public void fromInt() {
+ assertEquals("0000000f", HexFormat.fromInt(0xf));
+ assertEquals("801234ab", HexFormat.fromInt(0x801234ab));
+ assertEquals("deadbeef", HexFormat.fromInt(0xdeadbeef));
+ }
+}
diff --git a/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java b/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
index a7234f4..f8a613a 100644
--- a/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
+++ b/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
@@ -16,7 +16,8 @@
import static com.google.common.truth.Truth.assertThat;
-import com.google.gerrit.server.mail.receive.MailMessage;
+import com.google.gerrit.mail.Address;
+import com.google.gerrit.mail.MailMessage;
import com.google.gerrit.testing.GerritBaseTests;
import java.time.Instant;
import org.junit.Test;
diff --git a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
index 7028bb2..f99c356 100644
--- a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
@@ -22,12 +22,12 @@
import static org.easymock.EasyMock.verify;
import com.google.gerrit.common.TimeUtil;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
-import com.google.gerrit.server.mail.Address;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 3d65eae..574f6ac 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -30,6 +30,7 @@
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.common.data.SubmitRequirement;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -47,7 +48,6 @@
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerByEmailSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerSetEntryProto;
import com.google.gerrit.server.cache.proto.Cache.ChangeNotesStateProto.ReviewerStatusUpdateProto;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotesState.ChangeColumns;
import com.google.gerrit.server.notedb.ChangeNotesState.Serializer;
import com.google.gwtorm.client.KeyUtil;
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 3a98127..852c8bc 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -35,6 +35,7 @@
import com.google.common.collect.Lists;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
@@ -50,7 +51,6 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
import com.google.gerrit.server.util.RequestId;
import com.google.gerrit.testing.TestChanges;
diff --git a/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java b/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
index a5c4e49..2e19d20 100644
--- a/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
@@ -33,15 +33,15 @@
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.update.RefUpdateUtil;
+import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.notedb.CommentJsonMigrator.ProjectMigrationResult;
import com.google.gerrit.testing.TestChanges;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
+import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -57,13 +57,14 @@
@Inject private ChangeNoteUtil noteUtil;
@Inject private CommentsUtil commentsUtil;
@Inject private LegacyChangeNoteWrite legacyChangeNoteWrite;
+ @Inject private AllUsersName allUsersName;
private AtomicInteger uuidCounter;
@Before
public void setUpCounter() {
uuidCounter = new AtomicInteger();
- migrator = new CommentJsonMigrator(new ChangeNoteJson(), "gerrit");
+ migrator = new CommentJsonMigrator(new ChangeNoteJson(), "gerrit", allUsersName);
}
@Test
@@ -90,7 +91,7 @@
getRevId(notes, 2), ps2Comment.toString());
ChangeNotes oldNotes = notes;
- migrate(project, migrator::migrateChanges, 0);
+ checkMigrate(project, ImmutableList.of());
assertNoDifferences(notes, oldNotes);
assertThat(notes.getMetaId()).isEqualTo(oldNotes.getMetaId());
}
@@ -163,7 +164,7 @@
.containsExactly(ps1Comment1.key, true, ps1Comment2.key, true, ps2Comment1.key, true);
ChangeNotes oldNotes = notes;
- migrate(project, migrator::migrateChanges, 1);
+ checkMigrate(project, ImmutableList.of(RefNames.changeMetaRef(c.getId())));
// Comment content is the same.
notes = newNotes(c);
@@ -265,7 +266,11 @@
.containsExactly(otherCommentPs1.key, true);
ChangeNotes oldNotes = notes;
- migrate(allUsers, migrator::migrateDrafts, 2);
+ checkMigrate(
+ allUsers,
+ ImmutableList.of(
+ RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()),
+ RefNames.refsDraftComments(c.getId(), otherUser.getAccountId())));
assertNoDifferences(notes, oldNotes);
// Migration doesn't touch change ref.
@@ -366,7 +371,7 @@
.containsExactly(ps1Comment.key, true, ps2Comment.key, false, ps3Comment.key, true);
ChangeNotes oldNotes = notes;
- migrate(project, migrator::migrateChanges, 1);
+ checkMigrate(project, ImmutableList.of(RefNames.changeMetaRef(c.getId())));
assertNoDifferences(notes, oldNotes);
// Comment content is the same.
@@ -391,30 +396,12 @@
.containsExactly(ps1Comment.key, false, ps2Comment.key, false, ps3Comment.key, false);
}
- @FunctionalInterface
- interface MigrateFunction {
- boolean call(
- Project.NameKey project,
- Repository repo,
- RevWalk rw,
- ObjectInserter ins,
- BatchRefUpdate bru)
- throws Exception;
- }
+ private void checkMigrate(Project.NameKey project, List<String> expectedRefs) throws Exception {
+ try (Repository repo = repoManager.openRepository(project)) {
+ ProjectMigrationResult progress = migrator.migrateProject(project, repo, false);
- private void migrate(Project.NameKey project, MigrateFunction func, int expectedCommands)
- throws Exception {
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo);
- ObjectInserter ins = repo.newObjectInserter()) {
- BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
- bru.setAllowNonFastForwards(true);
- assertThat(func.call(project, repo, rw, ins, bru)).isTrue();
- assertThat(bru.getCommands()).hasSize(expectedCommands);
- if (!bru.getCommands().isEmpty()) {
- ins.flush();
- RefUpdateUtil.executeChecked(bru, rw);
- }
+ assertThat(progress.ok).isTrue();
+ assertThat(progress.refsUpdated).isEqualTo(expectedRefs);
}
}
diff --git a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
index db7035b..963546f 100644
--- a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
@@ -20,10 +20,10 @@
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.TimeUtil;
+import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.mail.Address;
import com.google.gerrit.server.util.RequestId;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.TestChanges;
diff --git a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index bc3c9a9..3d9d661 100644
--- a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -541,17 +541,19 @@
@Test
public void withSecondaryEmailsWithoutModifyAccountCapability() throws Exception {
- AccountInfo user = newAccount("myuser", "My User", "abc@example.com", true);
+ AccountInfo user = newAccount("myuser", "My User", "other@example.com", true);
+
+ AccountInfo otherUser = newAccount("otheruser", "Other User", "abc@example.com", true);
String[] secondaryEmails = new String[] {"dfg@example.com", "hij@example.com"};
- addEmails(user, secondaryEmails);
+ addEmails(otherUser, secondaryEmails);
requestContext.setContext(newRequestContext(new Account.Id(user._accountId)));
- List<AccountInfo> result = newQuery(user.username).withSuggest(true).get();
+ List<AccountInfo> result = newQuery(otherUser.username).withSuggest(true).get();
assertThat(result.get(0).secondaryEmails).isNull();
exception.expect(AuthException.class);
- newQuery(user.username).withOption(ListAccountsOption.ALL_EMAILS).get();
+ newQuery(otherUser.username).withOption(ListAccountsOption.ALL_EMAILS).get();
}
@Test
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index cf85aeb..0ff16bb 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -831,7 +831,13 @@
ChangeInserter ins4 = newChangeWithTopic(repo, "feature2-fixup");
Change change4 = insert(repo, ins4);
- Change change5 = insert(repo, newChange(repo));
+ ChangeInserter ins5 = newChangeWithTopic(repo, "https://gerrit.local");
+ Change change5 = insert(repo, ins5);
+
+ ChangeInserter ins6 = newChangeWithTopic(repo, "git_gerrit_training");
+ Change change6 = insert(repo, ins6);
+
+ Change change_no_topic = insert(repo, newChange(repo));
assertQuery("intopic:foo");
assertQuery("intopic:feature1", change1);
@@ -839,8 +845,9 @@
assertQuery("topic:feature2", change2);
assertQuery("intopic:feature2", change4, change3, change2);
assertQuery("intopic:fixup", change4);
- assertQuery("topic:\"\"", change5);
- assertQuery("intopic:\"\"", change5);
+ assertQuery("intopic:gerrit", change6, change5);
+ assertQuery("topic:\"\"", change_no_topic);
+ assertQuery("intopic:\"\"", change_no_topic);
}
@Test
@@ -899,6 +906,14 @@
}
@Test
+ public void byMessageSubstring() throws Exception {
+ TestRepository<Repo> repo = createProject("repo");
+ RevCommit commit1 = repo.parseBody(repo.commit().message("https://gerrit.local").create());
+ Change change1 = insert(repo, newChangeForCommit(repo, commit1));
+ assertQuery("message:gerrit", change1);
+ }
+
+ @Test
public void byLabel() throws Exception {
accountManager.authenticate(AuthRequest.forUser("anotheruser"));
TestRepository<Repo> repo = createProject("repo");
diff --git a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
index e34746c..2eec006 100644
--- a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
@@ -15,15 +15,21 @@
package com.google.gerrit.server.query.project;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.TruthJUnit.assume;
import static java.util.stream.Collectors.toList;
import com.google.common.base.CharMatcher;
import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.projects.ConfigInput;
import com.google.gerrit.extensions.api.projects.ProjectInput;
import com.google.gerrit.extensions.api.projects.Projects.QueryRequest;
+import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ProjectInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.index.Schema;
+import com.google.gerrit.index.project.ProjectData;
+import com.google.gerrit.index.project.ProjectIndexCollection;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
@@ -38,7 +44,6 @@
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
@@ -83,7 +88,7 @@
@Inject protected OneOffRequestContext oneOffRequestContext;
- @Inject protected InternalAccountQuery internalAccountQuery;
+ @Inject protected ProjectIndexCollection indexes;
@Inject protected AllProjectsName allProjects;
@@ -211,6 +216,30 @@
}
@Test
+ public void byState() throws Exception {
+ assume().that(getSchemaVersion() >= 2).isTrue();
+
+ ProjectInfo project1 = createProjectWithState(name("project1"), ProjectState.ACTIVE);
+ ProjectInfo project2 = createProjectWithState(name("project2"), ProjectState.READ_ONLY);
+ assertQuery("state:active", project1);
+ assertQuery("state:read-only", project2);
+ }
+
+ @Test
+ public void byState_emptyQuery() throws Exception {
+ exception.expect(BadRequestException.class);
+ exception.expectMessage("state operator requires a value");
+ assertQuery("state:\"\"");
+ }
+
+ @Test
+ public void byState_badQuery() throws Exception {
+ exception.expect(BadRequestException.class);
+ exception.expectMessage("state operator must be either 'active' or 'read-only'");
+ assertQuery("state:bla");
+ }
+
+ @Test
public void byDefaultField() throws Exception {
ProjectInfo project1 = createProject(name("foo-project"));
ProjectInfo project2 = createProject(name("project2"));
@@ -291,6 +320,14 @@
return gApi.projects().create(in).get();
}
+ protected ProjectInfo createProjectWithState(String name, ProjectState state) throws Exception {
+ ProjectInfo info = createProject(name);
+ ConfigInput config = new ConfigInput();
+ config.state = state;
+ gApi.projects().name(info.name).config(config);
+ return info;
+ }
+
protected ProjectInfo getProject(Project.NameKey nameKey) throws Exception {
return gApi.projects().name(nameKey.get()).get();
}
@@ -354,6 +391,14 @@
return b.toString();
}
+ protected int getSchemaVersion() {
+ return getSchema().getVersion();
+ }
+
+ protected Schema<ProjectData> getSchema() {
+ return indexes.getSearchIndex().getSchema();
+ }
+
protected static Iterable<String> names(ProjectInfo... projects) {
return names(Arrays.asList(projects));
}
diff --git a/javatests/com/google/gerrit/server/query/project/BUILD b/javatests/com/google/gerrit/server/query/project/BUILD
index eaa3df3..f0c455e 100644
--- a/javatests/com/google/gerrit/server/query/project/BUILD
+++ b/javatests/com/google/gerrit/server/query/project/BUILD
@@ -9,6 +9,8 @@
visibility = ["//visibility:public"],
deps = [
"//java/com/google/gerrit/extensions:api",
+ "//java/com/google/gerrit/index",
+ "//java/com/google/gerrit/index/project",
"//java/com/google/gerrit/lifecycle",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/server",
diff --git a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java b/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
index a6178ac..ead824f 100644
--- a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
+++ b/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
@@ -542,6 +542,8 @@
public void combineWithBatchGroupNameNotes() throws Exception {
AccountGroup g1 = newGroup("a");
AccountGroup g2 = newGroup("b");
+ GroupReference gr1 = new GroupReference(g1.getGroupUUID(), g1.getName());
+ GroupReference gr2 = new GroupReference(g2.getGroupUUID(), g2.getName());
GroupBundle b1 = builder().group(g1).build();
GroupBundle b2 = builder().group(g2).build();
@@ -551,8 +553,7 @@
rebuilder.rebuild(repo, b1, bru);
rebuilder.rebuild(repo, b2, bru);
try (ObjectInserter inserter = repo.newObjectInserter()) {
- ImmutableList<GroupReference> refs =
- ImmutableList.of(GroupReference.forGroup(g1), GroupReference.forGroup(g2));
+ ImmutableList<GroupReference> refs = ImmutableList.of(gr1, gr2);
GroupNameNotes.updateAllGroups(repo, inserter, bru, refs, newPersonIdent());
inserter.flush();
}
@@ -569,9 +570,7 @@
assertMigratedCleanly(reload(g1), b1);
assertMigratedCleanly(reload(g2), b2);
- GroupReference group1 = GroupReference.forGroup(g1);
- GroupReference group2 = GroupReference.forGroup(g2);
- assertThat(GroupNameNotes.loadAllGroups(repo)).containsExactly(group1, group2);
+ assertThat(GroupNameNotes.loadAllGroups(repo)).containsExactly(gr1, gr2);
}
@Test
diff --git a/javatests/com/google/gerrit/server/util/IdGeneratorTest.java b/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
index 39afcac..808eca8 100644
--- a/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
+++ b/javatests/com/google/gerrit/server/util/IdGeneratorTest.java
@@ -34,11 +34,4 @@
assertEquals(0xdeadbeef, IdGenerator.unmix(IdGenerator.mix(0xdeadbeef)));
assertEquals(0x0b966b11, IdGenerator.unmix(IdGenerator.mix(0x0b966b11)));
}
-
- @Test
- public void format() {
- assertEquals("0000000f", IdGenerator.format(0xf));
- assertEquals("801234ab", IdGenerator.format(0x801234ab));
- assertEquals("deadbeef", IdGenerator.format(0xdeadbeef));
- }
}
diff --git a/javatests/com/google/gerrit/server/util/git/BUILD b/javatests/com/google/gerrit/server/util/git/BUILD
new file mode 100644
index 0000000..928705c
--- /dev/null
+++ b/javatests/com/google/gerrit/server/util/git/BUILD
@@ -0,0 +1,32 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+
+junit_tests(
+ name = "git_tests",
+ size = "small",
+ srcs = glob(
+ ["**/*.java"],
+ ),
+ visibility = ["//visibility:public"],
+ deps = [
+ "//java/com/google/gerrit/reviewdb:server",
+ "//java/com/google/gerrit/server/util/git",
+ "//java/com/google/gerrit/truth",
+ "//java/org/eclipse/jgit:server",
+ "//lib:grappa",
+ "//lib:gson",
+ "//lib:guava",
+ "//lib:guava-retrying",
+ "//lib:gwtorm",
+ "//lib:protobuf",
+ "//lib/auto:auto-value",
+ "//lib/auto:auto-value-annotations",
+ "//lib/commons:codec",
+ "//lib/guice",
+ "//lib/jgit/org.eclipse.jgit:jgit",
+ "//lib/jgit/org.eclipse.jgit.junit:junit",
+ "//lib/truth",
+ "//lib/truth:truth-java8-extension",
+ "//lib/truth:truth-proto-extension",
+ "//proto:cache_java_proto",
+ ],
+)
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSectionParserIT.java b/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
similarity index 91%
rename from javatests/com/google/gerrit/acceptance/git/SubmoduleSectionParserIT.java
rename to javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
index d0225c7..0ec9b38 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSectionParserIT.java
+++ b/javatests/com/google/gerrit/server/util/git/SubmoduleSectionParserTest.java
@@ -12,26 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.acceptance.git;
+package com.google.gerrit.server.util.git;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.Sets;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
-import com.google.gerrit.server.util.SubmoduleSectionParser;
import java.util.Set;
import org.eclipse.jgit.lib.Config;
import org.junit.Test;
-public class SubmoduleSectionParserIT extends AbstractDaemonTest {
+public class SubmoduleSectionParserTest {
private static final String THIS_SERVER = "http://localhost/";
@Test
public void followMasterBranch() throws Exception {
- Project.NameKey p = createProject("a");
+ Project.NameKey p = new Project.NameKey("proj");
Config cfg = new Config();
cfg.fromText(
""
@@ -56,7 +54,7 @@
@Test
public void followMatchingBranch() throws Exception {
- Project.NameKey p = createProject("a");
+ Project.NameKey p = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -92,7 +90,7 @@
@Test
public void followAnotherBranch() throws Exception {
- Project.NameKey p = createProject("a");
+ Project.NameKey p = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -117,7 +115,7 @@
@Test
public void withAnotherURI() throws Exception {
- Project.NameKey p = createProject("a");
+ Project.NameKey p = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -142,7 +140,7 @@
@Test
public void withSlashesInProjectName() throws Exception {
- Project.NameKey p = createProject("project/with/slashes/a");
+ Project.NameKey p = new Project.NameKey("project/with/slashes/a");
Config cfg = new Config();
cfg.fromText(
""
@@ -167,7 +165,7 @@
@Test
public void withSlashesInPath() throws Exception {
- Project.NameKey p = createProject("a");
+ Project.NameKey p = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -192,8 +190,8 @@
@Test
public void withMoreSections() throws Exception {
- Project.NameKey p1 = createProject("a");
- Project.NameKey p2 = createProject("b");
+ Project.NameKey p1 = new Project.NameKey("a");
+ Project.NameKey p2 = new Project.NameKey("b");
Config cfg = new Config();
cfg.fromText(
""
@@ -225,8 +223,8 @@
@Test
public void withSubProjectFound() throws Exception {
- Project.NameKey p1 = createProject("a/b");
- Project.NameKey p2 = createProject("b");
+ Project.NameKey p1 = new Project.NameKey("a/b");
+ Project.NameKey p2 = new Project.NameKey("b");
Config cfg = new Config();
cfg.fromText(
"\n"
@@ -258,10 +256,10 @@
@Test
public void withAnInvalidSection() throws Exception {
- Project.NameKey p1 = createProject("a");
- Project.NameKey p2 = createProject("b");
- Project.NameKey p3 = createProject("d");
- Project.NameKey p4 = createProject("e");
+ Project.NameKey p1 = new Project.NameKey("a");
+ Project.NameKey p2 = new Project.NameKey("b");
+ Project.NameKey p3 = new Project.NameKey("d");
+ Project.NameKey p4 = new Project.NameKey("e");
Config cfg = new Config();
cfg.fromText(
"\n"
@@ -328,7 +326,7 @@
@Test
public void withSectionToOtherServer() throws Exception {
- Project.NameKey p1 = createProject("a");
+ Project.NameKey p1 = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -349,7 +347,7 @@
@Test
public void withRelativeURI() throws Exception {
- Project.NameKey p1 = createProject("a");
+ Project.NameKey p1 = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -374,7 +372,7 @@
@Test
public void withDeepRelativeURI() throws Exception {
- Project.NameKey p1 = createProject("a");
+ Project.NameKey p1 = new Project.NameKey("a");
Config cfg = new Config();
cfg.fromText(
""
@@ -400,7 +398,7 @@
@Test
public void withOverlyDeepRelativeURI() throws Exception {
- Project.NameKey p1 = createProject("nested/a");
+ Project.NameKey p1 = new Project.NameKey("nested/a");
Config cfg = new Config();
cfg.fromText(
""
diff --git a/lib/codemirror/cm.bzl b/lib/codemirror/cm.bzl
index 5088a05..593caa3 100644
--- a/lib/codemirror/cm.bzl
+++ b/lib/codemirror/cm.bzl
@@ -234,126 +234,142 @@
DIFF_MATCH_PATCH_VERSION)
def pkg_cm():
- for archive, suffix, top, license in [
- ('@codemirror-original-gwt//jar', '', TOP, LICENSE),
- ('@codemirror-minified-gwt//jar', '_r', TOP_MINIFIED, LICENSE_MINIFIED)
- ]:
- # Main JavaScript and addons
- genrule2(
- name = 'cm' + suffix,
- cmd = ' && '.join([
- "echo '/** @license' >$@",
- 'unzip -p $(location %s) %s/LICENSE >>$@' % (archive, top),
- "echo '*/' >>$@",
- ] +
- ['unzip -p $(location %s) %s/%s >>$@' % (archive, top, n) for n in CM_JS] +
- ['unzip -p $(location %s) %s/addon/%s >>$@' % (archive, top, n)
- for n in CM_ADDONS]
- ),
- tools = [archive],
- outs = ['cm%s.js' % suffix],
- )
+ for archive, suffix, top, license in [
+ ("@codemirror-original-gwt//jar", "", TOP, LICENSE),
+ ("@codemirror-minified-gwt//jar", "_r", TOP_MINIFIED, LICENSE_MINIFIED),
+ ]:
+ # Main JavaScript and addons
+ genrule2(
+ name = "cm" + suffix,
+ cmd = " && ".join(
+ [
+ "echo '/** @license' >$@",
+ "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
+ "echo '*/' >>$@",
+ ] +
+ ["unzip -p $(location %s) %s/%s >>$@" % (archive, top, n) for n in CM_JS] +
+ [
+ "unzip -p $(location %s) %s/addon/%s >>$@" % (archive, top, n)
+ for n in CM_ADDONS
+ ],
+ ),
+ tools = [archive],
+ outs = ["cm%s.js" % suffix],
+ )
- # Main CSS
- genrule2(
- name = 'css' + suffix,
- cmd = ' && '.join([
- "echo '/** @license' >$@",
- 'unzip -p $(location %s) %s/LICENSE >>$@' % (archive, top),
- "echo '*/' >>$@",
- ] +
- ['unzip -p $(location %s) %s/%s >>$@' % (archive, top, n)
- for n in CM_CSS]
- ),
- tools = [archive],
- outs = ['cm%s.css' % suffix],
- )
+ # Main CSS
+ genrule2(
+ name = "css" + suffix,
+ cmd = " && ".join(
+ [
+ "echo '/** @license' >$@",
+ "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
+ "echo '*/' >>$@",
+ ] +
+ [
+ "unzip -p $(location %s) %s/%s >>$@" % (archive, top, n)
+ for n in CM_CSS
+ ],
+ ),
+ tools = [archive],
+ outs = ["cm%s.css" % suffix],
+ )
- # Modes
- for n in CM_MODES:
- genrule2(
- name = 'mode_%s%s' % (n, suffix),
- cmd = ' && '.join([
- "echo '/** @license' >$@",
- 'unzip -p $(location %s) %s/LICENSE >>$@' % (archive, top),
- "echo '*/' >>$@",
- 'unzip -p $(location %s) %s/mode/%s/%s.js >>$@' % (archive, top, n, n),
- ]
- ),
- tools = [archive],
- outs = ['mode_%s%s.js' % (n, suffix)],
- )
+ # Modes
+ for n in CM_MODES:
+ genrule2(
+ name = "mode_%s%s" % (n, suffix),
+ cmd = " && ".join(
+ [
+ "echo '/** @license' >$@",
+ "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
+ "echo '*/' >>$@",
+ "unzip -p $(location %s) %s/mode/%s/%s.js >>$@" % (archive, top, n, n),
+ ],
+ ),
+ tools = [archive],
+ outs = ["mode_%s%s.js" % (n, suffix)],
+ )
- # Themes
- for n in CM_THEMES:
- genrule2(
- name = 'theme_%s%s' % (n, suffix),
- cmd = ' && '.join([
- "echo '/** @license' >$@",
- 'unzip -p $(location %s) %s/LICENSE >>$@' % (archive, top),
- "echo '*/' >>$@",
- 'unzip -p $(location %s) %s/theme/%s.css >>$@' % (archive, top, n)
- ]
- ),
- tools = [archive],
- outs = ['theme_%s%s.css' % (n, suffix)],
- )
+ # Themes
+ for n in CM_THEMES:
+ genrule2(
+ name = "theme_%s%s" % (n, suffix),
+ cmd = " && ".join(
+ [
+ "echo '/** @license' >$@",
+ "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
+ "echo '*/' >>$@",
+ "unzip -p $(location %s) %s/theme/%s.css >>$@" % (archive, top, n),
+ ],
+ ),
+ tools = [archive],
+ outs = ["theme_%s%s.css" % (n, suffix)],
+ )
- # Merge Addon bundled with diff-match-patch
- genrule2(
- name = 'addon_merge_with_diff_match_patch%s' % suffix,
- cmd = ' && '.join([
- "echo '/** @license' >$@",
- 'unzip -p $(location %s) %s/LICENSE >>$@' % (archive, top),
- "echo '*/\n' >>$@",
- "echo '// The google-diff-match-patch library is from https://repo1.maven.org/maven2/org/webjars/google-diff-match-patch/%s/google-diff-match-patch-%s.jar\n' >> $@" % (DIFF_MATCH_PATCH_VERSION, DIFF_MATCH_PATCH_VERSION),
- "echo '/** @license' >>$@",
- "echo 'LICENSE-Apache2.0' >>$@",
- "echo '*/' >>$@",
- 'unzip -p $(location @diff-match-patch//jar) %s/diff_match_patch.js >>$@' % DIFF_MATCH_PATCH_TOP,
- "echo ';' >> $@",
- 'unzip -p $(location %s) %s/addon/merge/merge.js >>$@' % (archive, top)
- ]
- ),
- tools = [
- '@diff-match-patch//jar',
- # dependency just for license tracking.
- ':diff-match-patch',
- archive,
- "//lib:LICENSE-Apache2.0",
- ],
- outs = ['addon_merge_with_diff_match_patch%s.js' % suffix],
- )
+ # Merge Addon bundled with diff-match-patch
+ genrule2(
+ name = "addon_merge_with_diff_match_patch%s" % suffix,
+ cmd = " && ".join(
+ [
+ "echo '/** @license' >$@",
+ "unzip -p $(location %s) %s/LICENSE >>$@" % (archive, top),
+ "echo '*/\n' >>$@",
+ "echo '// The google-diff-match-patch library is from https://repo1.maven.org/maven2/org/webjars/google-diff-match-patch/%s/google-diff-match-patch-%s.jar\n' >> $@" % (DIFF_MATCH_PATCH_VERSION, DIFF_MATCH_PATCH_VERSION),
+ "echo '/** @license' >>$@",
+ "echo 'LICENSE-Apache2.0' >>$@",
+ "echo '*/' >>$@",
+ "unzip -p $(location @diff-match-patch//jar) %s/diff_match_patch.js >>$@" % DIFF_MATCH_PATCH_TOP,
+ "echo ';' >> $@",
+ "unzip -p $(location %s) %s/addon/merge/merge.js >>$@" % (archive, top),
+ ],
+ ),
+ tools = [
+ "@diff-match-patch//jar",
+ # dependency just for license tracking.
+ ":diff-match-patch",
+ archive,
+ "//lib:LICENSE-Apache2.0",
+ ],
+ outs = ["addon_merge_with_diff_match_patch%s.js" % suffix],
+ )
- # Jar packaging
- genrule2(
- name = 'jar' + suffix,
- cmd = ' && '.join([
- 'cd $$TMP',
- 'mkdir -p net/codemirror/{addon,lib,mode,theme}',
- 'cp $$ROOT/$(location :css%s) net/codemirror/lib/cm.css' % suffix,
- 'cp $$ROOT/$(location :cm%s) net/codemirror/lib/cm.js' % suffix]
- + ['cp $$ROOT/$(location :mode_%s%s) net/codemirror/mode/%s.js' % (n, suffix, n)
- for n in CM_MODES]
- + ['cp $$ROOT/$(location :theme_%s%s) net/codemirror/theme/%s.css' % (n, suffix, n)
- for n in CM_THEMES]
- + ['cp $$ROOT/$(location :addon_merge_with_diff_match_patch%s) net/codemirror/addon/merge_bundled.js' % suffix]
- + ['zip -qr $$ROOT/$@ net/codemirror/{addon,lib,mode,theme}']),
- tools = [
- ':addon_merge_with_diff_match_patch%s' % suffix,
- ':cm%s' % suffix,
- ':css%s' % suffix,
- ] + [
- ':mode_%s%s' % (n, suffix) for n in CM_MODES
- ] + [
- ':theme_%s%s' % (n, suffix) for n in CM_THEMES
- ],
- outs = ['codemirror%s.jar' % suffix],
- )
+ # Jar packaging
+ genrule2(
+ name = "jar" + suffix,
+ cmd = " && ".join([
+ "cd $$TMP",
+ "mkdir -p net/codemirror/{addon,lib,mode,theme}",
+ "cp $$ROOT/$(location :css%s) net/codemirror/lib/cm.css" % suffix,
+ "cp $$ROOT/$(location :cm%s) net/codemirror/lib/cm.js" % suffix,
+ ] +
+ [
+ "cp $$ROOT/$(location :mode_%s%s) net/codemirror/mode/%s.js" % (n, suffix, n)
+ for n in CM_MODES
+ ] +
+ [
+ "cp $$ROOT/$(location :theme_%s%s) net/codemirror/theme/%s.css" % (n, suffix, n)
+ for n in CM_THEMES
+ ] +
+ ["cp $$ROOT/$(location :addon_merge_with_diff_match_patch%s) net/codemirror/addon/merge_bundled.js" % suffix] +
+ ["zip -qr $$ROOT/$@ net/codemirror/{addon,lib,mode,theme}"]),
+ tools = [
+ ":addon_merge_with_diff_match_patch%s" % suffix,
+ ":cm%s" % suffix,
+ ":css%s" % suffix,
+ ] + [
+ ":mode_%s%s" % (n, suffix)
+ for n in CM_MODES
+ ] + [
+ ":theme_%s%s" % (n, suffix)
+ for n in CM_THEMES
+ ],
+ outs = ["codemirror%s.jar" % suffix],
+ )
- native.java_import(
- name = 'codemirror' + suffix,
- jars = [':jar%s' % suffix],
- visibility = ['//visibility:public'],
- data = [license],
- )
+ native.java_import(
+ name = "codemirror" + suffix,
+ jars = [":jar%s" % suffix],
+ visibility = ["//visibility:public"],
+ data = [license],
+ )
diff --git a/lib/jgit/jgit.bzl b/lib/jgit/jgit.bzl
index adf2d4f8..384469c 100644
--- a/lib/jgit/jgit.bzl
+++ b/lib/jgit/jgit.bzl
@@ -1,8 +1,8 @@
-load("//tools/bzl:maven_jar.bzl", "GERRIT", "MAVEN_LOCAL", "MAVEN_CENTRAL", "maven_jar")
+load("//tools/bzl:maven_jar.bzl", "GERRIT", "MAVEN_CENTRAL", "MAVEN_LOCAL", "maven_jar")
_JGIT_VERS = "5.0.1.201806211838-r"
-_DOC_VERS = "5.0.0.201806131550-r" # Set to _JGIT_VERS unless using a snapshot
+_DOC_VERS = _JGIT_VERS # Set to _JGIT_VERS unless using a snapshot
JGIT_DOC_URL = "http://download.eclipse.org/jgit/site/" + _DOC_VERS + "/apidocs"
@@ -13,13 +13,13 @@
LOCAL_JGIT_REPO = ""
def jgit_repos():
- if LOCAL_JGIT_REPO:
- native.local_repository(
- name = "jgit",
- path = LOCAL_JGIT_REPO,
- )
- else:
- jgit_maven_repos()
+ if LOCAL_JGIT_REPO:
+ native.local_repository(
+ name = "jgit",
+ path = LOCAL_JGIT_REPO,
+ )
+ else:
+ jgit_maven_repos()
def jgit_maven_repos():
maven_jar(
@@ -52,15 +52,15 @@
)
def jgit_dep(name):
- mapping = {
- "@jgit-junit//jar": "@jgit//org.eclipse.jgit.junit:junit",
- "@jgit-lib//jar:src": "@jgit//org.eclipse.jgit:libjgit-src.jar",
- "@jgit-lib//jar": "@jgit//org.eclipse.jgit:jgit",
- "@jgit-servlet//jar":"@jgit//org.eclipse.jgit.http.server:jgit-servlet",
- "@jgit-archive//jar": "@jgit//org.eclipse.jgit.archive:jgit-archive",
- }
+ mapping = {
+ "@jgit-junit//jar": "@jgit//org.eclipse.jgit.junit:junit",
+ "@jgit-lib//jar:src": "@jgit//org.eclipse.jgit:libjgit-src.jar",
+ "@jgit-lib//jar": "@jgit//org.eclipse.jgit:jgit",
+ "@jgit-servlet//jar": "@jgit//org.eclipse.jgit.http.server:jgit-servlet",
+ "@jgit-archive//jar": "@jgit//org.eclipse.jgit.archive:jgit-archive",
+ }
- if LOCAL_JGIT_REPO:
- return mapping[name]
- else:
- return name
+ if LOCAL_JGIT_REPO:
+ return mapping[name]
+ else:
+ return name
diff --git a/lib/js/bower_archives.bzl b/lib/js/bower_archives.bzl
index 6b4e003..75c8277 100644
--- a/lib/js/bower_archives.bzl
+++ b/lib/js/bower_archives.bzl
@@ -7,138 +7,165 @@
load("//tools/bzl:js.bzl", "bower_archive")
def load_bower_archives():
- bower_archive(
- name = "accessibility-developer-tools",
- package = "accessibility-developer-tools",
- version = "2.12.0",
- sha1 = "88ae82dcdeb6c658f76eff509d0ee425cae14d49")
- bower_archive(
- name = "async",
- package = "async",
- version = "1.5.2",
- sha1 = "1ec975d3b3834646a7e3d4b7e68118b90ed72508")
- bower_archive(
- name = "chai",
- package = "chai",
- version = "3.5.0",
- sha1 = "849ad3ee7c77506548b7b5db603a4e150b9431aa")
- bower_archive(
- name = "font-roboto",
- package = "PolymerElements/font-roboto",
- version = "1.1.0",
- sha1 = "ab4218d87b9ce569d6282b01f7642e551879c3d5")
- bower_archive(
- name = "iron-a11y-announcer",
- package = "PolymerElements/iron-a11y-announcer",
- version = "1.0.6",
- sha1 = "14aed1e1b300ea344e80362e875919ea3d104dcc")
- bower_archive(
- name = "iron-a11y-keys-behavior",
- package = "PolymerElements/iron-a11y-keys-behavior",
- version = "1.1.9",
- sha1 = "f58358ee652c67e6e721364ba50fb77a2ece1465")
- bower_archive(
- name = "iron-behaviors",
- package = "PolymerElements/iron-behaviors",
- version = "1.0.18",
- sha1 = "e231a1a02b090f5183db917639fdb96cdd0dca18")
- bower_archive(
- name = "iron-checked-element-behavior",
- package = "PolymerElements/iron-checked-element-behavior",
- version = "1.0.6",
- sha1 = "93ad3554cec119d8c5732d1c722ad113e1866370")
- bower_archive(
- name = "iron-fit-behavior",
- package = "PolymerElements/iron-fit-behavior",
- version = "1.2.7",
- sha1 = "01c485fbf898307029bbb72ac7e132db1570a842")
- bower_archive(
- name = "iron-flex-layout",
- package = "PolymerElements/iron-flex-layout",
- version = "1.3.9",
- sha1 = "d987b924cf29fcfe4b393833e81fdc9f1e268796")
- bower_archive(
- name = "iron-form-element-behavior",
- package = "PolymerElements/iron-form-element-behavior",
- version = "1.0.7",
- sha1 = "7b5a79e02cc32f0918725dd26925d0df1e03ed12")
- bower_archive(
- name = "iron-menu-behavior",
- package = "PolymerElements/iron-menu-behavior",
- version = "2.1.1",
- sha1 = "1504997f6eb9aec490b855dadee473cac064f38c")
- bower_archive(
- name = "iron-meta",
- package = "PolymerElements/iron-meta",
- version = "1.1.3",
- sha1 = "f77eba3f6f6817f10bda33918bde8f963d450041")
- bower_archive(
- name = "iron-resizable-behavior",
- package = "polymerelements/iron-resizable-behavior",
- version = "1.0.6",
- sha1 = "719c2a8a1a784f8aefcdeef41fcc2e5a03518d9e")
- bower_archive(
- name = "iron-validatable-behavior",
- package = "PolymerElements/iron-validatable-behavior",
- version = "1.1.2",
- sha1 = "7111f34ff32e1510131dfbdb1eaa51bfa291e8be")
- bower_archive(
- name = "lodash",
- package = "lodash",
- version = "3.10.1",
- sha1 = "2f207a8293c4c554bf6cf071241f7a00dc513d3a")
- bower_archive(
- name = "mocha",
- package = "mocha",
- version = "3.5.3",
- sha1 = "c14f149821e4e96241b20f85134aa757b73038f1")
- bower_archive(
- name = "neon-animation",
- package = "polymerelements/neon-animation",
- version = "1.2.5",
- sha1 = "588d289f779d02b21ce5b676e257bbd6155649e8")
- bower_archive(
- name = "paper-behaviors",
- package = "PolymerElements/paper-behaviors",
- version = "1.0.13",
- sha1 = "a81eab28a952e124c208430e17508d9a1aae4ee7")
- bower_archive(
- name = "paper-icon-button",
- package = "PolymerElements/paper-icon-button",
- version = "2.2.0",
- sha1 = "9525e76ef433428bb9d6ec4fa65c4ef83156a803")
- bower_archive(
- name = "paper-ripple",
- package = "PolymerElements/paper-ripple",
- version = "1.0.10",
- sha1 = "21199db50d02b842da54bd6f4f1d1b10b474e893")
- bower_archive(
- name = "paper-styles",
- package = "PolymerElements/paper-styles",
- version = "1.3.1",
- sha1 = "4ee9c692366949a754e0e39f8031aa60ce66f24d")
- bower_archive(
- name = "sinon-chai",
- package = "sinon-chai",
- version = "2.14.0",
- sha1 = "78f0dc184efe47012a2b1b9a16a4289acf8300dc")
- bower_archive(
- name = "sinonjs",
- package = "sinonjs",
- version = "1.17.1",
- sha1 = "a26a6aab7358807de52ba738770f6ac709afd240")
- bower_archive(
- name = "stacky",
- package = "stacky",
- version = "1.3.2",
- sha1 = "d6c07a0112ab2e9677fe085933744466a89232fb")
- bower_archive(
- name = "web-animations-js",
- package = "web-animations/web-animations-js",
- version = "2.3.1",
- sha1 = "2ba5548d36188fe54555eaad0a576de4b027661e")
- bower_archive(
- name = "webcomponentsjs",
- package = "webcomponents/webcomponentsjs",
- version = "0.7.24",
- sha1 = "559227f8ee9db9bfbd81989f24510cc0c1bfc65c")
+ bower_archive(
+ name = "accessibility-developer-tools",
+ package = "accessibility-developer-tools",
+ version = "2.12.0",
+ sha1 = "88ae82dcdeb6c658f76eff509d0ee425cae14d49",
+ )
+ bower_archive(
+ name = "async",
+ package = "async",
+ version = "1.5.2",
+ sha1 = "1ec975d3b3834646a7e3d4b7e68118b90ed72508",
+ )
+ bower_archive(
+ name = "chai",
+ package = "chai",
+ version = "3.5.0",
+ sha1 = "849ad3ee7c77506548b7b5db603a4e150b9431aa",
+ )
+ bower_archive(
+ name = "font-roboto",
+ package = "PolymerElements/font-roboto",
+ version = "1.1.0",
+ sha1 = "ab4218d87b9ce569d6282b01f7642e551879c3d5",
+ )
+ bower_archive(
+ name = "iron-a11y-announcer",
+ package = "PolymerElements/iron-a11y-announcer",
+ version = "1.0.6",
+ sha1 = "14aed1e1b300ea344e80362e875919ea3d104dcc",
+ )
+ bower_archive(
+ name = "iron-a11y-keys-behavior",
+ package = "PolymerElements/iron-a11y-keys-behavior",
+ version = "1.1.9",
+ sha1 = "f58358ee652c67e6e721364ba50fb77a2ece1465",
+ )
+ bower_archive(
+ name = "iron-behaviors",
+ package = "PolymerElements/iron-behaviors",
+ version = "1.0.18",
+ sha1 = "e231a1a02b090f5183db917639fdb96cdd0dca18",
+ )
+ bower_archive(
+ name = "iron-checked-element-behavior",
+ package = "PolymerElements/iron-checked-element-behavior",
+ version = "1.0.6",
+ sha1 = "93ad3554cec119d8c5732d1c722ad113e1866370",
+ )
+ bower_archive(
+ name = "iron-fit-behavior",
+ package = "PolymerElements/iron-fit-behavior",
+ version = "1.2.7",
+ sha1 = "01c485fbf898307029bbb72ac7e132db1570a842",
+ )
+ bower_archive(
+ name = "iron-flex-layout",
+ package = "PolymerElements/iron-flex-layout",
+ version = "1.3.9",
+ sha1 = "d987b924cf29fcfe4b393833e81fdc9f1e268796",
+ )
+ bower_archive(
+ name = "iron-form-element-behavior",
+ package = "PolymerElements/iron-form-element-behavior",
+ version = "1.0.7",
+ sha1 = "7b5a79e02cc32f0918725dd26925d0df1e03ed12",
+ )
+ bower_archive(
+ name = "iron-menu-behavior",
+ package = "PolymerElements/iron-menu-behavior",
+ version = "2.1.1",
+ sha1 = "1504997f6eb9aec490b855dadee473cac064f38c",
+ )
+ bower_archive(
+ name = "iron-meta",
+ package = "PolymerElements/iron-meta",
+ version = "1.1.3",
+ sha1 = "f77eba3f6f6817f10bda33918bde8f963d450041",
+ )
+ bower_archive(
+ name = "iron-resizable-behavior",
+ package = "polymerelements/iron-resizable-behavior",
+ version = "1.0.6",
+ sha1 = "719c2a8a1a784f8aefcdeef41fcc2e5a03518d9e",
+ )
+ bower_archive(
+ name = "iron-validatable-behavior",
+ package = "PolymerElements/iron-validatable-behavior",
+ version = "1.1.2",
+ sha1 = "7111f34ff32e1510131dfbdb1eaa51bfa291e8be",
+ )
+ bower_archive(
+ name = "lodash",
+ package = "lodash",
+ version = "3.10.1",
+ sha1 = "2f207a8293c4c554bf6cf071241f7a00dc513d3a",
+ )
+ bower_archive(
+ name = "mocha",
+ package = "mocha",
+ version = "3.5.3",
+ sha1 = "c14f149821e4e96241b20f85134aa757b73038f1",
+ )
+ bower_archive(
+ name = "neon-animation",
+ package = "polymerelements/neon-animation",
+ version = "1.2.5",
+ sha1 = "588d289f779d02b21ce5b676e257bbd6155649e8",
+ )
+ bower_archive(
+ name = "paper-behaviors",
+ package = "PolymerElements/paper-behaviors",
+ version = "1.0.13",
+ sha1 = "a81eab28a952e124c208430e17508d9a1aae4ee7",
+ )
+ bower_archive(
+ name = "paper-icon-button",
+ package = "PolymerElements/paper-icon-button",
+ version = "2.2.0",
+ sha1 = "9525e76ef433428bb9d6ec4fa65c4ef83156a803",
+ )
+ bower_archive(
+ name = "paper-ripple",
+ package = "PolymerElements/paper-ripple",
+ version = "1.0.10",
+ sha1 = "21199db50d02b842da54bd6f4f1d1b10b474e893",
+ )
+ bower_archive(
+ name = "paper-styles",
+ package = "PolymerElements/paper-styles",
+ version = "1.3.1",
+ sha1 = "4ee9c692366949a754e0e39f8031aa60ce66f24d",
+ )
+ bower_archive(
+ name = "sinon-chai",
+ package = "sinon-chai",
+ version = "2.14.0",
+ sha1 = "78f0dc184efe47012a2b1b9a16a4289acf8300dc",
+ )
+ bower_archive(
+ name = "sinonjs",
+ package = "sinonjs",
+ version = "1.17.1",
+ sha1 = "a26a6aab7358807de52ba738770f6ac709afd240",
+ )
+ bower_archive(
+ name = "stacky",
+ package = "stacky",
+ version = "1.3.2",
+ sha1 = "d6c07a0112ab2e9677fe085933744466a89232fb",
+ )
+ bower_archive(
+ name = "web-animations-js",
+ package = "web-animations/web-animations-js",
+ version = "2.3.1",
+ sha1 = "2ba5548d36188fe54555eaad0a576de4b027661e",
+ )
+ bower_archive(
+ name = "webcomponentsjs",
+ package = "webcomponents/webcomponentsjs",
+ version = "0.7.24",
+ sha1 = "559227f8ee9db9bfbd81989f24510cc0c1bfc65c",
+ )
diff --git a/lib/js/bower_components.bzl b/lib/js/bower_components.bzl
index dc16ccf..a540828 100644
--- a/lib/js/bower_components.bzl
+++ b/lib/js/bower_components.bzl
@@ -7,377 +7,377 @@
load("//tools/bzl:js.bzl", "bower_component")
def define_bower_components():
- bower_component(
- name = "accessibility-developer-tools",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "async",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "chai",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "es6-promise",
- license = "//lib:LICENSE-es6-promise",
- seed = True,
- )
- bower_component(
- name = "fetch",
- license = "//lib:LICENSE-fetch",
- seed = True,
- )
- bower_component(
- name = "font-roboto",
- license = "//lib:LICENSE-polymer",
- )
- bower_component(
- name = "iron-a11y-announcer",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-a11y-keys-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-autogrow-textarea",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-flex-layout",
- ":iron-validatable-behavior",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-behaviors",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-keys-behavior",
- ":polymer",
- ],
- )
- bower_component(
- name = "iron-checked-element-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-form-element-behavior",
- ":iron-validatable-behavior",
- ":polymer",
- ],
- )
- bower_component(
- name = "iron-dropdown",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-overlay-behavior",
- ":iron-resizable-behavior",
- ":neon-animation",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-fit-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-flex-layout",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-form-element-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-icon",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-flex-layout",
- ":iron-meta",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-iconset-svg",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-meta",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-input",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-announcer",
- ":iron-validatable-behavior",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-menu-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-keys-behavior",
- ":iron-flex-layout",
- ":iron-selector",
- ":polymer",
- ],
- )
- bower_component(
- name = "iron-meta",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-overlay-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-keys-behavior",
- ":iron-fit-behavior",
- ":iron-resizable-behavior",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "iron-resizable-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- )
- bower_component(
- name = "iron-selector",
- license = "//lib:LICENSE-polymer",
- deps = [ ":polymer" ],
- seed = True,
- )
- bower_component(
- name = "iron-test-helpers",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- deps = [ ":polymer" ],
- seed = True,
- )
- bower_component(
- name = "iron-validatable-behavior",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-meta",
- ":polymer",
- ],
- )
- bower_component(
- name = "lodash",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "mocha",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "moment",
- license = "//lib:LICENSE-moment",
- seed = True,
- )
- bower_component(
- name = "neon-animation",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-meta",
- ":iron-resizable-behavior",
- ":iron-selector",
- ":polymer",
- ":web-animations-js",
- ],
- )
- bower_component(
- name = "page",
- license = "//lib:LICENSE-page.js",
- seed = True,
- )
- bower_component(
- name = "paper-behaviors",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-checked-element-behavior",
- ":paper-ripple",
- ":polymer",
- ],
- )
- bower_component(
- name = "paper-button",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-flex-layout",
- ":paper-behaviors",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "paper-icon-button",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-icon",
- ":paper-behaviors",
- ":paper-styles",
- ":polymer",
- ],
- )
- bower_component(
- name = "paper-input",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-keys-behavior",
- ":iron-autogrow-textarea",
- ":iron-behaviors",
- ":iron-form-element-behavior",
- ":iron-input",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "paper-item",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-flex-layout",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "paper-listbox",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-menu-behavior",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "paper-ripple",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-a11y-keys-behavior",
- ":polymer",
- ],
- )
- bower_component(
- name = "paper-styles",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":font-roboto",
- ":iron-flex-layout",
- ":polymer",
- ],
- )
- bower_component(
- name = "paper-tabs",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-behaviors",
- ":iron-flex-layout",
- ":iron-icon",
- ":iron-iconset-svg",
- ":iron-menu-behavior",
- ":iron-resizable-behavior",
- ":paper-behaviors",
- ":paper-icon-button",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "paper-toggle-button",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":iron-checked-element-behavior",
- ":paper-behaviors",
- ":paper-styles",
- ":polymer",
- ],
- seed = True,
- )
- bower_component(
- name = "polymer-resin",
- license = "//lib:LICENSE-polymer",
- deps = [
- ":polymer",
- ":webcomponentsjs",
- ],
- seed = True,
- )
- bower_component(
- name = "polymer",
- license = "//lib:LICENSE-polymer",
- deps = [ ":webcomponentsjs" ],
- seed = True,
- )
- bower_component(
- name = "promise-polyfill",
- license = "//lib:LICENSE-promise-polyfill",
- deps = [ ":polymer" ],
- seed = True,
- )
- bower_component(
- name = "sinon-chai",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "sinonjs",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "stacky",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- )
- bower_component(
- name = "test-fixture",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- seed = True,
- )
- bower_component(
- name = "web-animations-js",
- license = "//lib:LICENSE-Apache2.0",
- )
- bower_component(
- name = "web-component-tester",
- license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
- deps = [
- ":accessibility-developer-tools",
- ":async",
- ":chai",
- ":lodash",
- ":mocha",
- ":sinon-chai",
- ":sinonjs",
- ":stacky",
- ":test-fixture",
- ],
- seed = True,
- )
- bower_component(
- name = "webcomponentsjs",
- license = "//lib:LICENSE-polymer",
- )
+ bower_component(
+ name = "accessibility-developer-tools",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "async",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "chai",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "es6-promise",
+ license = "//lib:LICENSE-es6-promise",
+ seed = True,
+ )
+ bower_component(
+ name = "fetch",
+ license = "//lib:LICENSE-fetch",
+ seed = True,
+ )
+ bower_component(
+ name = "font-roboto",
+ license = "//lib:LICENSE-polymer",
+ )
+ bower_component(
+ name = "iron-a11y-announcer",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-a11y-keys-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-autogrow-textarea",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-flex-layout",
+ ":iron-validatable-behavior",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-behaviors",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "iron-checked-element-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-form-element-behavior",
+ ":iron-validatable-behavior",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "iron-dropdown",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-overlay-behavior",
+ ":iron-resizable-behavior",
+ ":neon-animation",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-fit-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-flex-layout",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-form-element-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-icon",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-flex-layout",
+ ":iron-meta",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-iconset-svg",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-meta",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-input",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-announcer",
+ ":iron-validatable-behavior",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-menu-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":iron-flex-layout",
+ ":iron-selector",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "iron-meta",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-overlay-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":iron-fit-behavior",
+ ":iron-resizable-behavior",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-resizable-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ )
+ bower_component(
+ name = "iron-selector",
+ license = "//lib:LICENSE-polymer",
+ deps = [":polymer"],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-test-helpers",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ deps = [":polymer"],
+ seed = True,
+ )
+ bower_component(
+ name = "iron-validatable-behavior",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-meta",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "lodash",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "mocha",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "moment",
+ license = "//lib:LICENSE-moment",
+ seed = True,
+ )
+ bower_component(
+ name = "neon-animation",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-meta",
+ ":iron-resizable-behavior",
+ ":iron-selector",
+ ":polymer",
+ ":web-animations-js",
+ ],
+ )
+ bower_component(
+ name = "page",
+ license = "//lib:LICENSE-page.js",
+ seed = True,
+ )
+ bower_component(
+ name = "paper-behaviors",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-checked-element-behavior",
+ ":paper-ripple",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "paper-button",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-flex-layout",
+ ":paper-behaviors",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-icon-button",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-icon",
+ ":paper-behaviors",
+ ":paper-styles",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "paper-input",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":iron-autogrow-textarea",
+ ":iron-behaviors",
+ ":iron-form-element-behavior",
+ ":iron-input",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-item",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-flex-layout",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-listbox",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-menu-behavior",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-ripple",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-a11y-keys-behavior",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "paper-styles",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":font-roboto",
+ ":iron-flex-layout",
+ ":polymer",
+ ],
+ )
+ bower_component(
+ name = "paper-tabs",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-behaviors",
+ ":iron-flex-layout",
+ ":iron-icon",
+ ":iron-iconset-svg",
+ ":iron-menu-behavior",
+ ":iron-resizable-behavior",
+ ":paper-behaviors",
+ ":paper-icon-button",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "paper-toggle-button",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":iron-checked-element-behavior",
+ ":paper-behaviors",
+ ":paper-styles",
+ ":polymer",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "polymer-resin",
+ license = "//lib:LICENSE-polymer",
+ deps = [
+ ":polymer",
+ ":webcomponentsjs",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "polymer",
+ license = "//lib:LICENSE-polymer",
+ deps = [":webcomponentsjs"],
+ seed = True,
+ )
+ bower_component(
+ name = "promise-polyfill",
+ license = "//lib:LICENSE-promise-polyfill",
+ deps = [":polymer"],
+ seed = True,
+ )
+ bower_component(
+ name = "sinon-chai",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "sinonjs",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "stacky",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ )
+ bower_component(
+ name = "test-fixture",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ seed = True,
+ )
+ bower_component(
+ name = "web-animations-js",
+ license = "//lib:LICENSE-Apache2.0",
+ )
+ bower_component(
+ name = "web-component-tester",
+ license = "//lib:LICENSE-DO_NOT_DISTRIBUTE",
+ deps = [
+ ":accessibility-developer-tools",
+ ":async",
+ ":chai",
+ ":lodash",
+ ":mocha",
+ ":sinon-chai",
+ ":sinonjs",
+ ":stacky",
+ ":test-fixture",
+ ],
+ seed = True,
+ )
+ bower_component(
+ name = "webcomponentsjs",
+ license = "//lib:LICENSE-polymer",
+ )
diff --git a/lib/prolog/prolog.bzl b/lib/prolog/prolog.bzl
index d905ad8..4d4dd3a 100644
--- a/lib/prolog/prolog.bzl
+++ b/lib/prolog/prolog.bzl
@@ -13,22 +13,22 @@
# limitations under the License.
def prolog_cafe_library(
- name,
- srcs,
- deps = [],
- **kwargs):
- native.genrule(
- name = name + '__pl2j',
- cmd = '$(location //lib/prolog:compiler-bin) ' +
- '$$(dirname $@) $@ ' +
- '$(SRCS)',
- srcs = srcs,
- tools = ['//lib/prolog:compiler-bin'],
- outs = [ name + '.srcjar' ],
- )
- native.java_library(
- name = name,
- srcs = [':' + name + '__pl2j'],
- deps = ['//lib/prolog:runtime-neverlink'] + deps,
- **kwargs
- )
+ name,
+ srcs,
+ deps = [],
+ **kwargs):
+ native.genrule(
+ name = name + "__pl2j",
+ cmd = "$(location //lib/prolog:compiler-bin) " +
+ "$$(dirname $@) $@ " +
+ "$(SRCS)",
+ srcs = srcs,
+ tools = ["//lib/prolog:compiler-bin"],
+ outs = [name + ".srcjar"],
+ )
+ native.java_library(
+ name = name,
+ srcs = [":" + name + "__pl2j"],
+ deps = ["//lib/prolog:runtime-neverlink"] + deps,
+ **kwargs
+ )
diff --git a/plugins/BUILD b/plugins/BUILD
index 4cc982a..a623ff7 100644
--- a/plugins/BUILD
+++ b/plugins/BUILD
@@ -19,6 +19,7 @@
PLUGIN_API = [
"//java/com/google/gerrit/server",
+ "//java/com/google/gerrit/server/ioutil",
"//java/com/google/gerrit/server/restapi",
"//java/com/google/gerrit/pgm/init/api",
"//java/com/google/gerrit/httpd",
@@ -37,6 +38,7 @@
"//java/com/google/gerrit/metrics/dropwizard",
"//java/com/google/gerrit/reviewdb:server",
"//java/com/google/gerrit/util/http",
+ "//lib/commons:compress",
"//lib/commons:dbcp",
"//lib/commons:lang",
"//lib/dropwizard:dropwizard-core",
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index 53dccff..318504d 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit 53dccff17c029459999ff70ac886b80626af634b
+Subproject commit 318504d0eb74f2f9c2967e9865ace6d5b57638c6
diff --git a/plugins/external_plugin_deps.bzl b/plugins/external_plugin_deps.bzl
index 391f920..1f7c020 100644
--- a/plugins/external_plugin_deps.bzl
+++ b/plugins/external_plugin_deps.bzl
@@ -1,2 +1,2 @@
def external_plugin_deps():
- pass
\ No newline at end of file
+ pass
diff --git a/plugins/replication b/plugins/replication
index 3a47f8c..1086fac 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 3a47f8c11ebdbcbc65fc6a58c35d18f1f3c3a74b
+Subproject commit 1086faccd0cf2aa53977854767fdc77f048b0253
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
index 61df877..45bc5f6 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.html
@@ -45,7 +45,7 @@
.header,
#deletedContainer {
align-items: center;
- background: #f6f6f6;
+ background: var(--table-header-background-color);
border-bottom: 1px dotted var(--border-color);
display: flex;
justify-content: space-between;
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
index 704974d..fd6eb80 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
@@ -243,6 +243,22 @@
</span>
</section>
<section>
+ <span class="title">
+ Set new changes to "work in progress" by default</span>
+ <span class="value">
+ <gr-select
+ id="setAllNewChangesWorkInProgressByDefaultSelect"
+ bind-value="{{_repoConfig.work_in_progress_by_default.configured_value}}">
+ <select disabled$="[[_readOnly]]">
+ <template is="dom-repeat"
+ items="[[_formatBooleanSelect(_repoConfig.work_in_progress_by_default)]]">
+ <option value="[[item.value]]">[[item.label]]</option>
+ </template>
+ </select>
+ </gr-select>
+ </span>
+ </section>
+ <section>
<span class="title">Maximum Git object size limit</span>
<span class="value">
<input
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
index 6ea7cf3..7eb2b6c 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.html
@@ -171,11 +171,14 @@
</td>
<td class="cell project"
hidden$="[[isColumnHidden('Project', visibleChangeTableColumns)]]">
- <a class="fullProject" href$="[[_computeProjectURL(change.project)]]">
- [[change.project]]
+ <a class="fullProject" href$="[[_computeProjectURL(change)]]">
+ [[_computeProjectDisplay(change)]]
</a>
- <a class="truncatedProject" href$="[[_computeProjectURL(change.project)]]">
- [[_computeTruncatedProject(change.project)]]
+ <a
+ class="truncatedProject"
+ href$="[[_computeProjectURL(change)]]"
+ title$="[[_computeProjectDisplay(change)]]">
+ [[_computeProjectDisplay(change, 'true')]]
</a>
</td>
<td class="cell branch"
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index 259580b..b73a237 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -122,22 +122,36 @@
return '';
},
- _computeProjectURL(project) {
- return Gerrit.Nav.getUrlForProjectChanges(project, true);
+ _computeProjectURL(change) {
+ return Gerrit.Nav.getUrlForProjectChanges(change.project, true,
+ change.internalHost);
},
_computeProjectBranchURL(change) {
- return Gerrit.Nav.getUrlForBranch(change.branch, change.project);
+ return Gerrit.Nav.getUrlForBranch(change.branch, change.project, null,
+ change.internalHost);
},
_computeTopicURL(change) {
if (!change.topic) { return ''; }
- return Gerrit.Nav.getUrlForTopic(change.topic);
+ return Gerrit.Nav.getUrlForTopic(change.topic, change.internalHost);
},
- _computeTruncatedProject(project) {
- if (!project) { return ''; }
- return this.truncatePath(project, 2);
+ /**
+ * Computes the display string for the project column. If there is a host
+ * specified in the change detail, the string will be prefixed with it.
+ *
+ * @param {!Object} change
+ * @param {string=} truncate whether or not the project name should be
+ * truncated. If this value is truthy, the name will be truncated.
+ * @return {string}
+ */
+ _computeProjectDisplay(change, truncate) {
+ if (!change || !change.project) { return ''; }
+ let str = '';
+ if (change.internalHost) { str += change.internalHost + '/'; }
+ str += truncate ? this.truncatePath(change.project, 2) : change.project;
+ return str;
},
_computeAccountStatusString(account) {
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
index 81e1034..f4c66c7 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
@@ -37,8 +37,10 @@
<script>
suite('gr-change-list-item tests', () => {
let element;
+ let sandbox;
setup(() => {
+ sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
getLoggedIn() { return Promise.resolve(false); },
@@ -46,6 +48,8 @@
element = fixture('basic');
});
+ teardown(() => { sandbox.restore(); });
+
test('computed fields', () => {
assert.equal(element._computeLabelClass({labels: {}}),
'cell label u-gray-background');
@@ -249,5 +253,39 @@
deletions: 999,
}), 'XL');
});
+
+ test('change params passed to gr-navigation', () => {
+ sandbox.stub(Gerrit.Nav);
+ const change = {
+ internalHost: 'test-host',
+ project: 'test-repo',
+ topic: 'test-topic',
+ branch: 'test-branch',
+ };
+ element.change = change;
+ flushAsynchronousOperations();
+
+ assert.deepEqual(Gerrit.Nav.getUrlForChange.lastCall.args, [change]);
+ assert.deepEqual(Gerrit.Nav.getUrlForProjectChanges.lastCall.args,
+ [change.project, true, change.internalHost]);
+ assert.deepEqual(Gerrit.Nav.getUrlForBranch.lastCall.args,
+ [change.branch, change.project, null, change.internalHost]);
+ assert.deepEqual(Gerrit.Nav.getUrlForTopic.lastCall.args,
+ [change.topic, change.internalHost]);
+ });
+
+ test('_computeProjectDisplay', () => {
+ const change = {
+ project: 'a/test/repo',
+ internalHost: 'host',
+ };
+ assert.equal(element._computeProjectDisplay(change), 'host/a/test/repo');
+ assert.equal(element._computeProjectDisplay(change, true),
+ 'host/…/test/repo');
+ delete change.internalHost;
+ assert.equal(element._computeProjectDisplay(change), 'a/test/repo');
+ assert.equal(element._computeProjectDisplay(change, true),
+ '…/test/repo');
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.html b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.html
index 3a7ff10..fc00299 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.html
@@ -86,7 +86,8 @@
changes="{{_changes}}"
preferences="[[preferences]]"
selected-index="{{viewState.selectedChangeIndex}}"
- show-star="[[_loggedIn]]"></gr-change-list>
+ show-star="[[_loggedIn]]"
+ on-toggle-star="_handleToggleStar"></gr-change-list>
<nav class$="[[_computeNavClass(_loading)]]">
Page [[_computePage(_offset, _changesPerPage)]]
<a id="prevArrow"
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
index 2a05a2f..9b099cd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
@@ -263,5 +263,10 @@
_computeLoggedIn(account) {
return !!(account && Object.keys(account).length > 0);
},
+
+ _handleToggleStar(e) {
+ this.$.restAPI.saveChangeStarred(e.detail.change._number,
+ e.detail.starred);
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index 9930bf5..33bc338 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -18,10 +18,9 @@
'use strict';
const NUMBER_FIXED_COLUMNS = 3;
-
const CLOSED_STATUS = ['MERGED', 'ABANDONED'];
-
const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
+ const MAX_SHORTCUT_CHARS = 5;
Polymer({
is: 'gr-change-list',
@@ -185,10 +184,12 @@
if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
labelName = labelName.slice(LABEL_PREFIX_INVALID_PROLOG.length);
}
- return labelName.split('-').reduce((a, i) => {
- if (!i) { return a; }
- return a + i[0].toUpperCase();
- }, '');
+ return labelName.split('-')
+ .reduce((a, i) => {
+ if (!i) { return a; }
+ return a + i[0].toUpperCase();
+ }, '')
+ .slice(0, MAX_SHORTCUT_CHARS);
},
_changesChanged(changes) {
@@ -306,10 +307,7 @@
}
const changeEl = changeEls[index];
- const change = changeEl.change;
- const newVal = !change.starred;
- changeEl.set('change.starred', newVal);
- this.$.restAPI.saveChangeStarred(change._number, newVal);
+ changeEl.$$('gr-change-star').toggleStar();
},
_changeForIndex(index) {
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
index 9ce5764..39d7ab1 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
@@ -132,6 +132,8 @@
'Some-Special-Label-7'), 'SSL7');
assert.equal(element._computeLabelShortcut('--Too----many----dashes---'),
'TMD');
+ assert.equal(element._computeLabelShortcut(
+ 'Really-rather-entirely-too-long-of-a-label-name'), 'RRETL');
});
test('colspans', () => {
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
index 1935962..1b21543 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
@@ -60,7 +60,8 @@
account="[[account]]"
preferences="[[preferences]]"
selected-index="{{viewState.selectedChangeIndex}}"
- sections="[[_results]]"></gr-change-list>
+ sections="[[_results]]"
+ on-toggle-star="_handleToggleStar"></gr-change-list>
</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
<gr-reporting id="reporting"></gr-reporting>
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index f86c98c..9cf76da 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -241,5 +241,10 @@
_computeUserHeaderClass(userParam) {
return userParam === 'self' ? 'hide' : '';
},
+
+ _handleToggleStar(e) {
+ this.$.restAPI.saveChangeStarred(e.detail.change._number,
+ e.detail.starred);
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 5a56475..1b911e0 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -273,6 +273,12 @@
#commitMessageEditor {
min-width: 0;
}
+ .commitMessage {
+ margin-right: 0;
+ }
+ .mainChangeInfo {
+ padding-right: 0;
+ }
}
/* NOTE: If you update this breakpoint, also update the
BREAKPOINT_RELATED_SMALL in the JS */
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
index e217b4b..dfe5410 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.html
@@ -177,13 +177,15 @@
* @param {!string} project The name of the project.
* @param {boolean=} opt_openOnly When true, only search open changes in
* the project.
+ * @param {string=} opt_host The host in which to search.
* @return {string}
*/
- getUrlForProjectChanges(project, opt_openOnly) {
+ getUrlForProjectChanges(project, opt_openOnly, opt_host) {
return this._getUrlFor({
view: Gerrit.Nav.View.SEARCH,
project,
statuses: opt_openOnly ? ['open'] : [],
+ host: opt_host,
});
},
@@ -191,26 +193,30 @@
* @param {string} branch The name of the branch.
* @param {string} project The name of the project.
* @param {string=} opt_status The status to search.
+ * @param {string=} opt_host The host in which to search.
* @return {string}
*/
- getUrlForBranch(branch, project, opt_status) {
+ getUrlForBranch(branch, project, opt_status, opt_host) {
return this._getUrlFor({
view: Gerrit.Nav.View.SEARCH,
branch,
project,
statuses: opt_status ? [opt_status] : undefined,
+ host: opt_host,
});
},
/**
* @param {string} topic The name of the topic.
+ * @param {string=} opt_host The host in which to search.
* @return {string}
*/
- getUrlForTopic(topic) {
+ getUrlForTopic(topic, opt_host) {
return this._getUrlFor({
view: Gerrit.Nav.View.SEARCH,
topic,
statuses: ['open', 'merged'],
+ host: opt_host,
});
},
@@ -267,6 +273,7 @@
patchNum: opt_patchNum,
basePatchNum: opt_basePatchNum,
edit: opt_isEdit,
+ host: change.internalHost || undefined,
});
},
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
index ea69fc2..edf9f5a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment.js
@@ -457,7 +457,11 @@
this._discardDraft();
return;
}
- this._openOverlay(this.confirmDiscardOverlay);
+
+ this._openOverlay(this.confirmDiscardOverlay).then(() => {
+ this.confirmDiscardOverlay.querySelector('#confirmDiscardDialog')
+ .resetFocus();
+ });
},
_handleConfirmDiscard(e) {
@@ -626,9 +630,7 @@
_openOverlay(overlay) {
Polymer.dom(Gerrit.getRootElement()).appendChild(overlay);
- this.async(() => {
- overlay.open();
- }, 1);
+ return overlay.open();
},
_closeOverlay(overlay) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
index b41ab23..f1ac649 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-comment/gr-diff-comment_test.html
@@ -614,7 +614,8 @@
setup(() => {
discardStub = sandbox.stub(element, '_discardDraft');
- overlayStub = sandbox.stub(element, '_openOverlay');
+ overlayStub = sandbox.stub(element, '_openOverlay')
+ .returns(Promise.resolve());
mockEvent = {preventDefault: sinon.stub()};
});
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-themes/gr-syntax-theme.html b/polygerrit-ui/app/elements/diff/gr-syntax-themes/gr-syntax-theme.html
index 0e028d8..41d3804 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-themes/gr-syntax-theme.html
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-themes/gr-syntax-theme.html
@@ -32,7 +32,8 @@
.gr-syntax-meta {
color: var(--syntax-meta-color);
}
- .gr-syntax-keyword {
+ .gr-syntax-keyword,
+ .gr-syntax-name {
color: var(--syntax-keyword-color);
line-height: 1;
}
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
index 14e5e6f..18c1734 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.html
@@ -227,6 +227,16 @@
</span>
</section>
<section>
+ <span class="title">Set new changes to "work in progress" by default</span>
+ <span class="value">
+ <input
+ id="workInProgressByDefault"
+ type="checkbox"
+ checked$="[[_localPrefs.work_in_progress_by_default]]"
+ on-change="_handleWorkInProgressByDefault">
+ </span>
+ </section>
+ <section>
<span class="title">
Insert Signed-off-by Footer For Inline Edit Changes
</span>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index 213ab65..8eefc0a 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -24,6 +24,7 @@
'email_strategy',
'diff_view',
'publish_comments_on_push',
+ 'work_in_progress_by_default',
'signed_off_by',
'email_format',
'size_bar_in_change_table',
@@ -291,6 +292,11 @@
this.$.publishCommentsOnPush.checked);
},
+ _handleWorkInProgressByDefault() {
+ this.set('_localPrefs.work_in_progress_by_default',
+ this.$.workInProgressByDefault.checked);
+ },
+
_handleInsertSignedOff() {
this.set('_localPrefs.signed_off_by', this.$.insertSignedOff.checked);
},
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
index b208ba2..f47816f 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.html
@@ -175,6 +175,9 @@
assert.equal(valueOf('Publish comments on push', 'preferences')
.firstElementChild.checked, false);
assert.equal(valueOf(
+ 'Set new changes to "work in progress" by default', 'preferences')
+ .firstElementChild.checked, false);
+ assert.equal(valueOf(
'Insert Signed-off-by Footer For Inline Edit Changes', 'preferences')
.firstElementChild.checked, false);
@@ -234,6 +237,30 @@
});
});
+ test('set new changes work-in-progress', done => {
+ const newChangesWorkInProgress =
+ valueOf('Set new changes to "work in progress" by default',
+ 'preferences').firstElementChild;
+ MockInteractions.tap(newChangesWorkInProgress);
+
+ assert.isFalse(element._menuChanged);
+ assert.isTrue(element._prefsChanged);
+
+ stub('gr-rest-api-interface', {
+ savePreferences(prefs) {
+ assert.equal(prefs.work_in_progress_by_default, true);
+ return Promise.resolve();
+ },
+ });
+
+ // Save the change.
+ element._handleSavePreferences().then(() => {
+ assert.isFalse(element._prefsChanged);
+ assert.isFalse(element._menuChanged);
+ done();
+ });
+ });
+
test('diff preferences', done => {
// Rendered with the expected preferences selected.
assert.equal(valueOf('Context', 'diffPreferences')
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.html b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.html
index 70b2635..a14c652 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.html
@@ -17,7 +17,6 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../shared/gr-icons/gr-icons.html">
-<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<link rel="import" href="../../../styles/shared-styles.html">
<dom-module id="gr-change-star">
@@ -36,7 +35,6 @@
class$="[[_computeStarClass(change.starred)]]"
icon$="[[_computeStarIcon(change.starred)]]"></iron-icon>
</button>
- <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-change-star.js"></script>
</dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
index 9646735..3c46d1b 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star.js
@@ -20,14 +20,18 @@
Polymer({
is: 'gr-change-star',
+ /**
+ * Fired when star state is toggled.
+ *
+ * @event toggle-star
+ */
+
properties: {
/** @type {?} */
change: {
type: Object,
notify: true,
},
-
- _xhrPromise: Object, // Used for testing.
},
_computeStarClass(starred) {
@@ -42,8 +46,10 @@
toggleStar() {
const newVal = !this.change.starred;
this.set('change.starred', newVal);
- this._xhrPromise = this.$.restAPI.saveChangeStarred(this.change._number,
- newVal);
+ this.dispatchEvent(new CustomEvent('toggle-star', {
+ bubbles: true,
+ detail: {change: this.change, starred: newVal},
+ }));
},
});
})();
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
index f24b45c..0ca9368 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
@@ -37,9 +37,6 @@
let element;
setup(() => {
- stub('gr-rest-api-interface', {
- saveChangeStarred() { return Promise.resolve({ok: true}); },
- });
element = fixture('basic');
element.change = {
_number: 2,
@@ -60,23 +57,21 @@
});
test('starring', done => {
- element.set('change.starred', false);
- MockInteractions.tap(element.$$('button'));
-
- element._xhrPromise.then(req => {
+ element.addEventListener('toggle-star', () => {
assert.equal(element.change.starred, true);
done();
});
+ element.set('change.starred', false);
+ MockInteractions.tap(element.$$('button'));
});
test('unstarring', done => {
- element.set('change.starred', true);
- MockInteractions.tap(element.$$('button'));
-
- element._xhrPromise.then(req => {
+ element.addEventListener('toggle-star', () => {
assert.equal(element.change.starred, false);
done();
});
+ element.set('change.starred', true);
+ MockInteractions.tap(element.$$('button'));
});
});
</script>
diff --git a/polygerrit-ui/app/rules.bzl b/polygerrit-ui/app/rules.bzl
index 199a947..293ef8b 100644
--- a/polygerrit-ui/app/rules.bzl
+++ b/polygerrit-ui/app/rules.bzl
@@ -1,107 +1,107 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
-load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library", "closure_js_binary")
+load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
load(
"//tools/bzl:js.bzl",
- "vulcanize",
"bower_component",
"js_component",
+ "vulcanize",
)
def polygerrit_bundle(name, srcs, outs, app):
- appName = app.split(".html")[0].split("/").pop() # eg: gr-app
+ appName = app.split(".html")[0].split("/").pop() # eg: gr-app
- closure_js_binary(
- name = name + "_closure_bin",
- # Known issue: Closure compilation not compatible with Polymer behaviors.
- # See: https://github.com/google/closure-compiler/issues/2042
- compilation_level = "WHITESPACE_ONLY",
- defs = [
- "--polymer_version=1",
- "--jscomp_off=duplicate",
- "--force_inject_library=es6_runtime",
- ],
- language = "ECMASCRIPT5",
- deps = [name + "_closure_lib"],
- )
+ closure_js_binary(
+ name = name + "_closure_bin",
+ # Known issue: Closure compilation not compatible with Polymer behaviors.
+ # See: https://github.com/google/closure-compiler/issues/2042
+ compilation_level = "WHITESPACE_ONLY",
+ defs = [
+ "--polymer_version=1",
+ "--jscomp_off=duplicate",
+ "--force_inject_library=es6_runtime",
+ ],
+ language = "ECMASCRIPT5",
+ deps = [name + "_closure_lib"],
+ )
- closure_js_library(
- name = name + "_closure_lib",
- srcs = [appName + ".js"],
- convention = "GOOGLE",
- # TODO(davido): Clean up these issues: http://paste.openstack.org/show/608548
- # and remove this supression
- suppress = [
- "JSC_JSDOC_MISSING_TYPE_WARNING",
- "JSC_UNNECESSARY_ESCAPE",
- "JSC_UNUSED_LOCAL_ASSIGNMENT",
- ],
- deps = [
- "//lib/polymer_externs:polymer_closure",
- "@io_bazel_rules_closure//closure/library",
- ],
- )
+ closure_js_library(
+ name = name + "_closure_lib",
+ srcs = [appName + ".js"],
+ convention = "GOOGLE",
+ # TODO(davido): Clean up these issues: http://paste.openstack.org/show/608548
+ # and remove this supression
+ suppress = [
+ "JSC_JSDOC_MISSING_TYPE_WARNING",
+ "JSC_UNNECESSARY_ESCAPE",
+ "JSC_UNUSED_LOCAL_ASSIGNMENT",
+ ],
+ deps = [
+ "//lib/polymer_externs:polymer_closure",
+ "@io_bazel_rules_closure//closure/library",
+ ],
+ )
- vulcanize(
- name = appName,
- srcs = srcs,
- app = app,
- deps = ["//polygerrit-ui:polygerrit_components.bower_components"],
- )
+ vulcanize(
+ name = appName,
+ srcs = srcs,
+ app = app,
+ deps = ["//polygerrit-ui:polygerrit_components.bower_components"],
+ )
- native.filegroup(
- name = name + "_app_sources",
- srcs = [
- name + "_closure_bin.js",
- appName + ".html",
- ],
- )
+ native.filegroup(
+ name = name + "_app_sources",
+ srcs = [
+ name + "_closure_bin.js",
+ appName + ".html",
+ ],
+ )
- native.filegroup(
- name = name + "_css_sources",
- srcs = native.glob(["styles/**/*.css"]),
- )
+ native.filegroup(
+ name = name + "_css_sources",
+ srcs = native.glob(["styles/**/*.css"]),
+ )
- native.filegroup(
- name = name + "_theme_sources",
- srcs = native.glob(
- ["styles/themes/*.html"],
- # app-theme.html already included via an import in gr-app.html.
- exclude = ["styles/themes/app-theme.html"],
- ),
- )
+ native.filegroup(
+ name = name + "_theme_sources",
+ srcs = native.glob(
+ ["styles/themes/*.html"],
+ # app-theme.html already included via an import in gr-app.html.
+ exclude = ["styles/themes/app-theme.html"],
+ ),
+ )
- native.filegroup(
- name = name + "_top_sources",
- srcs = [
- "favicon.ico",
- ],
- )
+ native.filegroup(
+ name = name + "_top_sources",
+ srcs = [
+ "favicon.ico",
+ ],
+ )
- genrule2(
- name = name,
- srcs = [
- name + "_app_sources",
- name + "_css_sources",
- name + "_theme_sources",
- name + "_top_sources",
- "//lib/fonts:robotofonts",
- "//lib/js:highlightjs_files",
- # we extract from the zip, but depend on the component for license checking.
- "@webcomponentsjs//:zipfile",
- "//lib/js:webcomponentsjs"
- ],
- outs = outs,
- cmd = " && ".join([
- "mkdir -p $$TMP/polygerrit_ui/{styles/themes,fonts,bower_components/{highlightjs,webcomponentsjs},elements}",
- "for f in $(locations " + name + "_app_sources); do ext=$${f##*.}; cp -p $$f $$TMP/polygerrit_ui/elements/" + appName + ".$$ext; done",
- "cp $(locations //lib/fonts:robotofonts) $$TMP/polygerrit_ui/fonts/",
- "for f in $(locations " + name + "_top_sources); do cp $$f $$TMP/polygerrit_ui/; done",
- "for f in $(locations "+ name + "_css_sources); do cp $$f $$TMP/polygerrit_ui/styles; done",
- "for f in $(locations "+ name + "_theme_sources); do cp $$f $$TMP/polygerrit_ui/styles/themes; done",
- "for f in $(locations //lib/js:highlightjs_files); do cp $$f $$TMP/polygerrit_ui/bower_components/highlightjs/ ; done",
- "unzip -qd $$TMP/polygerrit_ui/bower_components $(location @webcomponentsjs//:zipfile) webcomponentsjs/webcomponents-lite.js",
- "cd $$TMP",
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -qr $$ROOT/$@ *",
- ]),
- )
+ genrule2(
+ name = name,
+ srcs = [
+ name + "_app_sources",
+ name + "_css_sources",
+ name + "_theme_sources",
+ name + "_top_sources",
+ "//lib/fonts:robotofonts",
+ "//lib/js:highlightjs_files",
+ # we extract from the zip, but depend on the component for license checking.
+ "@webcomponentsjs//:zipfile",
+ "//lib/js:webcomponentsjs",
+ ],
+ outs = outs,
+ cmd = " && ".join([
+ "mkdir -p $$TMP/polygerrit_ui/{styles/themes,fonts,bower_components/{highlightjs,webcomponentsjs},elements}",
+ "for f in $(locations " + name + "_app_sources); do ext=$${f##*.}; cp -p $$f $$TMP/polygerrit_ui/elements/" + appName + ".$$ext; done",
+ "cp $(locations //lib/fonts:robotofonts) $$TMP/polygerrit_ui/fonts/",
+ "for f in $(locations " + name + "_top_sources); do cp $$f $$TMP/polygerrit_ui/; done",
+ "for f in $(locations " + name + "_css_sources); do cp $$f $$TMP/polygerrit_ui/styles; done",
+ "for f in $(locations " + name + "_theme_sources); do cp $$f $$TMP/polygerrit_ui/styles/themes; done",
+ "for f in $(locations //lib/js:highlightjs_files); do cp $$f $$TMP/polygerrit_ui/bower_components/highlightjs/ ; done",
+ "unzip -qd $$TMP/polygerrit_ui/bower_components $(location @webcomponentsjs//:zipfile) webcomponentsjs/webcomponents-lite.js",
+ "cd $$TMP",
+ "find . -exec touch -t 198001010000 '{}' ';'",
+ "zip -qr $$ROOT/$@ *",
+ ]),
+ )
diff --git a/polygerrit-ui/externs/BUILD b/polygerrit-ui/externs/BUILD
new file mode 100644
index 0000000..fab3954
--- /dev/null
+++ b/polygerrit-ui/externs/BUILD
@@ -0,0 +1,25 @@
+# Copyright (C) 2018 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(
+ default_visibility = ["//visibility:public"],
+)
+
+load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
+
+closure_js_library(
+ name = "plugin",
+ srcs = ["plugin.js"],
+ no_closure_library = True,
+)
diff --git a/polygerrit-ui/externs/plugin.js b/polygerrit-ui/externs/plugin.js
new file mode 100644
index 0000000..edace7d
--- /dev/null
+++ b/polygerrit-ui/externs/plugin.js
@@ -0,0 +1,28 @@
+/**
+ * @license
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * @fileoverview Closure compiler externs for the Gerrit UI plugins.
+ * @externs
+ */
+
+var Gerrit = {};
+
+/**
+ * @param {!Function} callback
+ */
+Gerrit.install = function(callback) {};
diff --git a/tools/bzl/asciidoc.bzl b/tools/bzl/asciidoc.bzl
index 263b465..97d68d6 100644
--- a/tools/bzl/asciidoc.bzl
+++ b/tools/bzl/asciidoc.bzl
@@ -1,40 +1,43 @@
def documentation_attributes():
- return [
- "toc2",
- 'newline="\\n"',
- 'asterisk="*"',
- 'plus="+"',
- 'caret="^"',
- 'startsb="["',
- 'endsb="]"',
- 'tilde="~"',
- "last-update-label!",
- "source-highlighter=prettify",
- "stylesheet=DEFAULT",
- "linkcss=true",
- "prettifydir=.",
- # Just a placeholder, will be filled in asciidoctor java binary:
- "revnumber=%s",
- ]
+ return [
+ "toc2",
+ 'newline="\\n"',
+ 'asterisk="*"',
+ 'plus="+"',
+ 'caret="^"',
+ 'startsb="["',
+ 'endsb="]"',
+ 'tilde="~"',
+ "last-update-label!",
+ "source-highlighter=prettify",
+ "stylesheet=DEFAULT",
+ "linkcss=true",
+ "prettifydir=.",
+ # Just a placeholder, will be filled in asciidoctor java binary:
+ "revnumber=%s",
+ ]
def _replace_macros_impl(ctx):
- cmd = [
- ctx.file._exe.path,
- '--suffix', ctx.attr.suffix,
- "-s", ctx.file.src.path,
- "-o", ctx.outputs.out.path,
- ]
- if ctx.attr.searchbox:
- cmd.append('--searchbox')
- else:
- cmd.append('--no-searchbox')
- ctx.actions.run_shell(
- inputs = [ctx.file._exe, ctx.file.src],
- outputs = [ctx.outputs.out],
- command = cmd,
- use_default_shell_env = True,
- progress_message = "Replacing macros in %s" % ctx.file.src.short_path,
- )
+ cmd = [
+ ctx.file._exe.path,
+ "--suffix",
+ ctx.attr.suffix,
+ "-s",
+ ctx.file.src.path,
+ "-o",
+ ctx.outputs.out.path,
+ ]
+ if ctx.attr.searchbox:
+ cmd.append("--searchbox")
+ else:
+ cmd.append("--no-searchbox")
+ ctx.actions.run_shell(
+ inputs = [ctx.file._exe, ctx.file.src],
+ outputs = [ctx.outputs.out],
+ command = cmd,
+ use_default_shell_env = True,
+ progress_message = "Replacing macros in %s" % ctx.file.src.short_path,
+ )
_replace_macros = rule(
attrs = {
@@ -54,52 +57,55 @@
)
def _generate_asciidoc_args(ctx):
- args = []
- if ctx.attr.backend:
- args.extend(["-b", ctx.attr.backend])
- revnumber = False
- for attribute in ctx.attr.attributes:
- if attribute.startswith("revnumber="):
- revnumber = True
- else:
- args.extend(["-a", attribute])
- if revnumber:
- args.extend([
- "--revnumber-file", ctx.file.version.path,
- ])
- for src in ctx.files.srcs:
- args.append(src.path)
- return args
+ args = []
+ if ctx.attr.backend:
+ args.extend(["-b", ctx.attr.backend])
+ revnumber = False
+ for attribute in ctx.attr.attributes:
+ if attribute.startswith("revnumber="):
+ revnumber = True
+ else:
+ args.extend(["-a", attribute])
+ if revnumber:
+ args.extend([
+ "--revnumber-file",
+ ctx.file.version.path,
+ ])
+ for src in ctx.files.srcs:
+ args.append(src.path)
+ return args
def _invoke_replace_macros(name, src, suffix, searchbox):
- fn = src
- if fn.startswith(":"):
- fn = src[1:]
+ fn = src
+ if fn.startswith(":"):
+ fn = src[1:]
- _replace_macros(
- name = "macros_%s_%s" % (name, fn),
- src = src,
- out = fn + suffix,
- suffix = suffix,
- searchbox = searchbox,
- )
+ _replace_macros(
+ name = "macros_%s_%s" % (name, fn),
+ src = src,
+ out = fn + suffix,
+ suffix = suffix,
+ searchbox = searchbox,
+ )
- return ":" + fn + suffix, fn.replace(".txt", ".html")
+ return ":" + fn + suffix, fn.replace(".txt", ".html")
def _asciidoc_impl(ctx):
- args = [
- "--bazel",
- "--in-ext", ".txt" + ctx.attr.suffix,
- "--out-ext", ".html",
- ]
- args.extend(_generate_asciidoc_args(ctx))
- ctx.actions.run(
- inputs = ctx.files.srcs + [ctx.executable._exe, ctx.file.version],
- outputs = ctx.outputs.outs,
- executable = ctx.executable._exe,
- arguments = args,
- progress_message = "Rendering asciidoctor files for %s" % ctx.label.name,
- )
+ args = [
+ "--bazel",
+ "--in-ext",
+ ".txt" + ctx.attr.suffix,
+ "--out-ext",
+ ".html",
+ ]
+ args.extend(_generate_asciidoc_args(ctx))
+ ctx.actions.run(
+ inputs = ctx.files.srcs + [ctx.executable._exe, ctx.file.version],
+ outputs = ctx.outputs.outs,
+ executable = ctx.executable._exe,
+ arguments = args,
+ progress_message = "Rendering asciidoctor files for %s" % ctx.label.name,
+ )
_asciidoc_attrs = {
"_exe": attr.label(
@@ -129,82 +135,85 @@
)
def _genasciidoc_htmlonly(
- name,
- srcs = [],
- attributes = [],
- backend = None,
- searchbox = True,
- **kwargs):
- SUFFIX = "." + name + "_macros"
- new_srcs = []
- outs = ["asciidoctor.css"]
+ name,
+ srcs = [],
+ attributes = [],
+ backend = None,
+ searchbox = True,
+ **kwargs):
+ SUFFIX = "." + name + "_macros"
+ new_srcs = []
+ outs = ["asciidoctor.css"]
- for src in srcs:
- new_src, html_name = _invoke_replace_macros(name, src, SUFFIX, searchbox)
- new_srcs.append(new_src)
- outs.append(html_name)
+ for src in srcs:
+ new_src, html_name = _invoke_replace_macros(name, src, SUFFIX, searchbox)
+ new_srcs.append(new_src)
+ outs.append(html_name)
- _asciidoc(
- name = name + "_gen",
- srcs = new_srcs,
- suffix = SUFFIX,
- backend = backend,
- attributes = attributes,
- outs = outs,
- )
-
- native.filegroup(
- name = name,
- data = outs,
- **kwargs
- )
-
-def genasciidoc(
- name,
- srcs = [],
- attributes = [],
- backend = None,
- searchbox = True,
- resources = True,
- **kwargs):
- SUFFIX = "_htmlonly"
-
- _genasciidoc_htmlonly(
- name = name + SUFFIX if resources else name,
- srcs = srcs,
- attributes = attributes,
- backend = backend,
- searchbox = searchbox,
- **kwargs
- )
-
- if resources:
- htmlonly = ":" + name + SUFFIX
- native.filegroup(
- name = name,
- srcs = [
- htmlonly,
- "//Documentation:resources",
- ],
- **kwargs
+ _asciidoc(
+ name = name + "_gen",
+ srcs = new_srcs,
+ suffix = SUFFIX,
+ backend = backend,
+ attributes = attributes,
+ outs = outs,
)
+ native.filegroup(
+ name = name,
+ data = outs,
+ **kwargs
+ )
+
+def genasciidoc(
+ name,
+ srcs = [],
+ attributes = [],
+ backend = None,
+ searchbox = True,
+ resources = True,
+ **kwargs):
+ SUFFIX = "_htmlonly"
+
+ _genasciidoc_htmlonly(
+ name = name + SUFFIX if resources else name,
+ srcs = srcs,
+ attributes = attributes,
+ backend = backend,
+ searchbox = searchbox,
+ **kwargs
+ )
+
+ if resources:
+ htmlonly = ":" + name + SUFFIX
+ native.filegroup(
+ name = name,
+ srcs = [
+ htmlonly,
+ "//Documentation:resources",
+ ],
+ **kwargs
+ )
+
def _asciidoc_html_zip_impl(ctx):
- args = [
- "--mktmp",
- "-z", ctx.outputs.out.path,
- "--in-ext", ".txt" + ctx.attr.suffix,
- "--out-ext", ".html",
- ]
- args.extend(_generate_asciidoc_args(ctx))
- ctx.actions.run(
- inputs = ctx.files.srcs + [ctx.file.version],
- outputs = [ctx.outputs.out],
- tools = [ctx.executable._exe],
- executable = ctx.executable._exe,
- arguments = args,
- progress_message = "Rendering asciidoctor files for %s" % ctx.label.name,
- )
+ args = [
+ "--mktmp",
+ "-z",
+ ctx.outputs.out.path,
+ "--in-ext",
+ ".txt" + ctx.attr.suffix,
+ "--out-ext",
+ ".html",
+ ]
+ args.extend(_generate_asciidoc_args(ctx))
+ ctx.actions.run(
+ inputs = ctx.files.srcs + [ctx.file.version],
+ outputs = [ctx.outputs.out],
+ tools = [ctx.executable._exe],
+ executable = ctx.executable._exe,
+ arguments = args,
+ progress_message = "Rendering asciidoctor files for %s" % ctx.label.name,
+ )
_asciidoc_html_zip = rule(
attrs = _asciidoc_attrs,
@@ -215,53 +224,54 @@
)
def _genasciidoc_htmlonly_zip(
- name,
- srcs = [],
- attributes = [],
- backend = None,
- searchbox = True,
- **kwargs):
- SUFFIX = "." + name + "_expn"
- new_srcs = []
+ name,
+ srcs = [],
+ attributes = [],
+ backend = None,
+ searchbox = True,
+ **kwargs):
+ SUFFIX = "." + name + "_expn"
+ new_srcs = []
- for src in srcs:
- new_src, _ = _invoke_replace_macros(name, src, SUFFIX, searchbox)
- new_srcs.append(new_src)
+ for src in srcs:
+ new_src, _ = _invoke_replace_macros(name, src, SUFFIX, searchbox)
+ new_srcs.append(new_src)
- _asciidoc_html_zip(
- name = name,
- srcs = new_srcs,
- suffix = SUFFIX,
- backend = backend,
- attributes = attributes,
- )
+ _asciidoc_html_zip(
+ name = name,
+ srcs = new_srcs,
+ suffix = SUFFIX,
+ backend = backend,
+ attributes = attributes,
+ )
def _asciidoc_zip_impl(ctx):
- tmpdir = ctx.outputs.out.path + "_tmpdir"
- cmd = [
- "p=$PWD",
- "rm -rf %s" % tmpdir,
- "mkdir -p %s/%s/" % (tmpdir, ctx.attr.directory),
- "unzip -q %s -d %s/%s/" % (ctx.file.src.path, tmpdir, ctx.attr.directory),
- ]
- for r in ctx.files.resources:
- if r.path == r.short_path:
- cmd.append("tar -cf- %s | tar -C %s -xf-" % (r.short_path, tmpdir))
- else:
- parent = r.path[:-len(r.short_path)]
- cmd.append(
- "tar -C %s -cf- %s | tar -C %s -xf-" % (parent, r.short_path, tmpdir))
- cmd.extend([
- "cd %s" % tmpdir,
- "zip -qr $p/%s *" % ctx.outputs.out.path,
- ])
- ctx.actions.run_shell(
- inputs = [ctx.file.src] + ctx.files.resources,
- outputs = [ctx.outputs.out],
- command = " && ".join(cmd),
- progress_message =
- "Generating asciidoctor zip file %s" % ctx.outputs.out.short_path,
- )
+ tmpdir = ctx.outputs.out.path + "_tmpdir"
+ cmd = [
+ "p=$PWD",
+ "rm -rf %s" % tmpdir,
+ "mkdir -p %s/%s/" % (tmpdir, ctx.attr.directory),
+ "unzip -q %s -d %s/%s/" % (ctx.file.src.path, tmpdir, ctx.attr.directory),
+ ]
+ for r in ctx.files.resources:
+ if r.path == r.short_path:
+ cmd.append("tar -cf- %s | tar -C %s -xf-" % (r.short_path, tmpdir))
+ else:
+ parent = r.path[:-len(r.short_path)]
+ cmd.append(
+ "tar -C %s -cf- %s | tar -C %s -xf-" % (parent, r.short_path, tmpdir),
+ )
+ cmd.extend([
+ "cd %s" % tmpdir,
+ "zip -qr $p/%s *" % ctx.outputs.out.path,
+ ])
+ ctx.actions.run_shell(
+ inputs = [ctx.file.src] + ctx.files.resources,
+ outputs = [ctx.outputs.out],
+ command = " && ".join(cmd),
+ progress_message =
+ "Generating asciidoctor zip file %s" % ctx.outputs.out.short_path,
+ )
_asciidoc_zip = rule(
attrs = {
@@ -282,30 +292,30 @@
)
def genasciidoc_zip(
- name,
- srcs = [],
- attributes = [],
- directory = None,
- backend = None,
- searchbox = True,
- resources = True,
- **kwargs):
- SUFFIX = "_htmlonly"
+ name,
+ srcs = [],
+ attributes = [],
+ directory = None,
+ backend = None,
+ searchbox = True,
+ resources = True,
+ **kwargs):
+ SUFFIX = "_htmlonly"
- _genasciidoc_htmlonly_zip(
- name = name + SUFFIX if resources else name,
- srcs = srcs,
- attributes = attributes,
- backend = backend,
- searchbox = searchbox,
- **kwargs
- )
-
- if resources:
- htmlonly = ":" + name + SUFFIX
- _asciidoc_zip(
- name = name,
- src = htmlonly,
- resources = ["//Documentation:resources"],
- directory = directory,
+ _genasciidoc_htmlonly_zip(
+ name = name + SUFFIX if resources else name,
+ srcs = srcs,
+ attributes = attributes,
+ backend = backend,
+ searchbox = searchbox,
+ **kwargs
)
+
+ if resources:
+ htmlonly = ":" + name + SUFFIX
+ _asciidoc_zip(
+ name = name,
+ src = htmlonly,
+ resources = ["//Documentation:resources"],
+ directory = directory,
+ )
diff --git a/tools/bzl/classpath.bzl b/tools/bzl/classpath.bzl
index 9448ed1..afdd907 100644
--- a/tools/bzl/classpath.bzl
+++ b/tools/bzl/classpath.bzl
@@ -1,15 +1,17 @@
def _classpath_collector(ctx):
all = depset()
for d in ctx.attr.deps:
- if hasattr(d, 'java'):
+ if hasattr(d, "java"):
all += d.java.transitive_runtime_deps
all += d.java.compilation_info.runtime_classpath
- elif hasattr(d, 'files'):
+ elif hasattr(d, "files"):
all += d.files
as_strs = [c.path for c in all]
- ctx.file_action(output= ctx.outputs.runtime,
- content="\n".join(sorted(as_strs)))
+ ctx.file_action(
+ output = ctx.outputs.runtime,
+ content = "\n".join(sorted(as_strs)),
+ )
classpath_collector = rule(
attrs = {
diff --git a/tools/bzl/genrule2.bzl b/tools/bzl/genrule2.bzl
index 563a9ef..3113022 100644
--- a/tools/bzl/genrule2.bzl
+++ b/tools/bzl/genrule2.bzl
@@ -17,11 +17,12 @@
# expose TMP shell variable
def genrule2(cmd, **kwargs):
- cmd = ' && '.join([
- 'ROOT=$$PWD',
- 'TMP=$$(mktemp -d || mktemp -d -t bazel-tmp)',
- '(' + cmd + ')',
- ])
- native.genrule(
- cmd = cmd,
- **kwargs)
+ cmd = " && ".join([
+ "ROOT=$$PWD",
+ "TMP=$$(mktemp -d || mktemp -d -t bazel-tmp)",
+ "(" + cmd + ")",
+ ])
+ native.genrule(
+ cmd = cmd,
+ **kwargs
+ )
diff --git a/tools/bzl/gwt.bzl b/tools/bzl/gwt.bzl
index 71ba750..2adb7dd 100644
--- a/tools/bzl/gwt.bzl
+++ b/tools/bzl/gwt.bzl
@@ -90,117 +90,122 @@
</module>
"""
-def gwt_module(gwt_xml=None, resources=[], srcs=[], **kwargs):
- if gwt_xml:
- resources = resources + [gwt_xml]
+def gwt_module(gwt_xml = None, resources = [], srcs = [], **kwargs):
+ if gwt_xml:
+ resources = resources + [gwt_xml]
- java_library2(
- srcs = srcs,
- resources = resources,
- **kwargs)
+ java_library2(
+ srcs = srcs,
+ resources = resources,
+ **kwargs
+ )
def _gwt_user_agent_module(ctx):
- """Generate user agent specific GWT module."""
- if not ctx.attr.user_agent:
- return None
+ """Generate user agent specific GWT module."""
+ if not ctx.attr.user_agent:
+ return None
- ua = ctx.attr.user_agent
- impl = ua
- if ua in ALIASES:
- impl = ALIASES[ua]
+ ua = ctx.attr.user_agent
+ impl = ua
+ if ua in ALIASES:
+ impl = ALIASES[ua]
- # intermediate artifact: user agent speific GWT xml file
- gwt_user_agent_xml = ctx.new_file(ctx.label.name + "_gwt.xml")
- ctx.file_action(output = gwt_user_agent_xml,
- content=USER_AGENT_XML % (MODULE, impl))
+ # intermediate artifact: user agent speific GWT xml file
+ gwt_user_agent_xml = ctx.new_file(ctx.label.name + "_gwt.xml")
+ ctx.file_action(
+ output = gwt_user_agent_xml,
+ content = USER_AGENT_XML % (MODULE, impl),
+ )
- # intermediate artifact: user agent specific zip with GWT module
- gwt_user_agent_zip = ctx.new_file(ctx.label.name + "_gwt.zip")
- gwt = '%s_%s.gwt.xml' % (MODULE.replace('.', '/'), ua)
- dir = gwt_user_agent_zip.path + ".dir"
- cmd = " && ".join([
- "p=$PWD",
- "mkdir -p %s" % dir,
- "cd %s" % dir,
- "mkdir -p $(dirname %s)" % gwt,
- "cp $p/%s %s" % (gwt_user_agent_xml.path, gwt),
- "$p/%s cC $p/%s $(find . | sed 's|^./||')" % (ctx.executable._zip.path, gwt_user_agent_zip.path)
- ])
- ctx.actions.run_shell(
- inputs = [gwt_user_agent_xml] + ctx.files._zip,
- outputs = [gwt_user_agent_zip],
- command = cmd,
- mnemonic = "GenerateUserAgentGWTModule")
+ # intermediate artifact: user agent specific zip with GWT module
+ gwt_user_agent_zip = ctx.new_file(ctx.label.name + "_gwt.zip")
+ gwt = "%s_%s.gwt.xml" % (MODULE.replace(".", "/"), ua)
+ dir = gwt_user_agent_zip.path + ".dir"
+ cmd = " && ".join([
+ "p=$PWD",
+ "mkdir -p %s" % dir,
+ "cd %s" % dir,
+ "mkdir -p $(dirname %s)" % gwt,
+ "cp $p/%s %s" % (gwt_user_agent_xml.path, gwt),
+ "$p/%s cC $p/%s $(find . | sed 's|^./||')" % (ctx.executable._zip.path, gwt_user_agent_zip.path),
+ ])
+ ctx.actions.run_shell(
+ inputs = [gwt_user_agent_xml] + ctx.files._zip,
+ outputs = [gwt_user_agent_zip],
+ command = cmd,
+ mnemonic = "GenerateUserAgentGWTModule",
+ )
- return struct(
- zip=gwt_user_agent_zip,
- module=MODULE + '_' + ua
- )
+ return struct(
+ zip = gwt_user_agent_zip,
+ module = MODULE + "_" + ua,
+ )
def _gwt_binary_impl(ctx):
- module = ctx.attr.module[0]
- output_zip = ctx.outputs.output
- output_dir = output_zip.path + '.gwt_output'
- deploy_dir = output_zip.path + '.gwt_deploy'
+ module = ctx.attr.module[0]
+ output_zip = ctx.outputs.output
+ output_dir = output_zip.path + ".gwt_output"
+ deploy_dir = output_zip.path + ".gwt_deploy"
- deps = _get_transitive_closure(ctx)
+ deps = _get_transitive_closure(ctx)
- paths = []
- for dep in deps:
- paths.append(dep.path)
+ paths = []
+ for dep in deps:
+ paths.append(dep.path)
- gwt_user_agent_modules = []
- ua = _gwt_user_agent_module(ctx)
- if ua:
- paths.append(ua.zip.path)
- gwt_user_agent_modules.append(ua.zip)
- module = ua.module
+ gwt_user_agent_modules = []
+ ua = _gwt_user_agent_module(ctx)
+ if ua:
+ paths.append(ua.zip.path)
+ gwt_user_agent_modules.append(ua.zip)
+ module = ua.module
- cmd = "%s %s -Dgwt.normalizeTimestamps=true -cp %s %s -war %s -deploy %s " % (
- ctx.attr._jdk[java_common.JavaRuntimeInfo].java_executable_exec_path,
- " ".join(ctx.attr.jvm_args),
- ":".join(paths),
- GWT_COMPILER,
- output_dir,
- deploy_dir,
- )
- # TODO(davido): clean up command concatenation
- cmd += " ".join([
- "-style %s" % ctx.attr.style,
- "-optimize %s" % ctx.attr.optimize,
- "-strict",
- " ".join(ctx.attr.compiler_args),
- module + "\n",
- "rm -rf %s/gwt-unitCache\n" % output_dir,
- "root=`pwd`\n",
- "cd %s; $root/%s Cc ../%s $(find .)\n" % (
- output_dir,
- ctx.executable._zip.path,
- output_zip.basename,
+ cmd = "%s %s -Dgwt.normalizeTimestamps=true -cp %s %s -war %s -deploy %s " % (
+ ctx.attr._jdk[java_common.JavaRuntimeInfo].java_executable_exec_path,
+ " ".join(ctx.attr.jvm_args),
+ ":".join(paths),
+ GWT_COMPILER,
+ output_dir,
+ deploy_dir,
)
- ])
- ctx.actions.run_shell(
- inputs = list(deps) + gwt_user_agent_modules,
- outputs = [output_zip],
- tools = ctx.files._jdk + ctx.files._zip,
- mnemonic = "GwtBinary",
- progress_message = "GWT compiling " + output_zip.short_path,
- command = "set -e\n" + cmd,
- )
+ # TODO(davido): clean up command concatenation
+ cmd += " ".join([
+ "-style %s" % ctx.attr.style,
+ "-optimize %s" % ctx.attr.optimize,
+ "-strict",
+ " ".join(ctx.attr.compiler_args),
+ module + "\n",
+ "rm -rf %s/gwt-unitCache\n" % output_dir,
+ "root=`pwd`\n",
+ "cd %s; $root/%s Cc ../%s $(find .)\n" % (
+ output_dir,
+ ctx.executable._zip.path,
+ output_zip.basename,
+ ),
+ ])
+
+ ctx.actions.run_shell(
+ inputs = list(deps) + gwt_user_agent_modules,
+ outputs = [output_zip],
+ tools = ctx.files._jdk + ctx.files._zip,
+ mnemonic = "GwtBinary",
+ progress_message = "GWT compiling " + output_zip.short_path,
+ command = "set -e\n" + cmd,
+ )
def _get_transitive_closure(ctx):
- deps = depset()
- for dep in ctx.attr.module_deps:
- deps += dep.java.transitive_runtime_deps
- deps += dep.java.transitive_source_jars
- for dep in ctx.attr.deps:
- if hasattr(dep, 'java'):
- deps += dep.java.transitive_runtime_deps
- elif hasattr(dep, 'files'):
- deps += dep.files
+ deps = depset()
+ for dep in ctx.attr.module_deps:
+ deps += dep.java.transitive_runtime_deps
+ deps += dep.java.transitive_source_jars
+ for dep in ctx.attr.deps:
+ if hasattr(dep, "java"):
+ deps += dep.java.transitive_runtime_deps
+ elif hasattr(dep, "files"):
+ deps += dep.files
- return deps
+ return deps
gwt_binary = rule(
attrs = {
@@ -230,77 +235,78 @@
)
def gwt_genrule(suffix = ""):
- dbg = 'ui_dbg' + suffix
- opt = 'ui_opt' + suffix
- module_dep = ':ui_module' + suffix
- args = GWT_COMPILER_ARGS_RELEASE_MODE if suffix == "_r" else GWT_COMPILER_ARGS
+ dbg = "ui_dbg" + suffix
+ opt = "ui_opt" + suffix
+ module_dep = ":ui_module" + suffix
+ args = GWT_COMPILER_ARGS_RELEASE_MODE if suffix == "_r" else GWT_COMPILER_ARGS
- genrule2(
- name = 'ui_optdbg' + suffix,
- srcs = [
- ':' + dbg,
- ':' + opt,
- ],
- cmd = 'cd $$TMP;' +
- 'unzip -q $$ROOT/$(location :%s);' % dbg +
- 'mv' +
- ' gerrit_ui/gerrit_ui.nocache.js' +
- ' gerrit_ui/dbg_gerrit_ui.nocache.js;' +
- 'unzip -qo $$ROOT/$(location :%s);' % opt +
- 'mkdir -p $$(dirname $@);' +
- 'zip -qrD $$ROOT/$@ .',
- outs = ['ui_optdbg' + suffix + '.zip'],
- visibility = ['//visibility:public'],
- )
+ genrule2(
+ name = "ui_optdbg" + suffix,
+ srcs = [
+ ":" + dbg,
+ ":" + opt,
+ ],
+ cmd = "cd $$TMP;" +
+ "unzip -q $$ROOT/$(location :%s);" % dbg +
+ "mv" +
+ " gerrit_ui/gerrit_ui.nocache.js" +
+ " gerrit_ui/dbg_gerrit_ui.nocache.js;" +
+ "unzip -qo $$ROOT/$(location :%s);" % opt +
+ "mkdir -p $$(dirname $@);" +
+ "zip -qrD $$ROOT/$@ .",
+ outs = ["ui_optdbg" + suffix + ".zip"],
+ visibility = ["//visibility:public"],
+ )
- gwt_binary(
- name = opt,
- module = [MODULE],
- module_deps = [module_dep],
- deps = DEPS,
- compiler_args = args,
- jvm_args = GWT_JVM_ARGS,
- )
+ gwt_binary(
+ name = opt,
+ module = [MODULE],
+ module_deps = [module_dep],
+ deps = DEPS,
+ compiler_args = args,
+ jvm_args = GWT_JVM_ARGS,
+ )
- gwt_binary(
- name = dbg,
- style = 'PRETTY',
- optimize = "0",
- module_deps = [module_dep],
- deps = DEPS,
- compiler_args = GWT_COMPILER_ARGS,
- jvm_args = GWT_JVM_ARGS,
- )
+ gwt_binary(
+ name = dbg,
+ style = "PRETTY",
+ optimize = "0",
+ module_deps = [module_dep],
+ deps = DEPS,
+ compiler_args = GWT_COMPILER_ARGS,
+ jvm_args = GWT_JVM_ARGS,
+ )
def gen_ui_module(name, suffix = ""):
- gwt_module(
- name = name + suffix,
- srcs = native.glob(['src/main/java/**/*.java']),
- gwt_xml = 'src/main/java/%s.gwt.xml' % MODULE.replace('.', '/'),
- resources = native.glob(
- ['src/main/java/**/*'],
- exclude = ['src/main/java/**/*.java'] +
- ['src/main/java/%s.gwt.xml' % MODULE.replace('.', '/')]),
- deps = [
- '//gerrit-gwtui-common:diffy_logo',
- '//gerrit-gwtui-common:client',
- '//java/com/google/gwtexpui/css',
- '//lib/codemirror:codemirror' + suffix,
- '//lib/gwt:user',
- ],
- visibility = ['//visibility:public'],
- )
+ gwt_module(
+ name = name + suffix,
+ srcs = native.glob(["src/main/java/**/*.java"]),
+ gwt_xml = "src/main/java/%s.gwt.xml" % MODULE.replace(".", "/"),
+ resources = native.glob(
+ ["src/main/java/**/*"],
+ exclude = ["src/main/java/**/*.java"] +
+ ["src/main/java/%s.gwt.xml" % MODULE.replace(".", "/")],
+ ),
+ deps = [
+ "//gerrit-gwtui-common:diffy_logo",
+ "//gerrit-gwtui-common:client",
+ "//java/com/google/gwtexpui/css",
+ "//lib/codemirror:codemirror" + suffix,
+ "//lib/gwt:user",
+ ],
+ visibility = ["//visibility:public"],
+ )
def gwt_user_agent_permutations():
- for ua in BROWSERS:
- gwt_binary(
- name = "ui_%s" % ua,
- user_agent = ua,
- style = 'PRETTY',
- optimize = "0",
- module = [MODULE],
- module_deps = [':ui_module'],
- deps = DEPS,
- compiler_args = GWT_COMPILER_ARGS,
- jvm_args = GWT_JVM_ARGS,
- )
+ for ua in BROWSERS:
+ gwt_binary(
+ name = "ui_%s" % ua,
+ user_agent = ua,
+ style = "PRETTY",
+ optimize = "0",
+ module = [MODULE],
+ module_deps = [":ui_module"],
+ deps = DEPS,
+ compiler_args = GWT_COMPILER_ARGS,
+ jvm_args = GWT_JVM_ARGS,
+ )
diff --git a/tools/bzl/java.bzl b/tools/bzl/java.bzl
index 5fca724..7c41fbe 100644
--- a/tools/bzl/java.bzl
+++ b/tools/bzl/java.bzl
@@ -15,11 +15,12 @@
# Syntactic sugar for native java_library() rule:
# accept exported_deps attributes
-def java_library2(deps=[], exported_deps=[], exports=[], **kwargs):
- if exported_deps:
- deps = deps + exported_deps
- exports = exports + exported_deps
- native.java_library(
- deps = deps,
- exports = exports,
- **kwargs)
+def java_library2(deps = [], exported_deps = [], exports = [], **kwargs):
+ if exported_deps:
+ deps = deps + exported_deps
+ exports = exports + exported_deps
+ native.java_library(
+ deps = deps,
+ exports = exports,
+ **kwargs
+ )
diff --git a/tools/bzl/javadoc.bzl b/tools/bzl/javadoc.bzl
index f49c881..34ae9d2 100644
--- a/tools/bzl/javadoc.bzl
+++ b/tools/bzl/javadoc.bzl
@@ -15,49 +15,51 @@
# Javadoc rule.
def _impl(ctx):
- zip_output = ctx.outputs.zip
+ zip_output = ctx.outputs.zip
- transitive_jar_set = depset()
- source_jars = depset()
- for l in ctx.attr.libs:
- source_jars += l.java.source_jars
- transitive_jar_set += l.java.transitive_deps
+ transitive_jar_set = depset()
+ source_jars = depset()
+ for l in ctx.attr.libs:
+ source_jars += l.java.source_jars
+ transitive_jar_set += l.java.transitive_deps
- transitive_jar_paths = [j.path for j in transitive_jar_set]
- dir = ctx.outputs.zip.path + ".dir"
- source = ctx.outputs.zip.path + ".source"
- external_docs = ["http://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
- cmd = [
- "TZ=UTC",
- "export TZ",
- "rm -rf %s" % source,
- "mkdir %s" % source,
- " && ".join(["unzip -qud %s %s" % (source, j.path) for j in source_jars]),
- "rm -rf %s" % dir,
- "mkdir %s" % dir,
- " ".join([
- ctx.file._javadoc.path,
- "-Xdoclint:-missing",
- "-protected",
- "-encoding UTF-8",
- "-charset UTF-8",
- "-notimestamp",
- "-quiet",
- "-windowtitle '%s'" % ctx.attr.title,
- " ".join(['-link %s' % url for url in external_docs]),
- "-sourcepath %s" % source,
- "-subpackages ",
- ":".join(ctx.attr.pkgs),
- " -classpath ",
- ":".join(transitive_jar_paths),
- "-d %s" % dir]),
- "find %s -exec touch -t 198001010000 '{}' ';'" % dir,
- "(cd %s && zip -Xqr ../%s *)" % (dir, ctx.outputs.zip.basename),
- ]
- ctx.actions.run_shell(
- inputs = list(transitive_jar_set) + list(source_jars) + ctx.files._jdk,
- outputs = [zip_output],
- command = " && ".join(cmd))
+ transitive_jar_paths = [j.path for j in transitive_jar_set]
+ dir = ctx.outputs.zip.path + ".dir"
+ source = ctx.outputs.zip.path + ".source"
+ external_docs = ["http://docs.oracle.com/javase/8/docs/api"] + ctx.attr.external_docs
+ cmd = [
+ "TZ=UTC",
+ "export TZ",
+ "rm -rf %s" % source,
+ "mkdir %s" % source,
+ " && ".join(["unzip -qud %s %s" % (source, j.path) for j in source_jars]),
+ "rm -rf %s" % dir,
+ "mkdir %s" % dir,
+ " ".join([
+ ctx.file._javadoc.path,
+ "-Xdoclint:-missing",
+ "-protected",
+ "-encoding UTF-8",
+ "-charset UTF-8",
+ "-notimestamp",
+ "-quiet",
+ "-windowtitle '%s'" % ctx.attr.title,
+ " ".join(["-link %s" % url for url in external_docs]),
+ "-sourcepath %s" % source,
+ "-subpackages ",
+ ":".join(ctx.attr.pkgs),
+ " -classpath ",
+ ":".join(transitive_jar_paths),
+ "-d %s" % dir,
+ ]),
+ "find %s -exec touch -t 198001010000 '{}' ';'" % dir,
+ "(cd %s && zip -Xqr ../%s *)" % (dir, ctx.outputs.zip.basename),
+ ]
+ ctx.actions.run_shell(
+ inputs = list(transitive_jar_set) + list(source_jars) + ctx.files._jdk,
+ outputs = [zip_output],
+ command = " && ".join(cmd),
+ )
java_doc = rule(
attrs = {
diff --git a/tools/bzl/js.bzl b/tools/bzl/js.bzl
index 2796f64..6590cd6 100644
--- a/tools/bzl/js.bzl
+++ b/tools/bzl/js.bzl
@@ -2,37 +2,38 @@
GERRIT = "GERRIT:"
-load("//lib/js:npm.bzl", "NPM_VERSIONS", "NPM_SHA1S")
+load("//lib/js:npm.bzl", "NPM_SHA1S", "NPM_VERSIONS")
+load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_binary", "closure_js_library")
def _npm_tarball(name):
- return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])
+ return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])
def _npm_binary_impl(ctx):
- """rule to download a NPM archive."""
- name = ctx.name
- version= NPM_VERSIONS[name]
- sha1 = NPM_SHA1S[name]
+ """rule to download a NPM archive."""
+ name = ctx.name
+ version = NPM_VERSIONS[name]
+ sha1 = NPM_SHA1S[name]
- dir = '%s-%s' % (name, version)
- filename = '%s.tgz' % dir
- base = '%s@%s.npm_binary.tgz' % (name, version)
- dest = ctx.path(base)
- repository = ctx.attr.repository
- if repository == GERRIT:
- url = 'http://gerrit-maven.storage.googleapis.com/npm-packages/%s' % filename
- elif repository == NPMJS:
- url = 'http://registry.npmjs.org/%s/-/%s' % (name, filename)
- else:
- fail('repository %s not in {%s,%s}' % (repository, GERRIT, NPMJS))
+ dir = "%s-%s" % (name, version)
+ filename = "%s.tgz" % dir
+ base = "%s@%s.npm_binary.tgz" % (name, version)
+ dest = ctx.path(base)
+ repository = ctx.attr.repository
+ if repository == GERRIT:
+ url = "http://gerrit-maven.storage.googleapis.com/npm-packages/%s" % filename
+ elif repository == NPMJS:
+ url = "http://registry.npmjs.org/%s/-/%s" % (name, filename)
+ else:
+ fail("repository %s not in {%s,%s}" % (repository, GERRIT, NPMJS))
- python = ctx.which("python")
- script = ctx.path(ctx.attr._download_script)
+ python = ctx.which("python")
+ script = ctx.path(ctx.attr._download_script)
- args = [python, script, "-o", dest, "-u", url, "-v", sha1]
- out = ctx.execute(args)
- if out.return_code:
- fail("failed %s: %s" % (args, out.stderr))
- ctx.file("BUILD", "package(default_visibility=['//visibility:public'])\nfilegroup(name='tarball', srcs=['%s'])" % base, False)
+ args = [python, script, "-o", dest, "-u", url, "-v", sha1]
+ out = ctx.execute(args)
+ if out.return_code:
+ fail("failed %s: %s" % (args, out.stderr))
+ ctx.file("BUILD", "package(default_visibility=['//visibility:public'])\nfilegroup(name='tarball', srcs=['%s'])" % base, False)
npm_binary = repository_rule(
attrs = {
@@ -46,64 +47,75 @@
# for use in repo rules.
def _run_npm_binary_str(ctx, tarball, args):
- python_bin = ctx.which("python")
- return " ".join([
- python_bin,
- ctx.path(ctx.attr._run_npm),
- ctx.path(tarball)] + args)
+ python_bin = ctx.which("python")
+ return " ".join([
+ python_bin,
+ ctx.path(ctx.attr._run_npm),
+ ctx.path(tarball),
+ ] + args)
def _bower_archive(ctx):
- """Download a bower package."""
- download_name = '%s__download_bower.zip' % ctx.name
- renamed_name = '%s__renamed.zip' % ctx.name
- version_name = '%s__version.json' % ctx.name
+ """Download a bower package."""
+ download_name = "%s__download_bower.zip" % ctx.name
+ renamed_name = "%s__renamed.zip" % ctx.name
+ version_name = "%s__version.json" % ctx.name
- cmd = [
- ctx.which("python"),
- ctx.path(ctx.attr._download_bower),
- '-b', '%s' % _run_npm_binary_str(ctx, ctx.attr._bower_archive, []),
- '-n', ctx.name,
- '-p', ctx.attr.package,
- '-v', ctx.attr.version,
- '-s', ctx.attr.sha1,
- '-o', download_name,
+ cmd = [
+ ctx.which("python"),
+ ctx.path(ctx.attr._download_bower),
+ "-b",
+ "%s" % _run_npm_binary_str(ctx, ctx.attr._bower_archive, []),
+ "-n",
+ ctx.name,
+ "-p",
+ ctx.attr.package,
+ "-v",
+ ctx.attr.version,
+ "-s",
+ ctx.attr.sha1,
+ "-o",
+ download_name,
]
- out = ctx.execute(cmd)
- if out.return_code:
- fail("failed %s: %s" % (" ".join(cmd), out.stderr))
+ out = ctx.execute(cmd)
+ if out.return_code:
+ fail("failed %s: %s" % (" ".join(cmd), out.stderr))
- _bash(ctx, " && " .join([
- "TMP=$(mktemp -d || mktemp -d -t bazel-tmp)",
- "TZ=UTC",
- "export UTC",
- "cd $TMP",
- "mkdir bower_components",
- "cd bower_components",
- "unzip %s" % ctx.path(download_name),
- "cd ..",
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xr %s bower_components" % renamed_name,
- "cd ..",
- "rm -rf ${TMP}",
- ]))
+ _bash(ctx, " && ".join([
+ "TMP=$(mktemp -d || mktemp -d -t bazel-tmp)",
+ "TZ=UTC",
+ "export UTC",
+ "cd $TMP",
+ "mkdir bower_components",
+ "cd bower_components",
+ "unzip %s" % ctx.path(download_name),
+ "cd ..",
+ "find . -exec touch -t 198001010000 '{}' ';'",
+ "zip -Xr %s bower_components" % renamed_name,
+ "cd ..",
+ "rm -rf ${TMP}",
+ ]))
- dep_version = ctx.attr.semver if ctx.attr.semver else ctx.attr.version
- ctx.file(version_name,
- '"%s":"%s#%s"' % (ctx.name, ctx.attr.package, dep_version))
- ctx.file(
- "BUILD",
- "\n".join([
- "package(default_visibility=['//visibility:public'])",
- "filegroup(name = 'zipfile', srcs = ['%s'], )" % download_name,
- "filegroup(name = 'version_json', srcs = ['%s'], visibility=['//visibility:public'])" % version_name,
- ]), False)
+ dep_version = ctx.attr.semver if ctx.attr.semver else ctx.attr.version
+ ctx.file(
+ version_name,
+ '"%s":"%s#%s"' % (ctx.name, ctx.attr.package, dep_version),
+ )
+ ctx.file(
+ "BUILD",
+ "\n".join([
+ "package(default_visibility=['//visibility:public'])",
+ "filegroup(name = 'zipfile', srcs = ['%s'], )" % download_name,
+ "filegroup(name = 'version_json', srcs = ['%s'], visibility=['//visibility:public'])" % version_name,
+ ]),
+ False,
+ )
def _bash(ctx, cmd):
- cmd_list = ["bash", "-c", cmd]
- out = ctx.execute(cmd_list)
- if out.return_code:
- fail("failed %s: %s" % (" ".join(cmd_list), out.stderr))
+ cmd_list = ["bash", "-c", cmd]
+ out = ctx.execute(cmd_list)
+ if out.return_code:
+ fail("failed %s: %s" % (" ".join(cmd_list), out.stderr))
bower_archive = repository_rule(
_bower_archive,
@@ -119,26 +131,26 @@
)
def _bower_component_impl(ctx):
- transitive_zipfiles = depset([ctx.file.zipfile])
- for d in ctx.attr.deps:
- transitive_zipfiles += d.transitive_zipfiles
+ transitive_zipfiles = depset([ctx.file.zipfile])
+ for d in ctx.attr.deps:
+ transitive_zipfiles += d.transitive_zipfiles
- transitive_licenses = depset()
- if ctx.file.license:
- transitive_licenses += depset([ctx.file.license])
+ transitive_licenses = depset()
+ if ctx.file.license:
+ transitive_licenses += depset([ctx.file.license])
- for d in ctx.attr.deps:
- transitive_licenses += d.transitive_licenses
+ for d in ctx.attr.deps:
+ transitive_licenses += d.transitive_licenses
- transitive_versions = depset(ctx.files.version_json)
- for d in ctx.attr.deps:
- transitive_versions += d.transitive_versions
+ transitive_versions = depset(ctx.files.version_json)
+ for d in ctx.attr.deps:
+ transitive_versions += d.transitive_versions
- return struct(
- transitive_zipfiles=transitive_zipfiles,
- transitive_versions=transitive_versions,
- transitive_licenses=transitive_licenses,
- )
+ return struct(
+ transitive_licenses = transitive_licenses,
+ transitive_versions = transitive_versions,
+ transitive_zipfiles = transitive_zipfiles,
+ )
_common_attrs = {
"deps": attr.label_list(providers = [
@@ -149,35 +161,37 @@
}
def _js_component(ctx):
- dir = ctx.outputs.zip.path + ".dir"
- name = ctx.outputs.zip.basename
- if name.endswith(".zip"):
- name = name[:-4]
- dest = "%s/%s" % (dir, name)
- cmd = " && ".join([
- "TZ=UTC",
- "export TZ",
- "mkdir -p %s" % dest,
- "cp %s %s/" % (' '.join([s.path for s in ctx.files.srcs]), dest),
- "cd %s" % dir,
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xqr ../%s *" % ctx.outputs.zip.basename
- ])
+ dir = ctx.outputs.zip.path + ".dir"
+ name = ctx.outputs.zip.basename
+ if name.endswith(".zip"):
+ name = name[:-4]
+ dest = "%s/%s" % (dir, name)
+ cmd = " && ".join([
+ "TZ=UTC",
+ "export TZ",
+ "mkdir -p %s" % dest,
+ "cp %s %s/" % (" ".join([s.path for s in ctx.files.srcs]), dest),
+ "cd %s" % dir,
+ "find . -exec touch -t 198001010000 '{}' ';'",
+ "zip -Xqr ../%s *" % ctx.outputs.zip.basename,
+ ])
- ctx.actions.run_shell(
- inputs = ctx.files.srcs,
- outputs = [ctx.outputs.zip],
- command = cmd,
- mnemonic = "GenBowerZip")
+ ctx.actions.run_shell(
+ inputs = ctx.files.srcs,
+ outputs = [ctx.outputs.zip],
+ command = cmd,
+ mnemonic = "GenBowerZip",
+ )
- licenses = depset()
- if ctx.file.license:
- licenses += depset([ctx.file.license])
+ licenses = depset()
+ if ctx.file.license:
+ licenses += depset([ctx.file.license])
- return struct(
- transitive_zipfiles=list([ctx.outputs.zip]),
- transitive_versions=depset(),
- transitive_licenses=licenses)
+ return struct(
+ transitive_licenses = licenses,
+ transitive_versions = depset(),
+ transitive_zipfiles = list([ctx.outputs.zip]),
+ )
js_component = rule(
_js_component,
@@ -203,61 +217,65 @@
)
# TODO(hanwen): make license mandatory.
-def bower_component(name, license=None, **kwargs):
- prefix = "//lib:LICENSE-"
- if license and not license.startswith(prefix):
- license = prefix + license
- _bower_component(
- name=name,
- license=license,
- zipfile="@%s//:zipfile"% name,
- version_json="@%s//:version_json" % name,
- **kwargs)
+def bower_component(name, license = None, **kwargs):
+ prefix = "//lib:LICENSE-"
+ if license and not license.startswith(prefix):
+ license = prefix + license
+ _bower_component(
+ name = name,
+ license = license,
+ zipfile = "@%s//:zipfile" % name,
+ version_json = "@%s//:version_json" % name,
+ **kwargs
+ )
def _bower_component_bundle_impl(ctx):
- """A bunch of bower components zipped up."""
- zips = depset()
- for d in ctx.attr.deps:
- zips += d.transitive_zipfiles
+ """A bunch of bower components zipped up."""
+ zips = depset()
+ for d in ctx.attr.deps:
+ zips += d.transitive_zipfiles
- versions = depset()
- for d in ctx.attr.deps:
- versions += d.transitive_versions
+ versions = depset()
+ for d in ctx.attr.deps:
+ versions += d.transitive_versions
- licenses = depset()
- for d in ctx.attr.deps:
- licenses += d.transitive_versions
+ licenses = depset()
+ for d in ctx.attr.deps:
+ licenses += d.transitive_versions
- out_zip = ctx.outputs.zip
- out_versions = ctx.outputs.version_json
+ out_zip = ctx.outputs.zip
+ out_versions = ctx.outputs.version_json
- ctx.actions.run_shell(
- inputs=list(zips),
- outputs=[out_zip],
- command=" && ".join([
- "p=$PWD",
- "TZ=UTC",
- "export TZ",
- "rm -rf %s.dir" % out_zip.path,
- "mkdir -p %s.dir/bower_components" % out_zip.path,
- "cd %s.dir/bower_components" % out_zip.path,
- "for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips])),
- "cd ..",
- "find . -exec touch -t 198001010000 '{}' ';'",
- "zip -Xqr $p/%s bower_components/*" % out_zip.path,
- ]),
- mnemonic="BowerCombine")
+ ctx.actions.run_shell(
+ inputs = list(zips),
+ outputs = [out_zip],
+ command = " && ".join([
+ "p=$PWD",
+ "TZ=UTC",
+ "export TZ",
+ "rm -rf %s.dir" % out_zip.path,
+ "mkdir -p %s.dir/bower_components" % out_zip.path,
+ "cd %s.dir/bower_components" % out_zip.path,
+ "for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips])),
+ "cd ..",
+ "find . -exec touch -t 198001010000 '{}' ';'",
+ "zip -Xqr $p/%s bower_components/*" % out_zip.path,
+ ]),
+ mnemonic = "BowerCombine",
+ )
- ctx.actions.run_shell(
- inputs=list(versions),
- outputs=[out_versions],
- mnemonic="BowerVersions",
- command="(echo '{' ; for j in %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions]), out_versions.path))
+ ctx.actions.run_shell(
+ inputs = list(versions),
+ outputs = [out_versions],
+ mnemonic = "BowerVersions",
+ command = "(echo '{' ; for j in %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions]), out_versions.path),
+ )
- return struct(
- transitive_zipfiles=zips,
- transitive_versions=versions,
- transitive_licenses=licenses)
+ return struct(
+ transitive_licenses = licenses,
+ transitive_versions = versions,
+ transitive_zipfiles = zips,
+ )
bower_component_bundle = rule(
_bower_component_bundle_impl,
@@ -279,80 +297,99 @@
"""
def _vulcanize_impl(ctx):
- # intermediate artifact if split is wanted.
- if ctx.attr.split:
- vulcanized = ctx.new_file(
- ctx.configuration.genfiles_dir, ctx.outputs.html, ".vulcanized.html")
- else:
- vulcanized = ctx.outputs.html
- destdir = ctx.outputs.html.path + ".dir"
- zips = [z for d in ctx.attr.deps for z in d.transitive_zipfiles ]
+ # intermediate artifact if split is wanted.
+ if ctx.attr.split:
+ vulcanized = ctx.new_file(
+ ctx.configuration.genfiles_dir,
+ ctx.outputs.html,
+ ".vulcanized.html",
+ )
+ else:
+ vulcanized = ctx.outputs.html
+ destdir = ctx.outputs.html.path + ".dir"
+ zips = [z for d in ctx.attr.deps for z in d.transitive_zipfiles]
- hermetic_npm_binary = " ".join([
- 'python',
- "$p/" + ctx.file._run_npm.path,
- "$p/" + ctx.file._vulcanize_archive.path,
- '--inline-scripts',
- '--inline-css',
- '--strip-comments',
- '--out-html', "$p/" + vulcanized.path,
- ctx.file.app.path
- ])
+ hermetic_npm_binary = " ".join([
+ "python",
+ "$p/" + ctx.file._run_npm.path,
+ "$p/" + ctx.file._vulcanize_archive.path,
+ "--inline-scripts",
+ "--inline-css",
+ "--strip-comments",
+ "--out-html",
+ "$p/" + vulcanized.path,
+ ctx.file.app.path,
+ ])
- pkg_dir = ctx.attr.pkg.lstrip("/")
- cmd = " && ".join([
- # unpack dependencies.
- "export PATH",
- "p=$PWD",
- "rm -rf %s" % destdir,
- "mkdir -p %s/%s/bower_components" % (destdir, pkg_dir),
- "for z in %s; do unzip -qd %s/%s/bower_components/ $z; done" % (
- ' '.join([z.path for z in zips]), destdir, pkg_dir),
- "tar -cf - %s | tar -C %s -xf -" % (" ".join([s.path for s in ctx.files.srcs]), destdir),
- "cd %s" % destdir,
- hermetic_npm_binary,
- ])
+ pkg_dir = ctx.attr.pkg.lstrip("/")
+ cmd = " && ".join([
+ # unpack dependencies.
+ "export PATH",
+ "p=$PWD",
+ "rm -rf %s" % destdir,
+ "mkdir -p %s/%s/bower_components" % (destdir, pkg_dir),
+ "for z in %s; do unzip -qd %s/%s/bower_components/ $z; done" % (
+ " ".join([z.path for z in zips]),
+ destdir,
+ pkg_dir,
+ ),
+ "tar -cf - %s | tar -C %s -xf -" % (" ".join([s.path for s in ctx.files.srcs]), destdir),
+ "cd %s" % destdir,
+ hermetic_npm_binary,
+ ])
- # Node/NPM is not (yet) hermeticized, so we have to get the binary
- # from the environment, and it may be under $HOME, so we can't run
- # in the sandbox.
- node_tweaks = dict(
- use_default_shell_env = True,
- execution_requirements = {"local": "1"},
- )
- ctx.actions.run_shell(
- mnemonic = "Vulcanize",
- inputs = [ctx.file._run_npm, ctx.file.app,
- ctx.file._vulcanize_archive
- ] + list(zips) + ctx.files.srcs,
- outputs = [vulcanized],
- command = cmd,
- **node_tweaks)
-
- if ctx.attr.split:
- hermetic_npm_command = "export PATH && " + " ".join([
- 'python',
- ctx.file._run_npm.path,
- ctx.file._crisper_archive.path,
- "--always-write-script",
- "--source", vulcanized.path,
- "--html", ctx.outputs.html.path,
- "--js", ctx.outputs.js.path])
-
+ # Node/NPM is not (yet) hermeticized, so we have to get the binary
+ # from the environment, and it may be under $HOME, so we can't run
+ # in the sandbox.
+ node_tweaks = dict(
+ execution_requirements = {"local": "1"},
+ use_default_shell_env = True,
+ )
ctx.actions.run_shell(
- mnemonic = "Crisper",
- inputs = [ctx.file._run_npm, ctx.file.app,
- ctx.file._crisper_archive, vulcanized],
- outputs = [ctx.outputs.js, ctx.outputs.html],
- command = hermetic_npm_command,
- **node_tweaks)
+ mnemonic = "Vulcanize",
+ inputs = [
+ ctx.file._run_npm,
+ ctx.file.app,
+ ctx.file._vulcanize_archive,
+ ] + list(zips) + ctx.files.srcs,
+ outputs = [vulcanized],
+ command = cmd,
+ **node_tweaks
+ )
+
+ if ctx.attr.split:
+ hermetic_npm_command = "export PATH && " + " ".join([
+ "python",
+ ctx.file._run_npm.path,
+ ctx.file._crisper_archive.path,
+ "--always-write-script",
+ "--source",
+ vulcanized.path,
+ "--html",
+ ctx.outputs.html.path,
+ "--js",
+ ctx.outputs.js.path,
+ ])
+
+ ctx.actions.run_shell(
+ mnemonic = "Crisper",
+ inputs = [
+ ctx.file._run_npm,
+ ctx.file.app,
+ ctx.file._crisper_archive,
+ vulcanized,
+ ],
+ outputs = [ctx.outputs.js, ctx.outputs.html],
+ command = hermetic_npm_command,
+ **node_tweaks
+ )
def _vulcanize_output_func(name, split):
- _ignore = [name] # unused.
- out = {"html": "%{name}.html"}
- if split:
- out["js"] = "%{name}.js"
- return out
+ _ignore = [name] # unused.
+ out = {"html": "%{name}.html"}
+ if split:
+ out["js"] = "%{name}.js"
+ return out
_vulcanize_rule = rule(
_vulcanize_impl,
@@ -388,9 +425,96 @@
)
def vulcanize(*args, **kwargs):
- """Vulcanize runs vulcanize and (optionally) crisper on a set of sources."""
- _vulcanize_rule(*args, pkg=PACKAGE_NAME, **kwargs)
+ """Vulcanize runs vulcanize and (optionally) crisper on a set of sources."""
+ _vulcanize_rule(*args, pkg = PACKAGE_NAME, **kwargs)
-def polygerrit_plugin(*args, **kwargs):
- """Bundles plugin dependencies for deployment."""
- _vulcanize_rule(*args, pkg=PACKAGE_NAME, **kwargs)
+def polygerrit_plugin(name, app, srcs = [], assets = None, **kwargs):
+ """Bundles plugin dependencies for deployment.
+
+ This rule bundles all Polymer elements and JS dependencies into .html and .js files.
+ Run-time dependencies (e.g. JS libraries loaded after plugin starts) should be provided using "assets" property.
+ Output of this rule is a FileSet with "${name}_fs", with deploy artifacts in "plugins/${name}/static".
+
+ Args:
+ name: String, plugin name.
+ app: String, the main or root source file.
+ assets: Fileset, additional files to be used by plugin in runtime, exported to "plugins/${name}/static".
+ srcs: Source files required for combining.
+ """
+
+ # Combines all .js and .html files into foo_combined.js and foo_combined.html
+ _vulcanize_rule(
+ name = name + "_combined",
+ app = app,
+ srcs = srcs if app in srcs else srcs + [app],
+ pkg = PACKAGE_NAME,
+ **kwargs
+ )
+
+ closure_js_binary(
+ name = name + "_bin",
+ compilation_level = "SIMPLE",
+ defs = [
+ "--polymer_version=1",
+ "--language_out=ECMASCRIPT6",
+ "--rewrite_polyfills=false",
+ ],
+ deps = [
+ name + "_closure_lib",
+ ],
+ )
+
+ closure_js_library(
+ name = name + "_closure_lib",
+ srcs = [name + "_combined.js"],
+ convention = "GOOGLE",
+ no_closure_library = True,
+ deps = [
+ "//lib/polymer_externs:polymer_closure",
+ "//polygerrit-ui/externs:plugin",
+ ],
+ )
+
+ native.genrule(
+ name = name + "_rename_html",
+ srcs = [name + "_combined.html"],
+ outs = [name + ".html"],
+ cmd = "sed 's/<script src=\"" + name + "_combined.js\"/<script src=\"" + name + ".js\"/g' $(SRCS) > $(OUTS)",
+ output_to_bindir = True,
+ )
+
+ native.genrule(
+ name = name + "_rename_js",
+ srcs = [name + "_bin.js"],
+ outs = [name + ".js"],
+ cmd = "cp $< $@",
+ output_to_bindir = True,
+ )
+
+ static_files = [
+ name + ".js",
+ name + ".html",
+ ]
+
+ if assets:
+ nested, direct = [], []
+ for x in assets:
+ target = nested if "/" in x else direct
+ target.append(x)
+
+ static_files += direct
+
+ if nested:
+ native.genrule(
+ name = name + "_copy_assets",
+ srcs = assets,
+ outs = [f.split("/")[-1] for f in nested],
+ cmd = "cp $(SRCS) $(@D)",
+ output_to_bindir = True,
+ )
+ static_files += [":" + name + "_copy_assets"]
+
+ native.filegroup(
+ name = name,
+ srcs = static_files,
+ )
diff --git a/tools/bzl/junit.bzl b/tools/bzl/junit.bzl
index 1abcc23..d711356 100644
--- a/tools/bzl/junit.bzl
+++ b/tools/bzl/junit.bzl
@@ -43,15 +43,17 @@
if findex != -1:
break
if findex == -1:
- fail("%s does not contain any of %s",
- fname, _PREFIXES)
+ fail("%s does not contain any of %s" % (fname, _PREFIXES))
return ".".join(toks[findex:]) + ".class"
def _impl(ctx):
classes = ",".join(
- [_AsClassName(x) for x in ctx.attr.srcs])
- ctx.file_action(output=ctx.outputs.out, content=_OUTPUT % (
- classes, ctx.attr.outname))
+ [_AsClassName(x) for x in ctx.attr.srcs],
+ )
+ ctx.file_action(output = ctx.outputs.out, content = _OUTPUT % (
+ classes,
+ ctx.attr.outname,
+ ))
_GenSuite = rule(
attrs = {
@@ -64,9 +66,11 @@
def junit_tests(name, srcs, **kwargs):
s_name = name + "TestSuite"
- _GenSuite(name = s_name,
- srcs = srcs,
- outname = s_name)
+ _GenSuite(
+ name = s_name,
+ srcs = srcs,
+ outname = s_name,
+ )
jvm_flags = kwargs.get("jvm_flags", [])
jvm_flags = jvm_flags + select({
"//:java9": [
@@ -78,7 +82,9 @@
],
"//conditions:default": [],
})
- native.java_test(name = name,
- test_class = s_name,
- srcs = srcs + [":"+s_name],
- **dict(kwargs, jvm_flags=jvm_flags))
+ native.java_test(
+ name = name,
+ test_class = s_name,
+ srcs = srcs + [":" + s_name],
+ **dict(kwargs, jvm_flags = jvm_flags)
+ )
diff --git a/tools/bzl/license.bzl b/tools/bzl/license.bzl
index 38dfbe5..f011446 100644
--- a/tools/bzl/license.bzl
+++ b/tools/bzl/license.bzl
@@ -1,57 +1,57 @@
def normalize_target_name(target):
- return target.replace("//", "").replace("/", "__").replace(":", "___")
+ return target.replace("//", "").replace("/", "__").replace(":", "___")
def license_map(name, targets = [], opts = [], **kwargs):
- """Generate XML for all targets that depend directly on a LICENSE file"""
- xmls = []
- tools = [ "//tools/bzl:license-map.py", "//lib:all-licenses" ]
- for target in targets:
- subname = name + "_" + normalize_target_name(target) + ".xml"
- xmls.append("$(location :%s)" % subname)
- tools.append(subname)
- native.genquery(
- name = subname,
- scope = [ target ],
+ """Generate XML for all targets that depend directly on a LICENSE file"""
+ xmls = []
+ tools = ["//tools/bzl:license-map.py", "//lib:all-licenses"]
+ for target in targets:
+ subname = name + "_" + normalize_target_name(target) + ".xml"
+ xmls.append("$(location :%s)" % subname)
+ tools.append(subname)
+ native.genquery(
+ name = subname,
+ scope = [target],
- # Find everything that depends on a license file, but remove
- # the license files themselves from this list.
- expression = 'rdeps(%s, filter("//lib:LICENSE.*", deps(%s)),1) - filter("//lib:LICENSE.*", deps(%s))' % (target, target, target),
+ # Find everything that depends on a license file, but remove
+ # the license files themselves from this list.
+ expression = 'rdeps(%s, filter("//lib:LICENSE.*", deps(%s)),1) - filter("//lib:LICENSE.*", deps(%s))' % (target, target, target),
- # We are interested in the edges of the graph ({java_library,
- # license-file} tuples). 'query' provides this in the XML output.
- opts = [ "--output=xml", ],
+ # We are interested in the edges of the graph ({java_library,
+ # license-file} tuples). 'query' provides this in the XML output.
+ opts = ["--output=xml"],
+ )
+
+ # post process the XML into our favorite format.
+ native.genrule(
+ name = "gen_license_txt_" + name,
+ cmd = "python $(location //tools/bzl:license-map.py) %s %s > $@" % (" ".join(opts), " ".join(xmls)),
+ outs = [name + ".txt"],
+ tools = tools,
+ **kwargs
)
- # post process the XML into our favorite format.
- native.genrule(
- name = "gen_license_txt_" + name,
- cmd = "python $(location //tools/bzl:license-map.py) %s %s > $@" % (" ".join(opts), " ".join(xmls)),
- outs = [ name + ".txt" ],
- tools = tools,
- **kwargs
- )
-
def license_test(name, target):
- """Make sure a target doesn't depend on DO_NOT_DISTRIBUTE license"""
- txt = name + "-forbidden.txt"
+ """Make sure a target doesn't depend on DO_NOT_DISTRIBUTE license"""
+ txt = name + "-forbidden.txt"
- # fully qualify target name.
- if target[0] not in ":/":
- target = ":" + target
- if target[0] != "/":
- target = "//" + PACKAGE_NAME + target
+ # fully qualify target name.
+ if target[0] not in ":/":
+ target = ":" + target
+ if target[0] != "/":
+ target = "//" + PACKAGE_NAME + target
- forbidden = "//lib:LICENSE-DO_NOT_DISTRIBUTE"
- native.genquery(
- name = txt,
- scope = [ target, forbidden ],
- # Find everything that depends on a license file, but remove
- # the license files themselves from this list.
- expression = 'rdeps(%s, "%s", 1) - rdeps(%s, "%s", 0)' % (target, forbidden, target, forbidden),
- )
- native.sh_test(
- name = name,
- srcs = [ "//tools/bzl:test_license.sh" ],
- args = [ "$(location :%s)" % txt ],
- data = [ txt ],
- )
+ forbidden = "//lib:LICENSE-DO_NOT_DISTRIBUTE"
+ native.genquery(
+ name = txt,
+ scope = [target, forbidden],
+ # Find everything that depends on a license file, but remove
+ # the license files themselves from this list.
+ expression = 'rdeps(%s, "%s", 1) - rdeps(%s, "%s", 0)' % (target, forbidden, target, forbidden),
+ )
+ native.sh_test(
+ name = name,
+ srcs = ["//tools/bzl:test_license.sh"],
+ args = ["$(location :%s)" % txt],
+ data = [txt],
+ )
diff --git a/tools/bzl/maven.bzl b/tools/bzl/maven.bzl
index c255c0c..71aa91c 100644
--- a/tools/bzl/maven.bzl
+++ b/tools/bzl/maven.bzl
@@ -15,18 +15,18 @@
# Merge maven files
def cmd(jars):
- return ('$(location //tools:merge_jars) $@ '
- + ' '.join(['$(location %s)' % j for j in jars]))
+ return ("$(location //tools:merge_jars) $@ " +
+ " ".join(["$(location %s)" % j for j in jars]))
def merge_maven_jars(name, srcs, **kwargs):
- native.genrule(
- name = '%s__merged_bin' % name,
- cmd = cmd(srcs),
- tools = srcs + ['//tools:merge_jars'],
- outs = ['%s__merged.jar' % name],
- )
- native.java_import(
- name = name,
- jars = [':%s__merged_bin' % name],
- **kwargs
- )
+ native.genrule(
+ name = "%s__merged_bin" % name,
+ cmd = cmd(srcs),
+ tools = srcs + ["//tools:merge_jars"],
+ outs = ["%s__merged.jar" % name],
+ )
+ native.java_import(
+ name = name,
+ jars = [":%s__merged_bin" % name],
+ **kwargs
+ )
diff --git a/tools/bzl/maven_jar.bzl b/tools/bzl/maven_jar.bzl
index 55bfae1..2ebb2c2 100644
--- a/tools/bzl/maven_jar.bzl
+++ b/tools/bzl/maven_jar.bzl
@@ -7,69 +7,70 @@
MAVEN_LOCAL = "MAVEN_LOCAL:"
def _maven_release(ctx, parts):
- """induce jar and url name from maven coordinates."""
- if len(parts) not in [3, 4]:
- fail('%s:\nexpected id="groupId:artifactId:version[:classifier]"'
- % ctx.attr.artifact)
- if len(parts) == 4:
- group, artifact, version, classifier = parts
- file_version = version + '-' + classifier
- else:
- group, artifact, version = parts
- file_version = version
+ """induce jar and url name from maven coordinates."""
+ if len(parts) not in [3, 4]:
+ fail('%s:\nexpected id="groupId:artifactId:version[:classifier]"' %
+ ctx.attr.artifact)
+ if len(parts) == 4:
+ group, artifact, version, classifier = parts
+ file_version = version + "-" + classifier
+ else:
+ group, artifact, version = parts
+ file_version = version
- jar = artifact.lower() + '-' + file_version
- url = '/'.join([
- ctx.attr.repository,
- group.replace('.', '/'),
- artifact,
- version,
- artifact + '-' + file_version])
+ jar = artifact.lower() + "-" + file_version
+ url = "/".join([
+ ctx.attr.repository,
+ group.replace(".", "/"),
+ artifact,
+ version,
+ artifact + "-" + file_version,
+ ])
- return jar, url
+ return jar, url
# Creates a struct containing the different parts of an artifact's FQN
def _create_coordinates(fully_qualified_name):
- parts = fully_qualified_name.split(":")
- packaging = None
- classifier = None
+ parts = fully_qualified_name.split(":")
+ packaging = None
+ classifier = None
- if len(parts) == 3:
- group_id, artifact_id, version = parts
- elif len(parts) == 4:
- group_id, artifact_id, version, packaging = parts
- elif len(parts) == 5:
- group_id, artifact_id, version, packaging, classifier = parts
- else:
- fail("Invalid fully qualified name for artifact: %s" % fully_qualified_name)
+ if len(parts) == 3:
+ group_id, artifact_id, version = parts
+ elif len(parts) == 4:
+ group_id, artifact_id, version, packaging = parts
+ elif len(parts) == 5:
+ group_id, artifact_id, version, packaging, classifier = parts
+ else:
+ fail("Invalid fully qualified name for artifact: %s" % fully_qualified_name)
- return struct(
- fully_qualified_name = fully_qualified_name,
- group_id = group_id,
- artifact_id = artifact_id,
- packaging = packaging,
- classifier = classifier,
- version = version,
- )
+ return struct(
+ fully_qualified_name = fully_qualified_name,
+ group_id = group_id,
+ artifact_id = artifact_id,
+ packaging = packaging,
+ classifier = classifier,
+ version = version,
+ )
def _format_deps(attr, deps):
- formatted_deps = ""
- if deps:
- if len(deps) == 1:
- formatted_deps += "%s = [\'%s\']," % (attr, deps[0])
- else:
- formatted_deps += "%s = [\n" % attr
- for dep in deps:
- formatted_deps += " \'%s\',\n" % dep
- formatted_deps += " ],"
- return formatted_deps
+ formatted_deps = ""
+ if deps:
+ if len(deps) == 1:
+ formatted_deps += "%s = [\'%s\']," % (attr, deps[0])
+ else:
+ formatted_deps += "%s = [\n" % attr
+ for dep in deps:
+ formatted_deps += " \'%s\',\n" % dep
+ formatted_deps += " ],"
+ return formatted_deps
def _generate_build_files(ctx, binjar, srcjar):
- header = "# DO NOT EDIT: automatically generated BUILD file for maven_jar rule %s" % ctx.name
- srcjar_attr = ""
- if srcjar:
- srcjar_attr = 'srcjar = "%s",' % srcjar
- contents = """
+ header = "# DO NOT EDIT: automatically generated BUILD file for maven_jar rule %s" % ctx.name
+ srcjar_attr = ""
+ if srcjar:
+ srcjar_attr = 'srcjar = "%s",' % srcjar
+ contents = """
{header}
package(default_visibility = ['//visibility:public'])
java_import(
@@ -86,22 +87,24 @@
{deps}
{exports}
)
-\n""".format(srcjar_attr = srcjar_attr,
- header = header,
- binjar = binjar,
- deps = _format_deps("deps", ctx.attr.deps),
- exports = _format_deps("exports", ctx.attr.exports))
- if srcjar:
- contents += """
+\n""".format(
+ srcjar_attr = srcjar_attr,
+ header = header,
+ binjar = binjar,
+ deps = _format_deps("deps", ctx.attr.deps),
+ exports = _format_deps("exports", ctx.attr.exports),
+ )
+ if srcjar:
+ contents += """
java_import(
name = 'src',
jars = ['{srcjar}'],
)
""".format(srcjar = srcjar)
- ctx.file('%s/BUILD' % ctx.path("jar"), contents, False)
+ ctx.file("%s/BUILD" % ctx.path("jar"), contents, False)
- # Compatibility layer for java_import_external from rules_closure
- contents = """
+ # Compatibility layer for java_import_external from rules_closure
+ contents = """
{header}
package(default_visibility = ['//visibility:public'])
@@ -110,52 +113,53 @@
actual = "@{rule_name}//jar",
)
\n""".format(rule_name = ctx.name, header = header)
- ctx.file("BUILD", contents, False)
+ ctx.file("BUILD", contents, False)
def _maven_jar_impl(ctx):
- """rule to download a Maven archive."""
- coordinates = _create_coordinates(ctx.attr.artifact)
+ """rule to download a Maven archive."""
+ coordinates = _create_coordinates(ctx.attr.artifact)
- name = ctx.name
- sha1 = ctx.attr.sha1
+ name = ctx.name
+ sha1 = ctx.attr.sha1
- parts = ctx.attr.artifact.split(':')
- # TODO(davido): Only releases for now, implement handling snapshots
- jar, url = _maven_release(ctx, parts)
+ parts = ctx.attr.artifact.split(":")
- binjar = jar + '.jar'
- binjar_path = ctx.path('/'.join(['jar', binjar]))
- binurl = url + '.jar'
+ # TODO(davido): Only releases for now, implement handling snapshots
+ jar, url = _maven_release(ctx, parts)
- python = ctx.which("python")
- script = ctx.path(ctx.attr._download_script)
+ binjar = jar + ".jar"
+ binjar_path = ctx.path("/".join(["jar", binjar]))
+ binurl = url + ".jar"
- args = [python, script, "-o", binjar_path, "-u", binurl]
- if ctx.attr.sha1:
- args.extend(["-v", sha1])
- if ctx.attr.unsign:
- args.append('--unsign')
- for x in ctx.attr.exclude:
- args.extend(['-x', x])
+ python = ctx.which("python")
+ script = ctx.path(ctx.attr._download_script)
- out = ctx.execute(args)
+ args = [python, script, "-o", binjar_path, "-u", binurl]
+ if ctx.attr.sha1:
+ args.extend(["-v", sha1])
+ if ctx.attr.unsign:
+ args.append("--unsign")
+ for x in ctx.attr.exclude:
+ args.extend(["-x", x])
- if out.return_code:
- fail("failed %s: %s" % (' '.join(args), out.stderr))
-
- srcjar = None
- if ctx.attr.src_sha1 or ctx.attr.attach_source:
- srcjar = jar + '-src.jar'
- srcurl = url + '-sources.jar'
- srcjar_path = ctx.path('jar/' + srcjar)
- args = [python, script, "-o", srcjar_path, "-u", srcurl]
- if ctx.attr.src_sha1:
- args.extend(['-v', ctx.attr.src_sha1])
out = ctx.execute(args)
- if out.return_code:
- fail("failed %s: %s" % (args, out.stderr))
- _generate_build_files(ctx, binjar, srcjar)
+ if out.return_code:
+ fail("failed %s: %s" % (" ".join(args), out.stderr))
+
+ srcjar = None
+ if ctx.attr.src_sha1 or ctx.attr.attach_source:
+ srcjar = jar + "-src.jar"
+ srcurl = url + "-sources.jar"
+ srcjar_path = ctx.path("jar/" + srcjar)
+ args = [python, script, "-o", srcjar_path, "-u", srcurl]
+ if ctx.attr.src_sha1:
+ args.extend(["-v", ctx.attr.src_sha1])
+ out = ctx.execute(args)
+ if out.return_code:
+ fail("failed %s: %s" % (args, out.stderr))
+
+ _generate_build_files(ctx, binjar, srcjar)
maven_jar = repository_rule(
attrs = {
diff --git a/tools/bzl/pkg_war.bzl b/tools/bzl/pkg_war.bzl
index 46a4f9b..1a376e9 100644
--- a/tools/bzl/pkg_war.bzl
+++ b/tools/bzl/pkg_war.bzl
@@ -32,93 +32,93 @@
]
def _add_context(in_file, output):
- input_path = in_file.path
- return [
- 'unzip -qd %s %s' % (output, input_path)
- ]
+ input_path = in_file.path
+ return [
+ "unzip -qd %s %s" % (output, input_path),
+ ]
def _add_file(in_file, output):
- output_path = output
- input_path = in_file.path
- short_path = in_file.short_path
- n = in_file.basename
+ output_path = output
+ input_path = in_file.path
+ short_path = in_file.short_path
+ n = in_file.basename
- if short_path.startswith('gerrit-'):
- n = short_path.split('/')[0] + '-' + n
- elif short_path.startswith('java/'):
- n = short_path[5:].replace('/', '_')
- output_path += n
- return [
- 'test -L %s || ln -s $(pwd)/%s %s' % (output_path, input_path, output_path)
- ]
+ if short_path.startswith("gerrit-"):
+ n = short_path.split("/")[0] + "-" + n
+ elif short_path.startswith("java/"):
+ n = short_path[5:].replace("/", "_")
+ output_path += n
+ return [
+ "test -L %s || ln -s $(pwd)/%s %s" % (output_path, input_path, output_path),
+ ]
def _make_war(input_dir, output):
- return '(%s)' % ' && '.join([
- 'root=$(pwd)',
- 'TZ=UTC',
- 'export TZ',
- 'cd %s' % input_dir,
- "find . -exec touch -t 198001010000 '{}' ';' 2> /dev/null",
- 'zip -X -9qr ${root}/%s .' % (output.path),
- ])
+ return "(%s)" % " && ".join([
+ "root=$(pwd)",
+ "TZ=UTC",
+ "export TZ",
+ "cd %s" % input_dir,
+ "find . -exec touch -t 198001010000 '{}' ';' 2> /dev/null",
+ "zip -X -9qr ${root}/%s ." % (output.path),
+ ])
def _war_impl(ctx):
- war = ctx.outputs.war
- build_output = war.path + '.build_output'
- inputs = []
+ war = ctx.outputs.war
+ build_output = war.path + ".build_output"
+ inputs = []
- # Create war layout
- cmd = [
- 'set -e;rm -rf ' + build_output,
- 'mkdir -p ' + build_output,
- 'mkdir -p %s/WEB-INF/lib' % build_output,
- 'mkdir -p %s/WEB-INF/pgm-lib' % build_output,
- ]
+ # Create war layout
+ cmd = [
+ "set -e;rm -rf " + build_output,
+ "mkdir -p " + build_output,
+ "mkdir -p %s/WEB-INF/lib" % build_output,
+ "mkdir -p %s/WEB-INF/pgm-lib" % build_output,
+ ]
- # Add lib
- transitive_lib_deps = depset()
- for l in ctx.attr.libs:
- if hasattr(l, 'java'):
- transitive_lib_deps += l.java.transitive_runtime_deps
- elif hasattr(l, 'files'):
- transitive_lib_deps += l.files
+ # Add lib
+ transitive_lib_deps = depset()
+ for l in ctx.attr.libs:
+ if hasattr(l, "java"):
+ transitive_lib_deps += l.java.transitive_runtime_deps
+ elif hasattr(l, "files"):
+ transitive_lib_deps += l.files
- for dep in transitive_lib_deps:
- cmd += _add_file(dep, build_output + '/WEB-INF/lib/')
- inputs.append(dep)
+ for dep in transitive_lib_deps:
+ cmd += _add_file(dep, build_output + "/WEB-INF/lib/")
+ inputs.append(dep)
- # Add pgm lib
- transitive_pgmlib_deps = depset()
- for l in ctx.attr.pgmlibs:
- transitive_pgmlib_deps += l.java.transitive_runtime_deps
+ # Add pgm lib
+ transitive_pgmlib_deps = depset()
+ for l in ctx.attr.pgmlibs:
+ transitive_pgmlib_deps += l.java.transitive_runtime_deps
- for dep in transitive_pgmlib_deps:
- if dep not in inputs:
- cmd += _add_file(dep, build_output + '/WEB-INF/pgm-lib/')
- inputs.append(dep)
+ for dep in transitive_pgmlib_deps:
+ if dep not in inputs:
+ cmd += _add_file(dep, build_output + "/WEB-INF/pgm-lib/")
+ inputs.append(dep)
- # Add context
- transitive_context_deps = depset()
- if ctx.attr.context:
- for jar in ctx.attr.context:
- if hasattr(jar, 'java'):
- transitive_context_deps += jar.java.transitive_runtime_deps
- elif hasattr(jar, 'files'):
- transitive_context_deps += jar.files
- for dep in transitive_context_deps:
- cmd += _add_context(dep, build_output)
- inputs.append(dep)
+ # Add context
+ transitive_context_deps = depset()
+ if ctx.attr.context:
+ for jar in ctx.attr.context:
+ if hasattr(jar, "java"):
+ transitive_context_deps += jar.java.transitive_runtime_deps
+ elif hasattr(jar, "files"):
+ transitive_context_deps += jar.files
+ for dep in transitive_context_deps:
+ cmd += _add_context(dep, build_output)
+ inputs.append(dep)
- # Add zip war
- cmd.append(_make_war(build_output, war))
+ # Add zip war
+ cmd.append(_make_war(build_output, war))
- ctx.actions.run_shell(
- inputs = inputs,
- outputs = [war],
- mnemonic = 'WAR',
- command = '\n'.join(cmd),
- use_default_shell_env = True,
- )
+ ctx.actions.run_shell(
+ inputs = inputs,
+ outputs = [war],
+ mnemonic = "WAR",
+ command = "\n".join(cmd),
+ use_default_shell_env = True,
+ )
# context: go to the root directory
# libs: go to the WEB-INF/lib directory
@@ -133,25 +133,25 @@
implementation = _war_impl,
)
-def pkg_war(name, ui = 'ui_optdbg', context = [], doc = False, **kwargs):
- doc_ctx = []
- doc_lib = []
- ui_deps = []
- if ui == 'polygerrit' or ui == 'ui_optdbg' or ui == 'ui_optdbg_r':
- ui_deps.append('//polygerrit-ui/app:polygerrit_ui')
- if ui and ui != 'polygerrit':
- ui_deps.append('//gerrit-gwtui:%s' % ui)
- if doc:
- doc_ctx.append('//Documentation:html')
- doc_lib.append('//Documentation:index')
+def pkg_war(name, ui = "ui_optdbg", context = [], doc = False, **kwargs):
+ doc_ctx = []
+ doc_lib = []
+ ui_deps = []
+ if ui == "polygerrit" or ui == "ui_optdbg" or ui == "ui_optdbg_r":
+ ui_deps.append("//polygerrit-ui/app:polygerrit_ui")
+ if ui and ui != "polygerrit":
+ ui_deps.append("//gerrit-gwtui:%s" % ui)
+ if doc:
+ doc_ctx.append("//Documentation:html")
+ doc_lib.append("//Documentation:index")
- _pkg_war(
- name = name,
- libs = LIBS + doc_lib,
- pgmlibs = PGMLIBS,
- context = doc_ctx + context + ui_deps + [
- '//java:gerrit-main-class_deploy.jar',
- '//webapp:assets',
- ],
- **kwargs
- )
+ _pkg_war(
+ name = name,
+ libs = LIBS + doc_lib,
+ pgmlibs = PGMLIBS,
+ context = doc_ctx + context + ui_deps + [
+ "//java:gerrit-main-class_deploy.jar",
+ "//webapp:assets",
+ ],
+ **kwargs
+ )
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl
index 23f88df..5ae7dd9 100644
--- a/tools/bzl/plugin.bzl
+++ b/tools/bzl/plugin.bzl
@@ -1,11 +1,11 @@
load("//tools/bzl:genrule2.bzl", "genrule2")
load(
"//tools/bzl:gwt.bzl",
+ "GWT_COMPILER_ARGS",
+ "GWT_JVM_ARGS",
"GWT_PLUGIN_DEPS",
"GWT_PLUGIN_DEPS_NEVERLINK",
"GWT_TRANSITIVE_DEPS",
- "GWT_COMPILER_ARGS",
- "GWT_JVM_ARGS",
"gwt_binary",
)
@@ -21,82 +21,84 @@
]
def gerrit_plugin(
- name,
- deps = [],
- provided_deps = [],
- srcs = [],
- gwt_module = [],
- resources = [],
- manifest_entries = [],
- dir_name = None,
- target_suffix = "",
- **kwargs):
- native.java_library(
- name = name + '__plugin',
- srcs = srcs,
- resources = resources,
- deps = provided_deps + deps + GWT_PLUGIN_DEPS_NEVERLINK + PLUGIN_DEPS_NEVERLINK,
- visibility = ['//visibility:public'],
- **kwargs
- )
-
- static_jars = []
- if gwt_module:
- static_jars = [':%s-static' % name]
-
- if not dir_name:
- dir_name = name
-
- native.java_binary(
- name = '%s__non_stamped' % name,
- deploy_manifest_lines = manifest_entries + ["Gerrit-ApiType: plugin"],
- main_class = 'Dummy',
- runtime_deps = [
- ':%s__plugin' % name,
- ] + static_jars,
- visibility = ['//visibility:public'],
- **kwargs
- )
-
- if gwt_module:
+ name,
+ deps = [],
+ provided_deps = [],
+ srcs = [],
+ gwt_module = [],
+ resources = [],
+ manifest_entries = [],
+ dir_name = None,
+ target_suffix = "",
+ **kwargs):
native.java_library(
- name = name + '__gwt_module',
- resources = depset(srcs + resources).to_list(),
- runtime_deps = deps + GWT_PLUGIN_DEPS,
- visibility = ['//visibility:public'],
- **kwargs
- )
- genrule2(
- name = '%s-static' % name,
- cmd = ' && '.join([
- 'mkdir -p $$TMP/static',
- 'unzip -qd $$TMP/static $(location %s__gwt_application)' % name,
- 'cd $$TMP',
- 'zip -qr $$ROOT/$@ .']),
- tools = [':%s__gwt_application' % name],
- outs = ['%s-static.jar' % name],
- )
- gwt_binary(
- name = name + '__gwt_application',
- module = [gwt_module],
- deps = GWT_PLUGIN_DEPS + GWT_TRANSITIVE_DEPS + ['//lib/gwt:dev'],
- module_deps = [':%s__gwt_module' % name],
- compiler_args = GWT_COMPILER_ARGS,
- jvm_args = GWT_JVM_ARGS,
+ name = name + "__plugin",
+ srcs = srcs,
+ resources = resources,
+ deps = provided_deps + deps + GWT_PLUGIN_DEPS_NEVERLINK + PLUGIN_DEPS_NEVERLINK,
+ visibility = ["//visibility:public"],
+ **kwargs
)
- # TODO(davido): Remove manual merge of manifest file when this feature
- # request is implemented: https://github.com/bazelbuild/bazel/issues/2009
- genrule2(
- name = name + target_suffix,
- stamp = 1,
- srcs = ['%s__non_stamped_deploy.jar' % name],
- cmd = " && ".join([
- "GEN_VERSION=$$(cat bazel-out/stable-status.txt | grep -w STABLE_BUILD_%s_LABEL | cut -d ' ' -f 2)" % dir_name.upper(),
- "cd $$TMP",
- "unzip -q $$ROOT/$<",
- "echo \"Implementation-Version: $$GEN_VERSION\n$$(cat META-INF/MANIFEST.MF)\" > META-INF/MANIFEST.MF",
- "zip -qr $$ROOT/$@ ."]),
- outs = ['%s%s.jar' % (name, target_suffix)],
- visibility = ['//visibility:public'],
- )
+ static_jars = []
+ if gwt_module:
+ static_jars = [":%s-static" % name]
+
+ if not dir_name:
+ dir_name = name
+
+ native.java_binary(
+ name = "%s__non_stamped" % name,
+ deploy_manifest_lines = manifest_entries + ["Gerrit-ApiType: plugin"],
+ main_class = "Dummy",
+ runtime_deps = [
+ ":%s__plugin" % name,
+ ] + static_jars,
+ visibility = ["//visibility:public"],
+ **kwargs
+ )
+
+ if gwt_module:
+ native.java_library(
+ name = name + "__gwt_module",
+ resources = depset(srcs + resources).to_list(),
+ runtime_deps = deps + GWT_PLUGIN_DEPS,
+ visibility = ["//visibility:public"],
+ **kwargs
+ )
+ genrule2(
+ name = "%s-static" % name,
+ cmd = " && ".join([
+ "mkdir -p $$TMP/static",
+ "unzip -qd $$TMP/static $(location %s__gwt_application)" % name,
+ "cd $$TMP",
+ "zip -qr $$ROOT/$@ .",
+ ]),
+ tools = [":%s__gwt_application" % name],
+ outs = ["%s-static.jar" % name],
+ )
+ gwt_binary(
+ name = name + "__gwt_application",
+ module = [gwt_module],
+ deps = GWT_PLUGIN_DEPS + GWT_TRANSITIVE_DEPS + ["//lib/gwt:dev"],
+ module_deps = [":%s__gwt_module" % name],
+ compiler_args = GWT_COMPILER_ARGS,
+ jvm_args = GWT_JVM_ARGS,
+ )
+
+ # TODO(davido): Remove manual merge of manifest file when this feature
+ # request is implemented: https://github.com/bazelbuild/bazel/issues/2009
+ genrule2(
+ name = name + target_suffix,
+ stamp = 1,
+ srcs = ["%s__non_stamped_deploy.jar" % name],
+ cmd = " && ".join([
+ "GEN_VERSION=$$(cat bazel-out/stable-status.txt | grep -w STABLE_BUILD_%s_LABEL | cut -d ' ' -f 2)" % dir_name.upper(),
+ "cd $$TMP",
+ "unzip -q $$ROOT/$<",
+ "echo \"Implementation-Version: $$GEN_VERSION\n$$(cat META-INF/MANIFEST.MF)\" > META-INF/MANIFEST.MF",
+ "zip -qr $$ROOT/$@ .",
+ ]),
+ outs = ["%s%s.jar" % (name, target_suffix)],
+ visibility = ["//visibility:public"],
+ )
diff --git a/tools/js/npm_pack.py b/tools/js/npm_pack.py
index d817701..f14262a 100755
--- a/tools/js/npm_pack.py
+++ b/tools/js/npm_pack.py
@@ -15,8 +15,8 @@
"""This downloads an NPM binary, and bundles it with its dependencies.
-This is used to assemble a pinned version of crisper, hosted on the
-Google storage bucket ("repository=GERRIT" in WORKSPACE).
+For full instructions on adding new binaries to the build, see
+http://gerrit-review.googlesource.com/Documentation/dev-bazel.html#npm-binary
"""
from __future__ import print_function
diff --git a/tools/maven/package.bzl b/tools/maven/package.bzl
index 3c32bb2..5b497f8 100644
--- a/tools/maven/package.bzl
+++ b/tools/maven/package.bzl
@@ -25,73 +25,86 @@
]))
def maven_package(
- version,
- repository = None,
- url = None,
- jar = {},
- src = {},
- doc = {},
- war = {}):
+ version,
+ repository = None,
+ url = None,
+ jar = {},
+ src = {},
+ doc = {},
+ war = {}):
+ build_cmd = ["bazel", "build"]
+ mvn_cmd = ["python", "tools/maven/mvn.py", "-v", version]
+ api_cmd = mvn_cmd[:]
+ api_targets = []
+ for type, d in [("jar", jar), ("java-source", src), ("javadoc", doc)]:
+ for a, t in sorted(d.items()):
+ api_cmd.append("-s %s:%s:$(location %s)" % (a, type, t))
+ api_targets.append(t)
- build_cmd = ['bazel', 'build']
- mvn_cmd = ['python', 'tools/maven/mvn.py', '-v', version]
- api_cmd = mvn_cmd[:]
- api_targets = []
- for type,d in [('jar', jar), ('java-source', src), ('javadoc', doc)]:
- for a,t in sorted(d.items()):
- api_cmd.append('-s %s:%s:$(location %s)' % (a,type,t))
- api_targets.append(t)
-
- native.genrule(
- name = 'gen_api_install',
- cmd = sh_bang_template % (
- ' '.join(build_cmd + api_targets),
- ' '.join(api_cmd + ['-a', 'install'])),
- srcs = api_targets,
- outs = ['api_install.sh'],
- executable = True,
- testonly = 1,
- )
-
- if repository and url:
native.genrule(
- name = 'gen_api_deploy',
- cmd = sh_bang_template % (
- ' '.join(build_cmd + api_targets),
- ' '.join(api_cmd + ['-a', 'deploy',
- '--repository', repository,
- '--url', url])),
- srcs = api_targets,
- outs = ['api_deploy.sh'],
- executable = True,
- testonly = 1,
+ name = "gen_api_install",
+ cmd = sh_bang_template % (
+ " ".join(build_cmd + api_targets),
+ " ".join(api_cmd + ["-a", "install"]),
+ ),
+ srcs = api_targets,
+ outs = ["api_install.sh"],
+ executable = True,
+ testonly = 1,
)
- war_cmd = mvn_cmd[:]
- war_targets = []
- for a,t in sorted(war.items()):
- war_cmd.append('-s %s:war:$(location %s)' % (a,t))
- war_targets.append(t)
+ if repository and url:
+ native.genrule(
+ name = "gen_api_deploy",
+ cmd = sh_bang_template % (
+ " ".join(build_cmd + api_targets),
+ " ".join(api_cmd + [
+ "-a",
+ "deploy",
+ "--repository",
+ repository,
+ "--url",
+ url,
+ ]),
+ ),
+ srcs = api_targets,
+ outs = ["api_deploy.sh"],
+ executable = True,
+ testonly = 1,
+ )
- native.genrule(
- name = 'gen_war_install',
- cmd = sh_bang_template % (' '.join(build_cmd + war_targets),
- ' '.join(war_cmd + ['-a', 'install'])),
- srcs = war_targets,
- outs = ['war_install.sh'],
- executable = True,
- )
+ war_cmd = mvn_cmd[:]
+ war_targets = []
+ for a, t in sorted(war.items()):
+ war_cmd.append("-s %s:war:$(location %s)" % (a, t))
+ war_targets.append(t)
- if repository and url:
native.genrule(
- name = 'gen_war_deploy',
- cmd = sh_bang_template % (
- ' '.join(build_cmd + war_targets),
- ' '.join(war_cmd + [
- '-a', 'deploy',
- '--repository', repository,
- '--url', url])),
- srcs = war_targets,
- outs = ['war_deploy.sh'],
- executable = True,
+ name = "gen_war_install",
+ cmd = sh_bang_template % (
+ " ".join(build_cmd + war_targets),
+ " ".join(war_cmd + ["-a", "install"]),
+ ),
+ srcs = war_targets,
+ outs = ["war_install.sh"],
+ executable = True,
)
+
+ if repository and url:
+ native.genrule(
+ name = "gen_war_deploy",
+ cmd = sh_bang_template % (
+ " ".join(build_cmd + war_targets),
+ " ".join(war_cmd + [
+ "-a",
+ "deploy",
+ "--repository",
+ repository,
+ "--url",
+ url,
+ ]),
+ ),
+ srcs = war_targets,
+ outs = ["war_deploy.sh"],
+ executable = True,
+ )