Merge branch 'stable-3.0'
* stable-3.0: Update git submodules Update git submodules Update git submodules Fix documentation of UI selection Set version to 2.16.12-SNAPSHOT Set version to 2.16.11 Update git submodules Revert "GerritServer: Silence non-critical logs from JGit's FileSnapshot" Revert "GerritServer: Silence non-critical logs from JGit's FS" Revert "Upgrade JGit to 5.1.10.201908230655-r" Revert "Stop using deprecated DirCacheEntry#setLastModified(long)" Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Update git submodules Set version to 2.15.17-SNAPSHOT Update git submodules Update git submodules Revert "Upgrade JGit to 5.3.4.201908231101-r" Set version to 2.15.16 Revert "CreateAccount: Fail early when invalid SSH key is given" Update git submodules tools/eclipse/project.py: Fix typo of bazelisk Set XSRF on '/' under PolyGerrit Migrate from old-style legacy .java provider to the new JavaInfo. Remove deleted rules for the new added section Support bazelisk or bazel in tools/eclipse/project.py Rework imports in project.py Update project.py to use argparse AccountIT: Test that account is not created with invalid email CreateAccount: Fail early when invalid SSH key is given Update git submodules GerritServer: Silence non-critical logs from JGit's FS GerritServer: Silence non-critical logs from JGit's FileSnapshot Stop using deprecated DirCacheEntry#setLastModified(long) ProjectState: Fix 'invalid type qualification' javadoc warning Upgrade JGit to 5.3.4.201908231101-r Documentation: refresh IntelliJ IDEA developer documentation Documentation: update external links to Bazel Use base url for commentlink Update git submodules Update git submodules Don't store LabelTypes in ProjectState Upgrade highlight.js to latest master revision Update git submodules Update git submodules Update git submodules StarredChangesUtil: Stop using deprecated RefDatabase.getRef Suppress warnings about deprecated BaseReceivePack DeleteRef: Stop using deprecated RefDatabase.getRef Upgrade elasticsearch-rest-client to 7.3.1 Add .gitreview file Remove vestigal GWT plugin loading hooks Upgrade JGit to 5.1.10.201908230655-r DeleteDraftComments: Don't update change modified timestamp ChangeIT: set submittableAfterLosingPermissions private Rebase: Don't swallow caught exception Output NoteDb migration progress to Flogger Update git submodules Remove AccountPatchReview data when change gets auto-abandoned DefaultChangeReportFormatter: Make constructor and urlFormatter visible StarredChangesUtil: Fix NPE when ref to be deleted doesn't exist StarredChangesUtil: Throw LockFailureException on LOCK_FAILURE Add test for creating a change on a non-existing base change Rebase: Do not fail with 500 ISE if non-existing change is given as base Fix detecting changes of parent trees when computing change kind for merge commit Remove duplicate descriptions of fields in Requirement JSON entity Allow to set content type in the plugin REST API interface InternalAccountQuery: Add back the oneByExternalId method Set version to 2.16.11-SNAPSHOT Revert "Migrate from old-style legacy .java provider to the new JavaInfo." Catch all exceptions for reporting on Schema_130 migration Update git submodules Migrate from old-style legacy .java provider to the new JavaInfo. Update git submodules Update git submodules AuthRequest: Fix Javadoc for return values ChangeApi: Add methods to get change comments/drafts as list Update git submodules ListChangeComments: Extend ListChangeDrafts Upgrade Go Bazel rules to the latest version detach -> detached Fix anchor tag for settings page Add support for Elasticsearch version 7.3.* PrologEnvironment: Reduce "setting reductionLimit" log spam ElasticContainer: Upgrade to 6.8.2 image for V6_8 tests Fix typo: program Fix email token routing Clarify usage of 'parent' option in list files API Remove unused Skylark patch file Files: Use Gerrit API to get revision parents Fix broken link for rest-api-projects.html#commentlink-info Add support for Elasticsearch version 6.8.x Upgrade elasticsearch-rest-client to 7.2.1 Add support for "Link Another Identity" in gr-identities Update git submodules CommitApi: Add method to get commit info Consolidate all CommitApi tests into a single class Files: Validate parent option to prevent internal server error RevisionIT: Assert that files(base) only works for patch set revisions Fix and expand documentation of REST API to get revision files RevisionIT#files: Simplify assertion Update git submodules Update git submodules Update git submodules Update git submodules Remove default bug tracker from _feedbackUrl PG: Add shortcuts for dashboard and watched changes PG: Allow empty label values Remove token param from getCapabilities Add an extension point to show a small banner next to the search bar Fix gr-group-audit-log to use tbody Change-Id: Iaf877b737f115d4fe95af74f8284eec19112a21d
This commit is contained in:
commit
923318b446
@ -1,6 +1,6 @@
|
||||
# The project view file (.bazelproject) is used to import Gerrit Bazel packages into the IDE.
|
||||
#
|
||||
# See: https://ij.bazel.io/docs/project-views.html
|
||||
# See: https://ij.bazel.build/docs/project-views.html
|
||||
|
||||
directories:
|
||||
.
|
||||
|
5
.gitreview
Normal file
5
.gitreview
Normal file
@ -0,0 +1,5 @@
|
||||
[gerrit]
|
||||
host=gerrit-review.googlesource.com
|
||||
scheme=https
|
||||
project=gerrit.git
|
||||
defaultbranch=master
|
@ -1389,6 +1389,13 @@ Whether changes which are mergeable should be auto-abandoned.
|
||||
+
|
||||
By default `true`.
|
||||
|
||||
[[changeCleanup.cleanupAccountPatchReview]]changeCleanup.cleanupAccountPatchReview::
|
||||
+
|
||||
Whether accountPatchReview data should be also removed when change
|
||||
gets auto-abandoned.
|
||||
+
|
||||
By default `false`.
|
||||
|
||||
[[changeCleanup.abandonMessage]]changeCleanup.abandonMessage::
|
||||
+
|
||||
Change message that should be posted when a change is abandoned.
|
||||
|
@ -10,7 +10,7 @@ To build Gerrit from source, you need:
|
||||
* Python 2 or 3
|
||||
* link:https://github.com/nodesource/distributions/blob/master/README.md[Node.js (including npm)]
|
||||
* Bower (`sudo npm install -g bower`)
|
||||
* link:https://www.bazel.io/versions/master/docs/install.html[Bazel]
|
||||
* link:https://docs.bazel.build/versions/master/install.html[Bazel]
|
||||
* Maven
|
||||
* zip, unzip
|
||||
* gcc
|
||||
@ -225,7 +225,7 @@ is not regenerated.
|
||||
|
||||
=== IntelliJ
|
||||
|
||||
The Gerrit build works with Bazel's link:https://ij.bazel.io[IntelliJ plugin].
|
||||
The Gerrit build works with Bazel's link:https://ij.bazel.build[IntelliJ plugin].
|
||||
Please follow the instructions on <<dev-intellij#,IntelliJ Setup>>.
|
||||
|
||||
=== Eclipse
|
||||
@ -245,7 +245,7 @@ and then follow the link:dev-eclipse.html#setup[setup instructions].
|
||||
If an updated classpath is needed, the Eclipse project can be
|
||||
refreshed and missing dependency JARs can be downloaded by running
|
||||
`project.py` again. For IntelliJ, you need to click the `Sync Project
|
||||
with BUILD Files` button of link:https://ij.bazel.io[IntelliJ plugin].
|
||||
with BUILD Files` button of link:https://ij.bazel.build[Bazel plugin].
|
||||
|
||||
[[documentation]]
|
||||
=== Documentation
|
||||
|
@ -88,6 +88,11 @@ by clicking the 'Obtain Password' link on the
|
||||
link:https://gerrit-review.googlesource.com/#/settings/http-password[HTTP
|
||||
Password tab of the user settings page].
|
||||
|
||||
Alternately, you may use the
|
||||
link:https://pypi.org/project/git-review/[git-review] tool to submit changes
|
||||
to Gerrit. If you do, it will set up the Change-Id hook and `gerrit` remote
|
||||
for you. You will still need to do the HTTP access step.
|
||||
|
||||
[[style]]
|
||||
== Style
|
||||
|
||||
|
@ -1,10 +1,24 @@
|
||||
= Gerrit Code Review - IntelliJ Setup
|
||||
= Gerrit Code Review - IntelliJ IDEA Setup
|
||||
|
||||
== Prerequisites
|
||||
You need an installation of IntelliJ version 2016.2 or later. The latest version
|
||||
might not yet be in-sync with the Bazel plugin for IntelliJ. It usually becomes
|
||||
so quite quickly after new IDEA versions get released, though. It should then be
|
||||
possible to use the fairly latest IntelliJ release with an updated Bazel plugin.
|
||||
|
||||
=== Bazel
|
||||
|
||||
Bazel must be installed as described by
|
||||
<<dev-bazel#installation,Building with Bazel - Installation>>.
|
||||
|
||||
It's strongly recommended to verify you can build your Gerrit tree with Bazel
|
||||
for Java 8 from the command line first. Ensure that at least
|
||||
`bazel build gerrit` runs successfully before you proceed.
|
||||
|
||||
=== IntelliJ version and Bazel plugin
|
||||
|
||||
Before downloading IntelliJ, look at the
|
||||
link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[JetBrains plugin repository page of the Bazel plugin]
|
||||
to see what version of the IntelliJ IDEA it is actually compatible with.
|
||||
|
||||
Also note that the version of the Bazel plugin used in turn may or may not be
|
||||
compatible with the Bazel version used.
|
||||
|
||||
In addition, Java 8 must be specified on your path or via `JAVA_HOME` so that
|
||||
building with Bazel via the Bazel plugin is possible.
|
||||
@ -13,46 +27,64 @@ TIP: If the synchronization of the project with the BUILD files using the Bazel
|
||||
plugin fails and IntelliJ reports the error **Could not get Bazel roots**, this
|
||||
indicates that the Bazel plugin couldn't find Java 8.
|
||||
|
||||
Bazel must be installed as described by
|
||||
<<dev-bazel#installation,Building with Bazel - Installation>>.
|
||||
=== Installation of IntelliJ IDEA
|
||||
|
||||
Please refer to the
|
||||
link:https://www.jetbrains.com/help/idea/installation-guide.html[installation guide provided by Jetbrains]
|
||||
to install it on your platform. Make sure to install a version compatible with
|
||||
the Bazel plugin as mentioned above.
|
||||
|
||||
== Installation of the Bazel plugin
|
||||
|
||||
The plugin is usually installed using the Jetbrains plugin repository as shown
|
||||
in the steps below, but it's also possible to
|
||||
link:https://github.com/bazelbuild/intellij[build it from source].
|
||||
|
||||
. Go to *File -> Settings -> Plugins*.
|
||||
. Click on *Browse Repositories*.
|
||||
. Search for the plugin `IntelliJ with Bazel`.
|
||||
+
|
||||
(Or, from the welcome screen, *Configure -> Plugins*)
|
||||
. Activate the *Marketplace* tab.
|
||||
. Search for the plugin `Bazel` (by Google).
|
||||
+
|
||||
TIP: In case the Bazel plugin is not listed, or if it shows an outdated version,
|
||||
verify the compatibility between the Bazel plugin and IntelliJ IDEA on link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[the JetBrains plugin page].
|
||||
. Install it.
|
||||
. Restart IntelliJ.
|
||||
. Restart IntelliJ IDEA.
|
||||
|
||||
TIP: If your project's Bazel build fails with **Cannot run program "bazel": No
|
||||
such file or directory**, then you may have to set the binary location in the
|
||||
Bazel plugin settings:
|
||||
[TIP]
|
||||
====
|
||||
If your project's Bazel build fails with **Cannot run program "bazel": No such
|
||||
file or directory**, then you may have to set the binary location in the Bazel
|
||||
plugin settings:
|
||||
|
||||
. Go to Preferences -> Other Settings -> Bazel Settings.
|
||||
. Set the Bazel binary location.
|
||||
. Go to *Preferences -> Other Settings -> Bazel Settings*.
|
||||
. Set the *Bazel binary location*.
|
||||
====
|
||||
|
||||
== Creation of IntelliJ project
|
||||
== Creation of the project
|
||||
|
||||
. Go to *File -> Import Bazel Project*.
|
||||
+
|
||||
(Or, from the welcome screen, *Import Bazel Project* should already be shown in
|
||||
there.)
|
||||
. For *Use existing bazel workspace -> Workspace*, select the directory
|
||||
containing the Gerrit source code.
|
||||
. Choose *Import from workspace* and select the `.bazelproject` file which is
|
||||
located in the top directory of the Gerrit source code.
|
||||
. Adjust the path of the project data directory and the name of the project if
|
||||
desired.
|
||||
. Finish the creation of the project.
|
||||
. Verify that you can now build the project. Hit the button with the Bazel icon
|
||||
(located on the top-right by default) to synchronize the project. Note that
|
||||
warnings may be present in the build.
|
||||
|
||||
At this point all the basic functionality should be working such as Java class
|
||||
inspection and running <<unit-tests,unit tests>>.
|
||||
|
||||
TIP: The project data directory can be separate from the source code. One
|
||||
advantage of this is that project files don't need to be excluded from version
|
||||
control.
|
||||
|
||||
Unfortunately, the created project seems to have a broken output path. To fix
|
||||
it, please complete the following steps:
|
||||
|
||||
. Go to *File -> Project Structure -> Project Settings -> Modules*.
|
||||
. Switch to the tab *Paths*.
|
||||
. Click on *Inherit project compile output path*.
|
||||
. Click on *Use module compile output path*.
|
||||
|
||||
== Recommended settings
|
||||
|
||||
=== Code style
|
||||
@ -61,17 +93,20 @@ it, please complete the following steps:
|
||||
Install the `google-java-format` plugin by following these steps:
|
||||
|
||||
. Go to *File -> Settings -> Plugins*.
|
||||
. Click on *Browse Repositories*.
|
||||
. Search for the plugin `google-java-format`.
|
||||
. Activate the *Marketplace* tab.
|
||||
. Search for the plugin `google-java-format` by Google.
|
||||
. Install it.
|
||||
. Restart IntelliJ.
|
||||
. Restart IntelliJ IDEA.
|
||||
|
||||
Every time you start IntelliJ, make sure to use *Code -> Reformat with
|
||||
Every time you start IntelliJ IDEA, make sure to use *Code -> Reformat with
|
||||
google-java-format* on an arbitrary line of code. This replaces the default
|
||||
CodeStyleManager with a custom one. Thus, uses of *Reformat Code* either via
|
||||
*Code -> Reformat Code*, keyboard shortcuts, or the commit dialog will use the
|
||||
custom style defined by the `google-java-format` plugin.
|
||||
|
||||
Please refer to the documentation on the <<dev-contributing#style,code style>>
|
||||
for which version of `google-java-format` is used with Gerrit.
|
||||
|
||||
==== Code style settings
|
||||
The `google-java-format` plugin is the preferred way to format the code. As it
|
||||
only kicks in on demand, it's also recommended to have code style settings
|
||||
@ -84,11 +119,10 @@ to be as close as possible. So before submitting code, please make sure to run
|
||||
https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml[
|
||||
intellij-java-google-style.xml].
|
||||
. Go to *File -> Settings -> Editor -> Code Style*.
|
||||
. Click on *Manage*.
|
||||
. Click on *Import*.
|
||||
. Choose `IntelliJ IDEA Code Style XML`.
|
||||
. Click on the wrench icon with the tooltip _Show Scheme Actions_.
|
||||
. Click on *Import Scheme*.
|
||||
. Select the previously downloaded file `intellij-java-google-style.xml`.
|
||||
. Make sure that `Google Style` is chosen as *Scheme*.
|
||||
. Make sure that `GoogleStyle` is chosen as the current *Scheme*.
|
||||
|
||||
In addition, the EditorConfig settings (which ensure a consistent style between
|
||||
Eclipse, IntelliJ, and other editors) should be applied on top of that. Those
|
||||
@ -97,7 +131,7 @@ will automatically pick up those settings if the EditorConfig plugin is enabled
|
||||
and configured correctly as can be verified by:
|
||||
|
||||
. Go to *File -> Settings -> Plugins*.
|
||||
. Ensure that the EditorConfig plugin is enabled.
|
||||
. Ensure that the *EditorConfig* plugin (by JetBrains) is enabled.
|
||||
. Go to *File -> Settings -> Editor -> Code Style*.
|
||||
. Ensure that *Enable EditorConfig support* is checked.
|
||||
|
||||
@ -105,35 +139,42 @@ NOTE: If IntelliJ notifies you later on that the EditorConfig settings override
|
||||
the code style settings, simply confirm that.
|
||||
|
||||
=== Copyright
|
||||
Copy the folder `$(gerrit_source_code)/tools/intellij/copyright` (not just the
|
||||
|
||||
. Copy the folder `$(gerrit_source_code)/tools/intellij/copyright` (not just the
|
||||
contents) to `$(project_data_directory)/.idea`. If it already exists, replace
|
||||
it. Then go to *File -> Settings -> Editor -> Copyright -> Copyright Profiles*,
|
||||
and import `Gerrit_Copyright.xml` to IntelliJ in case it doesn't pick the
|
||||
copyright up automatically.
|
||||
it. If you didn't select a custom data directory the command could look like
|
||||
this, as run from the Gerrit source tree checkout as working directory:
|
||||
+
|
||||
----
|
||||
cp -r tools/intellij/copyright .ijwb/.idea/
|
||||
----
|
||||
. Go to *File -> Settings -> Editor -> Copyright -> Copyright Profiles*.
|
||||
. Verify that the *Gerrit Copyright* is now present there.
|
||||
+
|
||||
Only in case it hasn't picked up the copyright profile automatically, import
|
||||
the `Gerrit_Copyright.xml` from that folder manually.
|
||||
|
||||
=== File header
|
||||
By default, IntelliJ adds a file header containing the name of the author and
|
||||
the current date to new files. To disable that, follow these steps:
|
||||
=== Git integration
|
||||
This section is only relevant in case you want to use the Git integration
|
||||
plugin in IntelliJ IDEA.
|
||||
|
||||
. Go to *File -> Settings -> Editor -> File and Code Templates*.
|
||||
. Select the tab *Includes*.
|
||||
. Select *File Header*.
|
||||
. Remove the template code in the right editor.
|
||||
|
||||
=== Commit message
|
||||
To simplify the creation of commit messages which are compliant with the
|
||||
<<dev-contributing#commit-message,Commit Message>> format, do the following:
|
||||
|
||||
. Go to *File -> Settings -> Version Control*.
|
||||
. Check *Commit message right margin (columns)*.
|
||||
. Make sure that 72 is specified as value.
|
||||
. Check *Wrap when typing reaches right margin*.
|
||||
. Go to *File -> Settings -> Version Control -> Commit Dialog*.
|
||||
. In the *Commit message inspections*, activate the three inspections:
|
||||
* *Blank line between subject and body*,
|
||||
* *Limit body line* and
|
||||
* *Limit subject line*.
|
||||
. For the limit line inspections, make sure that 72 is specified as value.
|
||||
. For *Limit body line*, tick *Show right margin* and *Wrap when typing reaches
|
||||
right margin*.
|
||||
|
||||
In addition, you should follow the instructions of
|
||||
<<dev-contributing#git_commit_settings,this section>> (if you haven't
|
||||
done so already):
|
||||
|
||||
* Install the Git hook for the `Change-Id` line.
|
||||
* Install the Git commit message hook for the `Change-Id` line.
|
||||
* Set up the HTTP access.
|
||||
|
||||
Setting up the HTTP access will allow you to commit changes via IntelliJ without
|
||||
@ -145,29 +186,18 @@ Run configurations can be accessed on the toolbar. To edit them or add new ones,
|
||||
choose *Edit Configurations* on the drop-down list of the run configurations
|
||||
or go to *Run -> Edit Configurations*.
|
||||
|
||||
=== Pre-configured run configurations
|
||||
|
||||
In order to be able to use the pre-configured run configurations, the following
|
||||
steps are necessary:
|
||||
|
||||
. Make sure that the folder `runConfigurations` exists within
|
||||
`$(project_data_directory)/.idea`. If it doesn't exist, create it.
|
||||
. Specify the IntelliJ path variable `GERRIT_TESTSITE`. (This configuration is
|
||||
shared among all IntelliJ projects.)
|
||||
.. Go to *Settings -> Appearance & Behavior -> Path Variables*.
|
||||
.. Click on the *+* to add a new path variable.
|
||||
.. Specify `GERRIT_TESTSITE` as name and the path to your local test site as
|
||||
value.
|
||||
|
||||
The copied run configurations will be added automatically to the available run
|
||||
configurations of the IntelliJ project.
|
||||
|
||||
[[runconfigurations-daemon]]
|
||||
==== Gerrit Daemon
|
||||
WARNING: At the moment running this configuration results in a
|
||||
[WARNING]
|
||||
====
|
||||
At the moment running this (local) configuration results in a
|
||||
`java.io.FileNotFoundException`. To debug a local Gerrit server with IntelliJ,
|
||||
use the instructions of <<dev-readme#run_daemon,Running the Daemon>> in
|
||||
combination with <<remote-debug,Debugging a remote Gerrit server>>.
|
||||
|
||||
(link:https://bugs.chromium.org/p/gerrit/issues/detail?id=11360[Issue 11360])
|
||||
====
|
||||
|
||||
Copy `$(gerrit_source_code)/tools/intellij/gerrit_daemon.xml` to
|
||||
`$(project_data_directory)/.idea/runConfigurations/`.
|
||||
|
||||
@ -177,10 +207,12 @@ This run configuration starts the Gerrit daemon similarly as
|
||||
NOTE: The <<dev-readme#init,Site Initialization>> has to be completed
|
||||
before this run configuration works properly.
|
||||
|
||||
[[unit-tests]]
|
||||
=== Unit tests
|
||||
To create run configurations for unit tests, run or debug them via a right-click
|
||||
on a method, class, file, or package. The created run configuration is a
|
||||
temporary one and can be saved to make it permanent.
|
||||
temporary one and can be saved to make it permanent by selecting *Create
|
||||
'Bazel test [...]'...* from the context menu.
|
||||
|
||||
Normally, this approach generates JUnit run configurations. When the Bazel
|
||||
plugin manages a project, it intercepts the creation and creates a Bazel test
|
||||
@ -193,10 +225,15 @@ IntelliJ via a `Remote debug configuration`.
|
||||
|
||||
. Go to *Run -> Edit Configurations*.
|
||||
. Click on the *+* to add a new configuration.
|
||||
. Choose *Remote*.
|
||||
. Choose *Remote* from the *Templates*.
|
||||
. Adjust *Configuration -> Settings -> Host* and *Port*.
|
||||
. Start this configuration in `Debug` mode.
|
||||
|
||||
TIP: This run configuration dialog also shows the line for the JVM as startup
|
||||
flag that you can copy to include in your
|
||||
`$(gerrit_test_site)/etc/gerrit.config` in the `[container]` section in order
|
||||
to work-around the <<runconfigurations-daemon,local run configuration issue>>.
|
||||
|
||||
GERRIT
|
||||
------
|
||||
Part of link:index.html[Gerrit Code Review]
|
||||
|
@ -251,7 +251,10 @@ link:https://gerrit-review.googlesource.com/admin/repos/gerrit,branches[
|
||||
Gerrit Web UI] or by push.
|
||||
|
||||
* Push the commits done on `stable-$version` to `refs/for/stable-$version` and
|
||||
get them merged
|
||||
get them merged.
|
||||
|
||||
* Create a change updating the `defaultbranch` field in the `.gitreview`
|
||||
to match the branch name created.
|
||||
|
||||
|
||||
[[push-tag]]
|
||||
|
@ -4934,12 +4934,22 @@ need the FileInfo should make two requests.
|
||||
The request parameter `q` changes the response to return a list
|
||||
of all files (modified or unmodified) that contain that substring
|
||||
in the path name. This is useful to implement suggestion services
|
||||
finding a file by partial name.
|
||||
finding a file by partial name. Clients that also need the FileInfo
|
||||
should make two requests.
|
||||
|
||||
The integer-valued request parameter `parent` changes the response to return a
|
||||
list of the files which are different in this commit compared to the given
|
||||
parent commit. This is useful for supporting review of merge commits. The value
|
||||
is the 1-based index of the parent's position in the commit object.
|
||||
For merge commits only, the integer-valued request parameter `parent`
|
||||
changes the response to return a map of the files which are different
|
||||
in this commit compared to the given parent commit. The value is the
|
||||
1-based index of the parent's position in the commit object. If not
|
||||
specified, the response contains a map of the files different in the
|
||||
auto merge result.
|
||||
|
||||
The request parameter `base` changes the response to return a map of the
|
||||
files which are different in this commit compared to the given revision. The
|
||||
revision must correspond to a patch set in the change.
|
||||
|
||||
The `reviewed`, `q`, `parent`, and `base` options are mutually exclusive.
|
||||
That is, only one of them may be used at a time.
|
||||
|
||||
.Request
|
||||
----
|
||||
|
@ -1062,8 +1062,8 @@ maven_jar(
|
||||
# and httpasyncclient as necessary.
|
||||
maven_jar(
|
||||
name = "elasticsearch-rest-client",
|
||||
artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.2.0",
|
||||
sha1 = "39cf34068b0af284eaa9b8bd86a131cb24b322d5",
|
||||
artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.3.1",
|
||||
sha1 = "f5793c89b50a159cbb3e15e17bb981ff854cbe51",
|
||||
)
|
||||
|
||||
maven_jar(
|
||||
|
@ -32,6 +32,7 @@ public @interface UsedAt {
|
||||
/** Enumeration of projects that call a method/type/field. */
|
||||
enum Project {
|
||||
GOOGLE,
|
||||
COLLABNET,
|
||||
PLUGIN_CHECKS,
|
||||
PLUGIN_DELETE_PROJECT,
|
||||
PLUGIN_SERVICEUSER,
|
||||
|
@ -25,9 +25,11 @@ public enum ElasticVersion {
|
||||
V6_5("6.5.*"),
|
||||
V6_6("6.6.*"),
|
||||
V6_7("6.7.*"),
|
||||
V6_8("6.8.*"),
|
||||
V7_0("7.0.*"),
|
||||
V7_1("7.1.*"),
|
||||
V7_2("7.2.*");
|
||||
V7_2("7.2.*"),
|
||||
V7_3("7.3.*");
|
||||
|
||||
private final String version;
|
||||
private final Pattern pattern;
|
||||
|
@ -335,6 +335,15 @@ public interface ChangeApi {
|
||||
*/
|
||||
Map<String, List<CommentInfo>> comments() throws RestApiException;
|
||||
|
||||
/**
|
||||
* Get all published comments on a change as a list.
|
||||
*
|
||||
* @return comments as a list; comments have the {@code revision} field set to indicate their
|
||||
* patch set.
|
||||
* @throws RestApiException
|
||||
*/
|
||||
List<CommentInfo> commentsAsList() throws RestApiException;
|
||||
|
||||
/**
|
||||
* Get all robot comments on a change.
|
||||
*
|
||||
@ -353,6 +362,15 @@ public interface ChangeApi {
|
||||
*/
|
||||
Map<String, List<CommentInfo>> drafts() throws RestApiException;
|
||||
|
||||
/**
|
||||
* Get all draft comments for the current user on a change as a list.
|
||||
*
|
||||
* @return drafts as a list; comments have the {@code revision} field set to indicate their patch
|
||||
* set.
|
||||
* @throws RestApiException
|
||||
*/
|
||||
List<CommentInfo> draftsAsList() throws RestApiException;
|
||||
|
||||
ChangeInfo check() throws RestApiException;
|
||||
|
||||
ChangeInfo check(FixInput fix) throws RestApiException;
|
||||
@ -580,6 +598,11 @@ public interface ChangeApi {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentInfo> commentsAsList() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
@ -590,6 +613,11 @@ public interface ChangeApi {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentInfo> draftsAsList() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeInfo check() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
|
@ -17,10 +17,12 @@ package com.google.gerrit.extensions.api.projects;
|
||||
import com.google.gerrit.extensions.api.changes.ChangeApi;
|
||||
import com.google.gerrit.extensions.api.changes.CherryPickInput;
|
||||
import com.google.gerrit.extensions.api.changes.IncludedInInfo;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.restapi.NotImplementedException;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
|
||||
public interface CommitApi {
|
||||
CommitInfo get() throws RestApiException;
|
||||
|
||||
ChangeApi cherryPick(CherryPickInput input) throws RestApiException;
|
||||
|
||||
@ -28,6 +30,11 @@ public interface CommitApi {
|
||||
|
||||
/** A default implementation for source compatibility when adding new methods to the interface. */
|
||||
class NotImplemented implements CommitApi {
|
||||
@Override
|
||||
public CommitInfo get() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeApi cherryPick(CherryPickInput input) throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
|
@ -66,7 +66,7 @@ public final class GerritLauncher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a proram.
|
||||
* Invokes a program.
|
||||
*
|
||||
* <p>Creates a new classloader to load and run the program class. To reuse a classloader across
|
||||
* calls (e.g. from tests), use {@link #invokeProgram(ClassLoader, String[])}.
|
||||
@ -176,7 +176,7 @@ public final class GerritLauncher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a proram in the provided {@code ClassLoader}.
|
||||
* Invokes a program in the provided {@code ClassLoader}.
|
||||
*
|
||||
* @param loader classloader to load program class from.
|
||||
* @param origArgv arguments, as would be passed to {@code gerrit.war}. The first argument is the
|
||||
|
@ -558,6 +558,15 @@ class ChangeApiImpl implements ChangeApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentInfo> commentsAsList() throws RestApiException {
|
||||
try {
|
||||
return listComments.getComments(change);
|
||||
} catch (Exception e) {
|
||||
throw asRestApiException("Cannot get comments", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
|
||||
try {
|
||||
@ -576,6 +585,15 @@ class ChangeApiImpl implements ChangeApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommentInfo> draftsAsList() throws RestApiException {
|
||||
try {
|
||||
return listDrafts.getComments(change);
|
||||
} catch (Exception e) {
|
||||
throw asRestApiException("Cannot get drafts", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeInfo check() throws RestApiException {
|
||||
try {
|
||||
|
@ -21,10 +21,12 @@ import com.google.gerrit.extensions.api.changes.Changes;
|
||||
import com.google.gerrit.extensions.api.changes.CherryPickInput;
|
||||
import com.google.gerrit.extensions.api.changes.IncludedInInfo;
|
||||
import com.google.gerrit.extensions.api.projects.CommitApi;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.server.project.CommitResource;
|
||||
import com.google.gerrit.server.restapi.change.CherryPickCommit;
|
||||
import com.google.gerrit.server.restapi.project.CommitIncludedIn;
|
||||
import com.google.gerrit.server.restapi.project.GetCommit;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
@ -34,6 +36,7 @@ public class CommitApiImpl implements CommitApi {
|
||||
}
|
||||
|
||||
private final Changes changes;
|
||||
private final GetCommit getCommit;
|
||||
private final CherryPickCommit cherryPickCommit;
|
||||
private final CommitIncludedIn includedIn;
|
||||
private final CommitResource commitResource;
|
||||
@ -41,15 +44,26 @@ public class CommitApiImpl implements CommitApi {
|
||||
@Inject
|
||||
CommitApiImpl(
|
||||
Changes changes,
|
||||
GetCommit getCommit,
|
||||
CherryPickCommit cherryPickCommit,
|
||||
CommitIncludedIn includedIn,
|
||||
@Assisted CommitResource commitResource) {
|
||||
this.changes = changes;
|
||||
this.getCommit = getCommit;
|
||||
this.cherryPickCommit = cherryPickCommit;
|
||||
this.includedIn = includedIn;
|
||||
this.commitResource = commitResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommitInfo get() throws RestApiException {
|
||||
try {
|
||||
return getCommit.apply(commitResource).value();
|
||||
} catch (Exception e) {
|
||||
throw asRestApiException("Cannot get commit info", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChangeApi cherryPick(CherryPickInput input) throws RestApiException {
|
||||
try {
|
||||
|
@ -31,7 +31,7 @@ public abstract class AuthRequest {
|
||||
/**
|
||||
* Returns the username to be authenticated.
|
||||
*
|
||||
* @return username for authentication or null for anonymous access.
|
||||
* @return username for authentication or {@code empty} for anonymous access.
|
||||
*/
|
||||
public final Optional<String> getUsername() {
|
||||
return username;
|
||||
@ -40,7 +40,7 @@ public abstract class AuthRequest {
|
||||
/**
|
||||
* Returns the user's credentials
|
||||
*
|
||||
* @return user's credentials or null
|
||||
* @return user's credentials or {@code empty}.
|
||||
*/
|
||||
public final Optional<String> getPassword() {
|
||||
return password;
|
||||
|
@ -19,6 +19,8 @@ import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.account.AccountState;
|
||||
import com.google.gerrit.server.config.ChangeCleanupConfig;
|
||||
import com.google.gerrit.server.plugincontext.PluginItemContext;
|
||||
import com.google.gerrit.server.query.change.ChangeData;
|
||||
import com.google.gerrit.server.update.BatchUpdate;
|
||||
import com.google.gerrit.server.update.UpdateException;
|
||||
@ -30,10 +32,17 @@ import java.util.Collection;
|
||||
@Singleton
|
||||
public class BatchAbandon {
|
||||
private final AbandonOp.Factory abandonOpFactory;
|
||||
private final ChangeCleanupConfig cfg;
|
||||
private final PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore;
|
||||
|
||||
@Inject
|
||||
BatchAbandon(AbandonOp.Factory abandonOpFactory) {
|
||||
BatchAbandon(
|
||||
AbandonOp.Factory abandonOpFactory,
|
||||
ChangeCleanupConfig cfg,
|
||||
PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore) {
|
||||
this.abandonOpFactory = abandonOpFactory;
|
||||
this.cfg = cfg;
|
||||
this.accountPatchReviewStore = accountPatchReviewStore;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,6 +76,10 @@ public class BatchAbandon {
|
||||
u.addOp(change.getId(), abandonOpFactory.create(accountState, msgTxt));
|
||||
}
|
||||
u.execute();
|
||||
|
||||
if (cfg.getCleanupAccountPatchReview()) {
|
||||
cleanupAccountPatchReview(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,4 +101,10 @@ public class BatchAbandon {
|
||||
throws RestApiException, UpdateException {
|
||||
batchAbandon(updateFactory, project, user, changes, "", NotifyResolver.Result.all());
|
||||
}
|
||||
|
||||
private void cleanupAccountPatchReview(Collection<ChangeData> changes) {
|
||||
for (ChangeData change : changes) {
|
||||
accountPatchReviewStore.run(s -> s.clearReviewed(change.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ public class ChangeCleanupConfig {
|
||||
private static String KEY_ABANDON_AFTER = "abandonAfter";
|
||||
private static String KEY_ABANDON_IF_MERGEABLE = "abandonIfMergeable";
|
||||
private static String KEY_ABANDON_MESSAGE = "abandonMessage";
|
||||
private static String KEY_CLEANUP_ACCOUNT_PATCH_REVIEW = "cleanupAccountPatchReview";
|
||||
private static String DEFAULT_ABANDON_MESSAGE =
|
||||
"Auto-Abandoned due to inactivity, see "
|
||||
+ "${URL}\n"
|
||||
@ -39,6 +40,7 @@ public class ChangeCleanupConfig {
|
||||
private final Optional<Schedule> schedule;
|
||||
private final long abandonAfter;
|
||||
private final boolean abandonIfMergeable;
|
||||
private final boolean cleanupAccountPatchReview;
|
||||
private final String abandonMessage;
|
||||
|
||||
@Inject
|
||||
@ -47,6 +49,8 @@ public class ChangeCleanupConfig {
|
||||
schedule = ScheduleConfig.createSchedule(cfg, SECTION);
|
||||
abandonAfter = readAbandonAfter(cfg);
|
||||
abandonIfMergeable = cfg.getBoolean(SECTION, null, KEY_ABANDON_IF_MERGEABLE, true);
|
||||
cleanupAccountPatchReview =
|
||||
cfg.getBoolean(SECTION, null, KEY_CLEANUP_ACCOUNT_PATCH_REVIEW, false);
|
||||
abandonMessage = readAbandonMessage(cfg);
|
||||
}
|
||||
|
||||
@ -73,6 +77,10 @@ public class ChangeCleanupConfig {
|
||||
return abandonIfMergeable;
|
||||
}
|
||||
|
||||
public boolean getCleanupAccountPatchReview() {
|
||||
return cleanupAccountPatchReview;
|
||||
}
|
||||
|
||||
public String getAbandonMessage() {
|
||||
String docUrl =
|
||||
urlFormatter.get().getDocUrl("user-change-cleanup.html", "auto-abandon").orElse("");
|
||||
|
@ -29,10 +29,10 @@ public class DefaultChangeReportFormatter implements ChangeReportFormatter {
|
||||
private static final int SUBJECT_CROP_RANGE = 10;
|
||||
private static final String NEW_CHANGE_INDICATOR = " [NEW]";
|
||||
|
||||
private final DynamicItem<UrlFormatter> urlFormatter;
|
||||
protected final DynamicItem<UrlFormatter> urlFormatter;
|
||||
|
||||
@Inject
|
||||
DefaultChangeReportFormatter(DynamicItem<UrlFormatter> urlFormatter) {
|
||||
public DefaultChangeReportFormatter(DynamicItem<UrlFormatter> urlFormatter) {
|
||||
this.urlFormatter = urlFormatter;
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,13 @@ package com.google.gerrit.server.query.account;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.gerrit.common.UsedAt;
|
||||
import com.google.gerrit.index.FieldDef;
|
||||
import com.google.gerrit.index.IndexConfig;
|
||||
import com.google.gerrit.index.Schema;
|
||||
@ -41,6 +44,8 @@ import java.util.Set;
|
||||
* holding on to a single instance.
|
||||
*/
|
||||
public class InternalAccountQuery extends InternalQuery<AccountState, InternalAccountQuery> {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
@Inject
|
||||
InternalAccountQuery(
|
||||
AccountQueryProcessor queryProcessor,
|
||||
@ -61,6 +66,23 @@ public class InternalAccountQuery extends InternalQuery<AccountState, InternalAc
|
||||
return query(AccountPredicates.externalIdIncludingSecondaryEmails(externalId.toString()));
|
||||
}
|
||||
|
||||
@UsedAt(UsedAt.Project.COLLABNET)
|
||||
public AccountState oneByExternalId(ExternalId.Key externalId) {
|
||||
List<AccountState> accountStates = byExternalId(externalId);
|
||||
if (accountStates.size() == 1) {
|
||||
return accountStates.get(0);
|
||||
} else if (accountStates.size() > 0) {
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Ambiguous external ID ").append(externalId).append(" for accounts: ");
|
||||
Joiner.on(", ")
|
||||
.appendTo(
|
||||
msg,
|
||||
accountStates.stream().map(a -> a.getAccount().id().toString()).collect(toList()));
|
||||
logger.atWarning().log(msg.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<AccountState> byFullName(String fullName) {
|
||||
return query(AccountPredicates.fullName(fullName));
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.hash.Hasher;
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.extensions.api.GerritApi;
|
||||
import com.google.gerrit.extensions.common.FileInfo;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
@ -27,8 +28,8 @@ import com.google.gerrit.extensions.restapi.CacheControl;
|
||||
import com.google.gerrit.extensions.restapi.ChildCollection;
|
||||
import com.google.gerrit.extensions.restapi.ETagView;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
@ -118,6 +119,7 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
|
||||
private final PatchListCache patchListCache;
|
||||
private final PatchSetUtil psUtil;
|
||||
private final PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore;
|
||||
private final GerritApi gApi;
|
||||
|
||||
@Inject
|
||||
ListFiles(
|
||||
@ -127,7 +129,8 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
|
||||
GitRepositoryManager gitManager,
|
||||
PatchListCache patchListCache,
|
||||
PatchSetUtil psUtil,
|
||||
PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore) {
|
||||
PluginItemContext<AccountPatchReviewStore> accountPatchReviewStore,
|
||||
GerritApi gApi) {
|
||||
this.self = self;
|
||||
this.fileInfoJson = fileInfoJson;
|
||||
this.revisions = revisions;
|
||||
@ -135,6 +138,7 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
|
||||
this.patchListCache = patchListCache;
|
||||
this.psUtil = psUtil;
|
||||
this.accountPatchReviewStore = accountPatchReviewStore;
|
||||
this.gApi = gApi;
|
||||
}
|
||||
|
||||
public ListFiles setReviewed(boolean r) {
|
||||
@ -144,9 +148,8 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
|
||||
|
||||
@Override
|
||||
public Response<?> apply(RevisionResource resource)
|
||||
throws AuthException, BadRequestException, ResourceNotFoundException,
|
||||
RepositoryNotFoundException, IOException, PatchListNotAvailableException,
|
||||
PermissionBackendException {
|
||||
throws RestApiException, RepositoryNotFoundException, IOException,
|
||||
PatchListNotAvailableException, PermissionBackendException {
|
||||
checkOptions();
|
||||
if (reviewed) {
|
||||
return Response.ok(reviewed(resource));
|
||||
@ -164,7 +167,17 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
|
||||
resource.getChange(),
|
||||
resource.getPatchSet().commitId(),
|
||||
baseResource.getPatchSet()));
|
||||
} else if (parentNum > 0) {
|
||||
} else if (parentNum != 0) {
|
||||
int parents =
|
||||
gApi.changes()
|
||||
.id(resource.getChange().getChangeId())
|
||||
.revision(resource.getPatchSet().id().get())
|
||||
.commit(false)
|
||||
.parents
|
||||
.size();
|
||||
if (parentNum < 0 || parentNum > parents) {
|
||||
throw new BadRequestException(String.format("invalid parent number: %d", parentNum));
|
||||
}
|
||||
r =
|
||||
Response.ok(
|
||||
fileInfoJson.toFileInfoMap(
|
||||
|
@ -14,46 +14,37 @@
|
||||
|
||||
package com.google.gerrit.server.restapi.change;
|
||||
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.reviewdb.client.Comment;
|
||||
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.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Singleton
|
||||
public class ListChangeComments implements RestReadView<ChangeResource> {
|
||||
private final ChangeData.Factory changeDataFactory;
|
||||
private final Provider<CommentJson> commentJson;
|
||||
private final CommentsUtil commentsUtil;
|
||||
|
||||
public class ListChangeComments extends ListChangeDrafts {
|
||||
@Inject
|
||||
ListChangeComments(
|
||||
ChangeData.Factory changeDataFactory,
|
||||
Provider<CommentJson> commentJson,
|
||||
CommentsUtil commentsUtil) {
|
||||
this.changeDataFactory = changeDataFactory;
|
||||
this.commentJson = commentJson;
|
||||
this.commentsUtil = commentsUtil;
|
||||
super(changeDataFactory, commentJson, commentsUtil);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Map<String, List<CommentInfo>>> apply(ChangeResource rsrc)
|
||||
throws AuthException, PermissionBackendException {
|
||||
protected Iterable<Comment> listComments(ChangeResource rsrc) {
|
||||
ChangeData cd = changeDataFactory.create(rsrc.getNotes());
|
||||
return Response.ok(
|
||||
commentJson
|
||||
.get()
|
||||
.setFillAccounts(true)
|
||||
.setFillPatchSet(true)
|
||||
.newCommentFormatter()
|
||||
.format(commentsUtil.publishedByChange(cd.notes())));
|
||||
return commentsUtil.publishedByChange(cd.notes());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean includeAuthorInfo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requireAuthentication() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ 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.gerrit.server.restapi.change.CommentJson.CommentFormatter;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
@ -31,9 +32,9 @@ import java.util.Map;
|
||||
|
||||
@Singleton
|
||||
public class ListChangeDrafts implements RestReadView<ChangeResource> {
|
||||
private final ChangeData.Factory changeDataFactory;
|
||||
private final Provider<CommentJson> commentJson;
|
||||
private final CommentsUtil commentsUtil;
|
||||
protected final ChangeData.Factory changeDataFactory;
|
||||
protected final Provider<CommentJson> commentJson;
|
||||
protected final CommentsUtil commentsUtil;
|
||||
|
||||
@Inject
|
||||
ListChangeDrafts(
|
||||
@ -45,21 +46,41 @@ public class ListChangeDrafts implements RestReadView<ChangeResource> {
|
||||
this.commentsUtil = commentsUtil;
|
||||
}
|
||||
|
||||
protected Iterable<Comment> listComments(ChangeResource rsrc) {
|
||||
ChangeData cd = changeDataFactory.create(rsrc.getNotes());
|
||||
return commentsUtil.draftByChangeAuthor(cd.notes(), rsrc.getUser().getAccountId());
|
||||
}
|
||||
|
||||
protected boolean includeAuthorInfo() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean requireAuthentication() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Map<String, List<CommentInfo>>> apply(ChangeResource rsrc)
|
||||
throws AuthException, PermissionBackendException {
|
||||
if (!rsrc.getUser().isIdentifiedUser()) {
|
||||
if (requireAuthentication() && !rsrc.getUser().isIdentifiedUser()) {
|
||||
throw new AuthException("Authentication required");
|
||||
}
|
||||
ChangeData cd = changeDataFactory.create(rsrc.getNotes());
|
||||
List<Comment> drafts =
|
||||
commentsUtil.draftByChangeAuthor(cd.notes(), rsrc.getUser().getAccountId());
|
||||
return Response.ok(
|
||||
commentJson
|
||||
.get()
|
||||
.setFillAccounts(false)
|
||||
.setFillPatchSet(true)
|
||||
.newCommentFormatter()
|
||||
.format(drafts));
|
||||
return Response.ok(getCommentFormatter().format(listComments(rsrc)));
|
||||
}
|
||||
|
||||
public List<CommentInfo> getComments(ChangeResource rsrc)
|
||||
throws AuthException, PermissionBackendException {
|
||||
if (requireAuthentication() && !rsrc.getUser().isIdentifiedUser()) {
|
||||
throw new AuthException("Authentication required");
|
||||
}
|
||||
return getCommentFormatter().formatAsList(listComments(rsrc));
|
||||
}
|
||||
|
||||
private CommentFormatter getCommentFormatter() {
|
||||
return commentJson
|
||||
.get()
|
||||
.setFillAccounts(includeAuthorInfo())
|
||||
.setFillPatchSet(true)
|
||||
.newCommentFormatter();
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,6 @@ public class PrologEnvironment extends BufferingPrologControl {
|
||||
public void setPredicate(Predicate goal) {
|
||||
super.setPredicate(goal);
|
||||
int reductionLimit = args.reductionLimit(goal);
|
||||
logger.atFine().log("setting reductionLimit %d", reductionLimit);
|
||||
setReductionLimit(reductionLimit);
|
||||
}
|
||||
|
||||
@ -223,6 +222,9 @@ public class PrologEnvironment extends BufferingPrologControl {
|
||||
|
||||
private int reductionLimit(Predicate goal) {
|
||||
if (goal.getClass() == CONSULT_STREAM_2) {
|
||||
logger.atFine().log(
|
||||
"predicate class is CONSULT_STREAM_2: override reductionLimit with compileLimit (%d)",
|
||||
compileLimit);
|
||||
return compileLimit;
|
||||
}
|
||||
return reductionLimit;
|
||||
|
@ -320,6 +320,21 @@ public class AccountIT extends AbstractDaemonTest {
|
||||
RefUpdateCounter.projectRef(allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithInvalidEmailAddress() throws Exception {
|
||||
AccountInput input = new AccountInput();
|
||||
input.username = name("test");
|
||||
input.email = "invalid email address";
|
||||
|
||||
// Invalid email address should cause the creation to fail
|
||||
BadRequestException thrown =
|
||||
assertThrows(BadRequestException.class, () -> gApi.accounts().create(input));
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("invalid email address");
|
||||
|
||||
// The account should not have been created
|
||||
assertThrows(ResourceNotFoundException.class, () -> gApi.accounts().id(input.username).get());
|
||||
}
|
||||
|
||||
private Account.Id createByAccountCreator(int expectedAccountReindexCalls) throws Exception {
|
||||
String name = "foo";
|
||||
TestAccount foo = accountCreator.create(name);
|
||||
|
@ -90,10 +90,12 @@ import com.google.gerrit.common.data.LabelType;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.exceptions.StorageException;
|
||||
import com.google.gerrit.extensions.annotations.Exports;
|
||||
import com.google.gerrit.extensions.api.accounts.DeleteDraftCommentsInput;
|
||||
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
|
||||
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
|
||||
import com.google.gerrit.extensions.api.changes.DeleteReviewerInput;
|
||||
import com.google.gerrit.extensions.api.changes.DeleteVoteInput;
|
||||
import com.google.gerrit.extensions.api.changes.DraftApi;
|
||||
import com.google.gerrit.extensions.api.changes.DraftInput;
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.api.changes.NotifyInfo;
|
||||
@ -4189,7 +4191,7 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
submittableAfterLosingPermissions("Label");
|
||||
}
|
||||
|
||||
public void submittableAfterLosingPermissions(String label) throws Exception {
|
||||
private void submittableAfterLosingPermissions(String label) throws Exception {
|
||||
String codeReviewLabel = "Code-Review";
|
||||
AccountGroup.UUID registered = REGISTERED_USERS;
|
||||
projectOperations
|
||||
@ -4242,6 +4244,46 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
gApi.changes().id(changeId).current().submit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void draftCommentsShouldNotUpdateChangeTimestamp() throws Exception {
|
||||
String changeId = createNewChange();
|
||||
Timestamp changeTs = getChangeLastUpdate(changeId);
|
||||
DraftApi draftApi = addDraftComment(changeId);
|
||||
assertThat(getChangeLastUpdate(changeId)).isEqualTo(changeTs);
|
||||
draftApi.delete();
|
||||
assertThat(getChangeLastUpdate(changeId)).isEqualTo(changeTs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletingAllDraftCommentsShouldNotUpdateChangeTimestamp() throws Exception {
|
||||
String changeId = createNewChange();
|
||||
Timestamp changeTs = getChangeLastUpdate(changeId);
|
||||
addDraftComment(changeId);
|
||||
assertThat(getChangeLastUpdate(changeId)).isEqualTo(changeTs);
|
||||
gApi.accounts().self().deleteDraftComments(new DeleteDraftCommentsInput());
|
||||
assertThat(getChangeLastUpdate(changeId)).isEqualTo(changeTs);
|
||||
}
|
||||
|
||||
private Timestamp getChangeLastUpdate(String changeId) throws RestApiException {
|
||||
Timestamp changeTs = gApi.changes().id(changeId).get().updated;
|
||||
return changeTs;
|
||||
}
|
||||
|
||||
private String createNewChange() throws Exception {
|
||||
TestRepository<InMemoryRepository> userRepo = cloneProject(project, user);
|
||||
PushOneCommit.Result result =
|
||||
pushFactory.create(user.newIdent(), userRepo).to("refs/for/master");
|
||||
String changeId = result.getChangeId();
|
||||
return changeId;
|
||||
}
|
||||
|
||||
private DraftApi addDraftComment(String changeId) throws RestApiException {
|
||||
DraftInput comment = new DraftInput();
|
||||
comment.message = "foo";
|
||||
comment.path = "/foo";
|
||||
return gApi.changes().id(changeId).current().createDraft(comment);
|
||||
}
|
||||
|
||||
private String getCommitMessage(String changeId) throws RestApiException, IOException {
|
||||
return gApi.changes().id(changeId).current().file("/COMMIT_MSG").content().asString();
|
||||
}
|
||||
|
160
javatests/com/google/gerrit/acceptance/api/project/CommitIT.java
Normal file
160
javatests/com/google/gerrit/acceptance/api/project/CommitIT.java
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright (C) 2017 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.testsuite.project.TestProjectUpdate.allow;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.eclipse.jgit.lib.Constants.R_TAGS;
|
||||
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit.Result;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.extensions.api.changes.CherryPickInput;
|
||||
import com.google.gerrit.extensions.api.changes.IncludedInInfo;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.projects.BranchInput;
|
||||
import com.google.gerrit.extensions.api.projects.TagInput;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeMessageInfo;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.common.GitPerson;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.reviewdb.client.BranchNameKey;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public class CommitIT extends AbstractDaemonTest {
|
||||
@Inject private ProjectOperations projectOperations;
|
||||
|
||||
@Test
|
||||
public void getCommitInfo() throws Exception {
|
||||
Result result = createChange();
|
||||
String commitId = result.getCommit().getId().name();
|
||||
CommitInfo info = gApi.projects().name(project.get()).commit(commitId).get();
|
||||
assertThat(info.commit).isEqualTo(commitId);
|
||||
assertThat(info.parents.stream().map(c -> c.commit).collect(toList()))
|
||||
.containsExactly(result.getCommit().getParent(0).name());
|
||||
assertThat(info.subject).isEqualTo(result.getCommit().getShortMessage());
|
||||
assertPerson(info.author, admin);
|
||||
assertPerson(info.committer, admin);
|
||||
assertThat(info.webLinks).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includedInOpenChange() throws Exception {
|
||||
Result result = createChange();
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches).isEmpty();
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includedInMergedChange() throws Exception {
|
||||
Result result = createChange();
|
||||
gApi.changes()
|
||||
.id(result.getChangeId())
|
||||
.revision(result.getCommit().name())
|
||||
.review(ReviewInput.approve());
|
||||
gApi.changes().id(result.getChangeId()).revision(result.getCommit().name()).submit();
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches).containsExactly("master");
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).isEmpty();
|
||||
|
||||
projectOperations
|
||||
.project(project)
|
||||
.forUpdate()
|
||||
.add(allow(Permission.CREATE_TAG).ref(R_TAGS + "*").group(adminGroupUuid()))
|
||||
.update();
|
||||
gApi.projects().name(result.getChange().project().get()).tag("test-tag").create(new TagInput());
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).containsExactly("test-tag");
|
||||
|
||||
createBranch(BranchNameKey.create(project, "test-branch"));
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches)
|
||||
.containsExactly("master", "test-branch");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cherryPickCommitWithoutChangeId() throws Exception {
|
||||
// This test is a little superfluous, since the current cherry-pick code ignores
|
||||
// the commit message of the to-be-cherry-picked change, using the one in
|
||||
// CherryPickInput instead.
|
||||
CherryPickInput input = new CherryPickInput();
|
||||
input.destination = "foo";
|
||||
input.message = "it goes to foo branch";
|
||||
gApi.projects().name(project.get()).branch(input.destination).create(new BranchInput());
|
||||
|
||||
RevCommit revCommit = createNewCommitWithoutChangeId("refs/heads/master", "a.txt", "content");
|
||||
ChangeInfo changeInfo =
|
||||
gApi.projects().name(project.get()).commit(revCommit.getName()).cherryPick(input).get();
|
||||
|
||||
assertThat(changeInfo.messages).hasSize(1);
|
||||
Iterator<ChangeMessageInfo> messageIterator = changeInfo.messages.iterator();
|
||||
String expectedMessage =
|
||||
String.format("Patch Set 1: Cherry Picked from commit %s.", revCommit.getName());
|
||||
assertThat(messageIterator.next().message).isEqualTo(expectedMessage);
|
||||
|
||||
RevisionInfo revInfo = changeInfo.revisions.get(changeInfo.currentRevision);
|
||||
assertThat(revInfo).isNotNull();
|
||||
CommitInfo commitInfo = revInfo.commit;
|
||||
assertThat(commitInfo.message)
|
||||
.isEqualTo(input.message + "\n\nChange-Id: " + changeInfo.changeId + "\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cherryPickCommitWithChangeId() throws Exception {
|
||||
CherryPickInput input = new CherryPickInput();
|
||||
input.destination = "foo";
|
||||
|
||||
RevCommit revCommit = createChange().getCommit();
|
||||
List<String> footers = revCommit.getFooterLines("Change-Id");
|
||||
assertThat(footers).hasSize(1);
|
||||
String changeId = footers.get(0);
|
||||
|
||||
input.message = "it goes to foo branch\n\nChange-Id: " + changeId;
|
||||
gApi.projects().name(project.get()).branch(input.destination).create(new BranchInput());
|
||||
|
||||
ChangeInfo changeInfo =
|
||||
gApi.projects().name(project.get()).commit(revCommit.getName()).cherryPick(input).get();
|
||||
|
||||
assertThat(changeInfo.messages).hasSize(1);
|
||||
Iterator<ChangeMessageInfo> messageIterator = changeInfo.messages.iterator();
|
||||
String expectedMessage =
|
||||
String.format("Patch Set 1: Cherry Picked from commit %s.", revCommit.getName());
|
||||
assertThat(messageIterator.next().message).isEqualTo(expectedMessage);
|
||||
|
||||
RevisionInfo revInfo = changeInfo.revisions.get(changeInfo.currentRevision);
|
||||
assertThat(revInfo).isNotNull();
|
||||
assertThat(revInfo.commit.message).isEqualTo(input.message + "\n");
|
||||
}
|
||||
|
||||
private IncludedInInfo getIncludedIn(ObjectId id) throws Exception {
|
||||
return gApi.projects().name(project.get()).commit(id.name()).includedIn();
|
||||
}
|
||||
|
||||
private static void assertPerson(GitPerson actual, TestAccount expected) {
|
||||
assertThat(actual.email).isEqualTo(expected.email());
|
||||
assertThat(actual.name).isEqualTo(expected.fullName());
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
// Copyright (C) 2017 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.testsuite.project.TestProjectUpdate.allow;
|
||||
import static org.eclipse.jgit.lib.Constants.R_TAGS;
|
||||
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit.Result;
|
||||
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.extensions.api.changes.IncludedInInfo;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.projects.TagInput;
|
||||
import com.google.gerrit.reviewdb.client.BranchNameKey;
|
||||
import com.google.inject.Inject;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public class CommitIncludedInIT extends AbstractDaemonTest {
|
||||
@Inject private ProjectOperations projectOperations;
|
||||
|
||||
@Test
|
||||
public void includedInOpenChange() throws Exception {
|
||||
Result result = createChange();
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches).isEmpty();
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includedInMergedChange() throws Exception {
|
||||
Result result = createChange();
|
||||
gApi.changes()
|
||||
.id(result.getChangeId())
|
||||
.revision(result.getCommit().name())
|
||||
.review(ReviewInput.approve());
|
||||
gApi.changes().id(result.getChangeId()).revision(result.getCommit().name()).submit();
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches).containsExactly("master");
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).isEmpty();
|
||||
|
||||
projectOperations
|
||||
.project(project)
|
||||
.forUpdate()
|
||||
.add(allow(Permission.CREATE_TAG).ref(R_TAGS + "*").group(adminGroupUuid()))
|
||||
.update();
|
||||
gApi.projects().name(result.getChange().project().get()).tag("test-tag").create(new TagInput());
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).tags).containsExactly("test-tag");
|
||||
|
||||
createBranch(BranchNameKey.create(project, "test-branch"));
|
||||
|
||||
assertThat(getIncludedIn(result.getCommit().getId()).branches)
|
||||
.containsExactly("master", "test-branch");
|
||||
}
|
||||
|
||||
private IncludedInInfo getIncludedIn(ObjectId id) throws Exception {
|
||||
return gApi.projects().name(project.get()).commit(id.name()).includedIn();
|
||||
}
|
||||
}
|
@ -1085,30 +1085,76 @@ public class RevisionIT extends AbstractDaemonTest {
|
||||
PushOneCommit.Result r = createChange();
|
||||
Map<String, FileInfo> files =
|
||||
gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files();
|
||||
assertThat(files).hasSize(2);
|
||||
assertThat(Iterables.all(files.keySet(), f -> f.matches(FILE_NAME + '|' + COMMIT_MSG)))
|
||||
.isTrue();
|
||||
assertThat(files.keySet()).containsExactly(FILE_NAME, COMMIT_MSG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filesOnMergeCommitChange() throws Exception {
|
||||
PushOneCommit.Result r = createMergeCommitChange("refs/for/master");
|
||||
|
||||
// list files against auto-merge
|
||||
// List files against auto-merge
|
||||
assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files().keySet())
|
||||
.containsExactly(COMMIT_MSG, MERGE_LIST, "foo", "bar");
|
||||
|
||||
// list files against parent 1
|
||||
// List files against parent 1
|
||||
assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files(1).keySet())
|
||||
.containsExactly(COMMIT_MSG, MERGE_LIST, "bar");
|
||||
|
||||
// list files against parent 2
|
||||
// List files against parent 2
|
||||
assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files(2).keySet())
|
||||
.containsExactly(COMMIT_MSG, MERGE_LIST, "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filesOnMergeCommitChangeWithInvalidParent() throws Exception {
|
||||
PushOneCommit.Result r = createMergeCommitChange("refs/for/master");
|
||||
|
||||
BadRequestException thrown =
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
() ->
|
||||
gApi.changes()
|
||||
.id(r.getChangeId())
|
||||
.revision(r.getCommit().name())
|
||||
.files(3)
|
||||
.keySet());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("invalid parent number: 3");
|
||||
thrown =
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
() ->
|
||||
gApi.changes()
|
||||
.id(r.getChangeId())
|
||||
.revision(r.getCommit().name())
|
||||
.files(-1)
|
||||
.keySet());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("invalid parent number: -1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFilesWithInvalidParent() throws Exception {
|
||||
PushOneCommit.Result result1 = createChange();
|
||||
String changeId = result1.getChangeId();
|
||||
PushOneCommit.Result result2 = amendChange(changeId, SUBJECT, "b.txt", "b");
|
||||
String revId2 = result2.getCommit().name();
|
||||
|
||||
BadRequestException thrown =
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
() -> gApi.changes().id(changeId).revision(revId2).files(2).keySet());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("invalid parent number: 2");
|
||||
|
||||
thrown =
|
||||
assertThrows(
|
||||
BadRequestException.class,
|
||||
() -> gApi.changes().id(changeId).revision(revId2).files(-1).keySet());
|
||||
assertThat(thrown).hasMessageThat().isEqualTo("invalid parent number: -1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listFilesOnDifferentBases() throws Exception {
|
||||
RevCommit initialCommit = getHead(repo(), "HEAD");
|
||||
|
||||
PushOneCommit.Result result1 = createChange();
|
||||
String changeId = result1.getChangeId();
|
||||
PushOneCommit.Result result2 = amendChange(changeId, SUBJECT, "b.txt", "b");
|
||||
@ -1131,6 +1177,19 @@ public class RevisionIT extends AbstractDaemonTest {
|
||||
.containsExactly(COMMIT_MSG, "b.txt", "c.txt");
|
||||
assertThat(gApi.changes().id(changeId).revision(revId3).files(revId2).keySet())
|
||||
.containsExactly(COMMIT_MSG, "c.txt");
|
||||
|
||||
ResourceNotFoundException thrown =
|
||||
assertThrows(
|
||||
ResourceNotFoundException.class,
|
||||
() -> gApi.changes().id(changeId).revision(revId3).files(initialCommit.getName()));
|
||||
assertThat(thrown).hasMessageThat().contains(initialCommit.getName());
|
||||
|
||||
String invalidRev = "deadbeef";
|
||||
thrown =
|
||||
assertThrows(
|
||||
ResourceNotFoundException.class,
|
||||
() -> gApi.changes().id(changeId).revision(revId3).files(invalidRev));
|
||||
assertThat(thrown).hasMessageThat().contains(invalidRev);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -32,12 +32,12 @@ public class ElasticReindexIT extends AbstractReindexTests {
|
||||
|
||||
@ConfigSuite.Config
|
||||
public static Config elasticsearchV6() {
|
||||
return getConfig(ElasticVersion.V6_7);
|
||||
return getConfig(ElasticVersion.V6_8);
|
||||
}
|
||||
|
||||
@ConfigSuite.Config
|
||||
public static Config elasticsearchV7() {
|
||||
return getConfig(ElasticVersion.V7_2);
|
||||
return getConfig(ElasticVersion.V7_3);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,15 +35,11 @@ import com.google.gerrit.extensions.api.changes.ChangeApi;
|
||||
import com.google.gerrit.extensions.api.changes.CherryPickInput;
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.projects.BranchInput;
|
||||
import com.google.gerrit.extensions.client.ChangeStatus;
|
||||
import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInput;
|
||||
import com.google.gerrit.extensions.common.ChangeMessageInfo;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.common.MergeInput;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
@ -56,7 +52,6 @@ import com.google.gerrit.server.submit.ChangeAlreadyMergedException;
|
||||
import com.google.gerrit.testing.FakeEmailSender.Message;
|
||||
import com.google.gerrit.testing.TestTimeUtil;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
@ -409,60 +404,6 @@ public class CreateChangeIT extends AbstractDaemonTest {
|
||||
assertCreateSucceeds(in);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cherryPickCommitWithoutChangeId() throws Exception {
|
||||
// This test is a little superfluous, since the current cherry-pick code ignores
|
||||
// the commit message of the to-be-cherry-picked change, using the one in
|
||||
// CherryPickInput instead.
|
||||
CherryPickInput input = new CherryPickInput();
|
||||
input.destination = "foo";
|
||||
input.message = "it goes to foo branch";
|
||||
gApi.projects().name(project.get()).branch(input.destination).create(new BranchInput());
|
||||
|
||||
RevCommit revCommit = createNewCommitWithoutChangeId("refs/heads/master", "a.txt", "content");
|
||||
ChangeInfo changeInfo =
|
||||
gApi.projects().name(project.get()).commit(revCommit.getName()).cherryPick(input).get();
|
||||
|
||||
assertThat(changeInfo.messages).hasSize(1);
|
||||
Iterator<ChangeMessageInfo> messageIterator = changeInfo.messages.iterator();
|
||||
String expectedMessage =
|
||||
String.format("Patch Set 1: Cherry Picked from commit %s.", revCommit.getName());
|
||||
assertThat(messageIterator.next().message).isEqualTo(expectedMessage);
|
||||
|
||||
RevisionInfo revInfo = changeInfo.revisions.get(changeInfo.currentRevision);
|
||||
assertThat(revInfo).isNotNull();
|
||||
CommitInfo commitInfo = revInfo.commit;
|
||||
assertThat(commitInfo.message)
|
||||
.isEqualTo(input.message + "\n\nChange-Id: " + changeInfo.changeId + "\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cherryPickCommitWithChangeId() throws Exception {
|
||||
CherryPickInput input = new CherryPickInput();
|
||||
input.destination = "foo";
|
||||
|
||||
RevCommit revCommit = createChange().getCommit();
|
||||
List<String> footers = revCommit.getFooterLines("Change-Id");
|
||||
assertThat(footers).hasSize(1);
|
||||
String changeId = footers.get(0);
|
||||
|
||||
input.message = "it goes to foo branch\n\nChange-Id: " + changeId;
|
||||
gApi.projects().name(project.get()).branch(input.destination).create(new BranchInput());
|
||||
|
||||
ChangeInfo changeInfo =
|
||||
gApi.projects().name(project.get()).commit(revCommit.getName()).cherryPick(input).get();
|
||||
|
||||
assertThat(changeInfo.messages).hasSize(1);
|
||||
Iterator<ChangeMessageInfo> messageIterator = changeInfo.messages.iterator();
|
||||
String expectedMessage =
|
||||
String.format("Patch Set 1: Cherry Picked from commit %s.", revCommit.getName());
|
||||
assertThat(messageIterator.next().message).isEqualTo(expectedMessage);
|
||||
|
||||
RevisionInfo revInfo = changeInfo.revisions.get(changeInfo.currentRevision);
|
||||
assertThat(revInfo).isNotNull();
|
||||
assertThat(revInfo.commit.message).isEqualTo(input.message + "\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createChangeOnExistingBranchNotPermitted() throws Exception {
|
||||
createBranch(BranchNameKey.create(project, "foo"));
|
||||
|
@ -113,6 +113,11 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
assertThat(result).hasSize(1);
|
||||
CommentInfo actual = Iterables.getOnlyElement(result.get(comment.path));
|
||||
assertThat(comment).isEqualTo(infoToDraft(path).apply(actual));
|
||||
|
||||
List<CommentInfo> list = getDraftCommentsAsList(changeId);
|
||||
assertThat(list).hasSize(1);
|
||||
actual = list.get(0);
|
||||
assertThat(comment).isEqualTo(infoToDraft(path).apply(actual));
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +139,10 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
Map<String, List<CommentInfo>> result = getDraftComments(changeId, revId);
|
||||
assertThat(result).hasSize(1);
|
||||
assertThat(result.get(path).stream().map(infoToDraft(path))).containsExactly(c1, c2, c3, c4);
|
||||
|
||||
List<CommentInfo> list = getDraftCommentsAsList(changeId);
|
||||
assertThat(list).hasSize(4);
|
||||
assertThat(list.stream().map(infoToDraft(path))).containsExactly(c1, c2, c3, c4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +244,9 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
Map<String, List<CommentInfo>> result = getPublishedComments(changeId, revId);
|
||||
assertThat(result).isNotEmpty();
|
||||
assertThat(result.get(file).stream().map(infoToInput(file))).containsExactly(c1, c2, c3, c4);
|
||||
|
||||
List<CommentInfo> list = getPublishedCommentsAsList(changeId);
|
||||
assertThat(list.stream().map(infoToInput(file))).containsExactly(c1, c2, c3, c4);
|
||||
}
|
||||
|
||||
// for the commit message comments on the auto-merge are not possible
|
||||
@ -253,6 +265,9 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
Map<String, List<CommentInfo>> result = getPublishedComments(changeId, revId);
|
||||
assertThat(result).isNotEmpty();
|
||||
assertThat(result.get(file).stream().map(infoToInput(file))).containsExactly(c1, c2, c3);
|
||||
|
||||
List<CommentInfo> list = getPublishedCommentsAsList(changeId);
|
||||
assertThat(list.stream().map(infoToInput(file))).containsExactly(c1, c2, c3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,6 +323,7 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
String changeId = r.getChangeId();
|
||||
String revId = r.getCommit().getName();
|
||||
assertThat(getPublishedComments(changeId, revId)).isEmpty();
|
||||
assertThat(getPublishedCommentsAsList(changeId)).isEmpty();
|
||||
|
||||
List<CommentInput> expectedComments = new ArrayList<>();
|
||||
for (Integer line : lines) {
|
||||
@ -324,6 +340,9 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
List<CommentInfo> actualComments = result.get(file);
|
||||
assertThat(actualComments.stream().map(infoToInput(file)))
|
||||
.containsExactlyElementsIn(expectedComments);
|
||||
|
||||
List<CommentInfo> list = getPublishedCommentsAsList(changeId);
|
||||
assertThat(list.stream().map(infoToInput(file))).containsExactlyElementsIn(expectedComments);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1125,11 +1144,19 @@ public class CommentsIT extends AbstractDaemonTest {
|
||||
return gApi.changes().id(changeId).revision(revId).comments();
|
||||
}
|
||||
|
||||
private List<CommentInfo> getPublishedCommentsAsList(String changeId) throws Exception {
|
||||
return gApi.changes().id(changeId).commentsAsList();
|
||||
}
|
||||
|
||||
private Map<String, List<CommentInfo>> getDraftComments(String changeId, String revId)
|
||||
throws Exception {
|
||||
return gApi.changes().id(changeId).revision(revId).drafts();
|
||||
}
|
||||
|
||||
private List<CommentInfo> getDraftCommentsAsList(String changeId) throws Exception {
|
||||
return gApi.changes().id(changeId).draftsAsList();
|
||||
}
|
||||
|
||||
private CommentInfo getDraftComment(String changeId, String revId, String uuid) throws Exception {
|
||||
return gApi.changes().id(changeId).revision(revId).draft(uuid).get();
|
||||
}
|
||||
|
@ -31,12 +31,12 @@ public class ElasticIndexIT extends AbstractIndexTests {
|
||||
|
||||
@ConfigSuite.Config
|
||||
public static Config elasticsearchV6() {
|
||||
return getConfig(ElasticVersion.V6_7);
|
||||
return getConfig(ElasticVersion.V6_8);
|
||||
}
|
||||
|
||||
@ConfigSuite.Config
|
||||
public static Config elasticsearchV7() {
|
||||
return getConfig(ElasticVersion.V7_2);
|
||||
return getConfig(ElasticVersion.V7_3);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,12 +50,16 @@ public class ElasticContainer extends ElasticsearchContainer {
|
||||
return "blacktop/elasticsearch:6.6.2";
|
||||
case V6_7:
|
||||
return "blacktop/elasticsearch:6.7.2";
|
||||
case V6_8:
|
||||
return "blacktop/elasticsearch:6.8.2";
|
||||
case V7_0:
|
||||
return "blacktop/elasticsearch:7.0.1";
|
||||
case V7_1:
|
||||
return "blacktop/elasticsearch:7.1.1";
|
||||
case V7_2:
|
||||
return "blacktop/elasticsearch:7.2.0";
|
||||
return "blacktop/elasticsearch:7.2.1";
|
||||
case V7_3:
|
||||
return "blacktop/elasticsearch:7.3.1";
|
||||
}
|
||||
throw new IllegalStateException("No tests for version: " + version.name());
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV6QueryAccountsTest extends AbstractQueryAccountsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_7);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ public class ElasticV6QueryChangesTest extends AbstractQueryChangesTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_7);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV6QueryGroupsTest extends AbstractQueryGroupsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_7);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV6QueryProjectsTest extends AbstractQueryProjectsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_7);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V6_8);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV7QueryAccountsTest extends AbstractQueryAccountsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_2);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_3);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class ElasticV7QueryChangesTest extends AbstractQueryChangesTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_2);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_3);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
client = HttpAsyncClients.createDefault();
|
||||
client.start();
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV7QueryGroupsTest extends AbstractQueryGroupsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_2);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_3);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class ElasticV7QueryProjectsTest extends AbstractQueryProjectsTest {
|
||||
return;
|
||||
}
|
||||
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_2);
|
||||
container = ElasticContainer.createAndStart(ElasticVersion.V7_3);
|
||||
nodeInfo = new ElasticNodeInfo(container.getHttpHost().getPort());
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,9 @@ public class ElasticVersionTest {
|
||||
assertThat(ElasticVersion.forVersion("6.7.0")).isEqualTo(ElasticVersion.V6_7);
|
||||
assertThat(ElasticVersion.forVersion("6.7.1")).isEqualTo(ElasticVersion.V6_7);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("6.8.0")).isEqualTo(ElasticVersion.V6_8);
|
||||
assertThat(ElasticVersion.forVersion("6.8.1")).isEqualTo(ElasticVersion.V6_8);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("7.0.0")).isEqualTo(ElasticVersion.V7_0);
|
||||
assertThat(ElasticVersion.forVersion("7.0.1")).isEqualTo(ElasticVersion.V7_0);
|
||||
|
||||
@ -51,6 +54,9 @@ public class ElasticVersionTest {
|
||||
|
||||
assertThat(ElasticVersion.forVersion("7.2.0")).isEqualTo(ElasticVersion.V7_2);
|
||||
assertThat(ElasticVersion.forVersion("7.2.1")).isEqualTo(ElasticVersion.V7_2);
|
||||
|
||||
assertThat(ElasticVersion.forVersion("7.3.0")).isEqualTo(ElasticVersion.V7_3);
|
||||
assertThat(ElasticVersion.forVersion("7.3.1")).isEqualTo(ElasticVersion.V7_3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -74,9 +80,11 @@ public class ElasticVersionTest {
|
||||
assertThat(ElasticVersion.V6_5.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_6.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V6_7.isAtLeastMinorVersion(ElasticVersion.V6_7)).isTrue();
|
||||
assertThat(ElasticVersion.V6_8.isAtLeastMinorVersion(ElasticVersion.V6_8)).isTrue();
|
||||
assertThat(ElasticVersion.V7_0.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V7_1.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V7_2.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
assertThat(ElasticVersion.V7_3.isAtLeastMinorVersion(ElasticVersion.V6_7)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -88,9 +96,11 @@ public class ElasticVersionTest {
|
||||
assertThat(ElasticVersion.V6_5.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_6.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_7.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V6_8.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_0.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_1.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_2.isV6OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_3.isV6OrLater()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -102,8 +112,10 @@ public class ElasticVersionTest {
|
||||
assertThat(ElasticVersion.V6_5.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_6.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_7.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V6_8.isV7OrLater()).isFalse();
|
||||
assertThat(ElasticVersion.V7_0.isV7OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_1.isV7OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_2.isV7OrLater()).isTrue();
|
||||
assertThat(ElasticVersion.V7_3.isV7OrLater()).isTrue();
|
||||
}
|
||||
}
|
||||
|
203
lib/highlightjs/highlight.min.js
vendored
203
lib/highlightjs/highlight.min.js
vendored
File diff suppressed because one or more lines are too long
@ -121,9 +121,11 @@ shortcuts are.
|
||||
|
||||
const Shortcut = {
|
||||
OPEN_SHORTCUT_HELP_DIALOG: 'OPEN_SHORTCUT_HELP_DIALOG',
|
||||
GO_TO_USER_DASHBOARD: 'GO_TO_USER_DASHBOARD',
|
||||
GO_TO_OPENED_CHANGES: 'GO_TO_OPENED_CHANGES',
|
||||
GO_TO_MERGED_CHANGES: 'GO_TO_MERGED_CHANGES',
|
||||
GO_TO_ABANDONED_CHANGES: 'GO_TO_ABANDONED_CHANGES',
|
||||
GO_TO_WATCHED_CHANGES: 'GO_TO_WATCHED_CHANGES',
|
||||
|
||||
CURSOR_NEXT_CHANGE: 'CURSOR_NEXT_CHANGE',
|
||||
CURSOR_PREV_CHANGE: 'CURSOR_PREV_CHANGE',
|
||||
@ -192,12 +194,16 @@ shortcuts are.
|
||||
_describe(Shortcut.SEARCH, ShortcutSection.EVERYWHERE, 'Search');
|
||||
_describe(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, ShortcutSection.EVERYWHERE,
|
||||
'Show this dialog');
|
||||
_describe(Shortcut.GO_TO_USER_DASHBOARD, ShortcutSection.EVERYWHERE,
|
||||
'Go to User Dashboard');
|
||||
_describe(Shortcut.GO_TO_OPENED_CHANGES, ShortcutSection.EVERYWHERE,
|
||||
'Go to Opened Changes');
|
||||
_describe(Shortcut.GO_TO_MERGED_CHANGES, ShortcutSection.EVERYWHERE,
|
||||
'Go to Merged Changes');
|
||||
_describe(Shortcut.GO_TO_ABANDONED_CHANGES, ShortcutSection.EVERYWHERE,
|
||||
'Go to Abandoned Changes');
|
||||
_describe(Shortcut.GO_TO_WATCHED_CHANGES, ShortcutSection.EVERYWHERE,
|
||||
'Go to Watched Changes');
|
||||
|
||||
_describe(Shortcut.CURSOR_NEXT_CHANGE, ShortcutSection.ACTIONS,
|
||||
'Select next change');
|
||||
|
@ -204,10 +204,11 @@
|
||||
});
|
||||
|
||||
for (const key of keys) {
|
||||
if (!values[key]) { return; }
|
||||
let text = values[key];
|
||||
if (!text) { text = ''; }
|
||||
// The value from the server being used to choose which item is
|
||||
// selected is in integer form, so this must be converted.
|
||||
valuesArr.push({value: parseInt(key, 10), text: values[key]});
|
||||
valuesArr.push({value: parseInt(key, 10), text});
|
||||
}
|
||||
return valuesArr;
|
||||
},
|
||||
|
@ -349,6 +349,13 @@ limitations under the License.
|
||||
return this._navigate(this.getUrlForSearchQuery(query, opt_offset));
|
||||
},
|
||||
|
||||
/**
|
||||
* Navigate to the user's dashboard
|
||||
*/
|
||||
navigateToUserDashboard() {
|
||||
return this._navigate(this.getUrlForUserDashboard('self'));
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {!Object} change The change object.
|
||||
* @param {number=} opt_patchNum
|
||||
|
@ -1424,9 +1424,13 @@
|
||||
},
|
||||
|
||||
_handleSettingsLegacyRoute(data) {
|
||||
// email tokens may contain '+' but no space.
|
||||
// The parameter parsing replaces all '+' with a space,
|
||||
// undo that to have valid tokens.
|
||||
const token = data.params[0].replace(/ /g, '+');
|
||||
this._setParams({
|
||||
view: Gerrit.Nav.View.SETTINGS,
|
||||
emailToken: data.params[0],
|
||||
emailToken: token,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -672,6 +672,14 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
test('_handleSettingsLegacyRoute with +', () => {
|
||||
const data = {params: {0: 'my-token test'}};
|
||||
assertDataToParams(data, '_handleSettingsLegacyRoute', {
|
||||
view: Gerrit.Nav.View.SETTINGS,
|
||||
emailToken: 'my-token+test',
|
||||
});
|
||||
});
|
||||
|
||||
test('_handleSettingsRoute', () => {
|
||||
const data = {};
|
||||
assertDataToParams(data, '_handleSettingsRoute', {
|
||||
|
@ -106,9 +106,11 @@
|
||||
keyboardShortcuts() {
|
||||
return {
|
||||
[this.Shortcut.OPEN_SHORTCUT_HELP_DIALOG]: '_showKeyboardShortcuts',
|
||||
[this.Shortcut.GO_TO_USER_DASHBOARD]: '_goToUserDashboard',
|
||||
[this.Shortcut.GO_TO_OPENED_CHANGES]: '_goToOpenedChanges',
|
||||
[this.Shortcut.GO_TO_MERGED_CHANGES]: '_goToMergedChanges',
|
||||
[this.Shortcut.GO_TO_ABANDONED_CHANGES]: '_goToAbandonedChanges',
|
||||
[this.Shortcut.GO_TO_WATCHED_CHANGES]: '_goToWatchedChanges',
|
||||
};
|
||||
},
|
||||
|
||||
@ -172,12 +174,16 @@
|
||||
|
||||
this.bindShortcut(
|
||||
this.Shortcut.OPEN_SHORTCUT_HELP_DIALOG, '?');
|
||||
this.bindShortcut(
|
||||
this.Shortcut.GO_TO_USER_DASHBOARD, this.GO_KEY, 'i');
|
||||
this.bindShortcut(
|
||||
this.Shortcut.GO_TO_OPENED_CHANGES, this.GO_KEY, 'o');
|
||||
this.bindShortcut(
|
||||
this.Shortcut.GO_TO_MERGED_CHANGES, this.GO_KEY, 'm');
|
||||
this.bindShortcut(
|
||||
this.Shortcut.GO_TO_ABANDONED_CHANGES, this.GO_KEY, 'a');
|
||||
this.bindShortcut(
|
||||
this.Shortcut.GO_TO_WATCHED_CHANGES, this.GO_KEY, 'w');
|
||||
|
||||
this.bindShortcut(
|
||||
this.Shortcut.CURSOR_NEXT_CHANGE, 'j');
|
||||
@ -401,6 +407,10 @@
|
||||
Gerrit.Nav.navigateToStatusSearch('open');
|
||||
},
|
||||
|
||||
_goToUserDashboard() {
|
||||
Gerrit.Nav.navigateToUserDashboard();
|
||||
},
|
||||
|
||||
_goToMergedChanges() {
|
||||
Gerrit.Nav.navigateToStatusSearch('merged');
|
||||
},
|
||||
@ -409,6 +419,11 @@
|
||||
Gerrit.Nav.navigateToStatusSearch('abandoned');
|
||||
},
|
||||
|
||||
_goToWatchedChanges() {
|
||||
// The query is hardcoded, and doesn't respect custom menu entries
|
||||
Gerrit.Nav.navigateToSearchQuery('is:watched is:open');
|
||||
},
|
||||
|
||||
_computePluginScreenName({plugin, screen}) {
|
||||
return Gerrit._getPluginScreenName(plugin, screen);
|
||||
},
|
||||
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||
-->
|
||||
|
||||
<link rel="import" href="/bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
|
||||
<link rel="import" href="../../../styles/shared-styles.html">
|
||||
<link rel="import" href="../../../styles/gr-form-styles.html">
|
||||
<link rel="import" href="../../admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.html">
|
||||
@ -48,9 +49,12 @@ limitations under the License.
|
||||
.deleteButton:not(.show) {
|
||||
display: none;
|
||||
}
|
||||
.space {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
<div class="gr-form-styles">
|
||||
<fieldset>
|
||||
<fieldset class="space">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -80,6 +84,13 @@ limitations under the License.
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
<dom-if if="[[_showLinkAnotherIdentity]]">
|
||||
<fieldset>
|
||||
<a href$="[[_computeLinkAnotherIdentity()]]">
|
||||
<gr-button id="linkAnotherIdentity" link>Link Another Identity</gr-button>
|
||||
</a>
|
||||
</fieldset>
|
||||
</dom-if>
|
||||
</div>
|
||||
<gr-overlay id="overlay" with-backdrop>
|
||||
<gr-confirm-delete-item-dialog
|
||||
|
@ -17,6 +17,11 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const AUTH = [
|
||||
'OPENID',
|
||||
'OAUTH',
|
||||
];
|
||||
|
||||
Polymer({
|
||||
is: 'gr-identities',
|
||||
_legacyUndefinedCheck: true,
|
||||
@ -24,8 +29,17 @@
|
||||
properties: {
|
||||
_identities: Object,
|
||||
_idName: String,
|
||||
serverConfig: Object,
|
||||
_showLinkAnotherIdentity: {
|
||||
type: Boolean,
|
||||
computed: '_computeShowLinkAnotherIdentity(serverConfig)',
|
||||
},
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Gerrit.BaseUrlBehavior,
|
||||
],
|
||||
|
||||
loadData() {
|
||||
return this.$.restAPI.getExternalIds().then(id => {
|
||||
this._identities = id;
|
||||
@ -64,5 +78,24 @@
|
||||
filterIdentities(item) {
|
||||
return !item.identity.startsWith('username:');
|
||||
},
|
||||
|
||||
_computeShowLinkAnotherIdentity(config) {
|
||||
if (config && config.auth &&
|
||||
config.auth.git_basic_auth_policy) {
|
||||
return AUTH.includes(
|
||||
config.auth.git_basic_auth_policy.toUpperCase());
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_computeLinkAnotherIdentity() {
|
||||
const baseUrl = this.getBaseUrl() || '';
|
||||
let pathname = window.location.pathname;
|
||||
if (baseUrl) {
|
||||
pathname = '/' + pathname.substring(baseUrl.length);
|
||||
}
|
||||
return baseUrl + '/login/' + encodeURIComponent(pathname) + '?link';
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
@ -124,5 +124,65 @@ limitations under the License.
|
||||
MockInteractions.tap(deleteBtn);
|
||||
assert.isTrue(deleteItem.called);
|
||||
});
|
||||
|
||||
test('_computeShowLinkAnotherIdentity', () => {
|
||||
let serverConfig;
|
||||
|
||||
serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'OAUTH',
|
||||
},
|
||||
};
|
||||
assert.isTrue(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
|
||||
serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'OpenID',
|
||||
},
|
||||
};
|
||||
assert.isTrue(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
|
||||
serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'HTTP_LDAP',
|
||||
},
|
||||
};
|
||||
assert.isFalse(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
|
||||
serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'LDAP',
|
||||
},
|
||||
};
|
||||
assert.isFalse(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
|
||||
serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'HTTP',
|
||||
},
|
||||
};
|
||||
assert.isFalse(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
|
||||
serverConfig = {};
|
||||
assert.isFalse(element._computeShowLinkAnotherIdentity(serverConfig));
|
||||
});
|
||||
|
||||
test('_showLinkAnotherIdentity', () => {
|
||||
element.serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'OAUTH',
|
||||
},
|
||||
};
|
||||
|
||||
assert.isTrue(element._showLinkAnotherIdentity);
|
||||
|
||||
element.serverConfig = {
|
||||
auth: {
|
||||
git_basic_auth_policy: 'LDAP',
|
||||
},
|
||||
};
|
||||
|
||||
assert.isFalse(element._showLinkAnotherIdentity);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -427,7 +427,7 @@ limitations under the License.
|
||||
</fieldset>
|
||||
<h2 id="Identities">Identities</h2>
|
||||
<fieldset>
|
||||
<gr-identities id="identities"></gr-identities>
|
||||
<gr-identities id="identities" server-config="[[_serverConfig]]"></gr-identities>
|
||||
</fieldset>
|
||||
<template is="dom-if" if="[[_serverConfig.auth.use_contributor_agreements]]">
|
||||
<h2 id="Agreements">Agreements</h2>
|
||||
|
@ -397,19 +397,6 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
test('installGwt calls _pluginInstalled', () => {
|
||||
sandbox.stub(Gerrit, '_pluginInstalled');
|
||||
Gerrit.installGwt('http://test.com/plugins/testplugin/static/test.js');
|
||||
assert.isTrue(Gerrit._pluginInstalled.calledOnce);
|
||||
});
|
||||
|
||||
test('installGwt returns a plugin', () => {
|
||||
const plugin = Gerrit.installGwt(
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
assert.isOk(plugin);
|
||||
assert.isOk(plugin._loadedGwt);
|
||||
});
|
||||
|
||||
test('attributeHelper', () => {
|
||||
assert.isOk(plugin.attributeHelper());
|
||||
});
|
||||
|
@ -69,9 +69,9 @@
|
||||
* @return {!Promise}
|
||||
*/
|
||||
GrPluginRestApi.prototype.fetch = function(method, url, opt_payload,
|
||||
opt_errFn) {
|
||||
opt_errFn, opt_contentType) {
|
||||
return getRestApi().send(method, this.opt_prefix + url, opt_payload,
|
||||
opt_errFn);
|
||||
opt_errFn, opt_contentType);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -84,20 +84,21 @@
|
||||
* @return {!Promise} resolves on success, rejects on error.
|
||||
*/
|
||||
GrPluginRestApi.prototype.send = function(method, url, opt_payload,
|
||||
opt_errFn) {
|
||||
return this.fetch(method, url, opt_payload, opt_errFn).then(response => {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
opt_errFn, opt_contentType) {
|
||||
return this.fetch(method, url, opt_payload, opt_errFn, opt_contentType)
|
||||
.then(response => {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
return response.text().then(text => {
|
||||
if (text) {
|
||||
return Promise.reject(text);
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Promise.reject(response.status);
|
||||
return getRestApi().getResponseObject(response);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return getRestApi().getResponseObject(response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -112,16 +113,18 @@
|
||||
* @param {string} url URL without base path or plugin prefix
|
||||
* @return {!Promise} resolves on success, rejects on error.
|
||||
*/
|
||||
GrPluginRestApi.prototype.post = function(url, opt_payload) {
|
||||
return this.send('POST', url, opt_payload);
|
||||
GrPluginRestApi.prototype.post = function(url, opt_payload, opt_errFn,
|
||||
opt_contentType) {
|
||||
return this.send('POST', url, opt_payload, opt_errFn, opt_contentType);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} url URL without base path or plugin prefix
|
||||
* @return {!Promise} resolves on success, rejects on error.
|
||||
*/
|
||||
GrPluginRestApi.prototype.put = function(url, opt_payload) {
|
||||
return this.send('PUT', url, opt_payload);
|
||||
GrPluginRestApi.prototype.put = function(url, opt_payload, opt_errFn,
|
||||
opt_contentType) {
|
||||
return this.send('PUT', url, opt_payload, opt_errFn, opt_contentType);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -99,10 +99,6 @@
|
||||
STYLE: 'style',
|
||||
};
|
||||
|
||||
// GWT JSNI uses $wnd to refer to window.
|
||||
// http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
|
||||
window.$wnd = window;
|
||||
|
||||
function flushPreinstalls() {
|
||||
if (window.Gerrit.flushPreinstalls) {
|
||||
window.Gerrit.flushPreinstalls();
|
||||
@ -607,23 +603,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Install "stepping stones" API for GWT-compiled plugins by default.
|
||||
* @deprecated best effort support, will be removed with GWT UI.
|
||||
*/
|
||||
Gerrit.installGwt = function(url) {
|
||||
const name = getPluginNameFromUrl(url);
|
||||
let plugin;
|
||||
try {
|
||||
plugin = _plugins[name] || new Plugin(url);
|
||||
plugin.deprecated.install();
|
||||
Gerrit._pluginInstalled(url);
|
||||
} catch (e) {
|
||||
Gerrit._pluginInstallError(`${e.name}: ${e.message}`);
|
||||
}
|
||||
return plugin;
|
||||
};
|
||||
|
||||
Gerrit.awaitPluginsLoaded = function() {
|
||||
if (!_allPluginsPromise) {
|
||||
if (Gerrit._arePluginsLoaded()) {
|
||||
|
@ -77,8 +77,8 @@ def _war_impl(ctx):
|
||||
# Add lib
|
||||
transitive_libs = []
|
||||
for j in ctx.attr.libs:
|
||||
if hasattr(j, "java"):
|
||||
transitive_libs.append(j.java.transitive_runtime_deps)
|
||||
if JavaInfo in j:
|
||||
transitive_libs.append(j[JavaInfo].transitive_runtime_deps)
|
||||
elif hasattr(j, "files"):
|
||||
transitive_libs.append(j.files)
|
||||
|
||||
@ -90,7 +90,7 @@ def _war_impl(ctx):
|
||||
# Add pgm lib
|
||||
transitive_pgmlibs = []
|
||||
for j in ctx.attr.pgmlibs:
|
||||
transitive_pgmlibs.append(j.java.transitive_runtime_deps)
|
||||
transitive_pgmlibs.append(j[JavaInfo].transitive_runtime_deps)
|
||||
|
||||
transitive_pgmlib_deps = depset(transitive = transitive_pgmlibs)
|
||||
for dep in transitive_pgmlib_deps.to_list():
|
||||
|
@ -12,17 +12,12 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
# TODO(davido): use Google style for importing instead:
|
||||
# import optparse
|
||||
# ...
|
||||
# optparse.OptionParser
|
||||
from optparse import OptionParser
|
||||
from os import environ, path, makedirs
|
||||
from subprocess import CalledProcessError, check_call, check_output
|
||||
from xml.dom import minidom
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import xml.dom.minidom
|
||||
import re
|
||||
import sys
|
||||
|
||||
@ -39,30 +34,57 @@ cp_targets = {
|
||||
MAIN: '//tools/eclipse:main_classpath_collect',
|
||||
}
|
||||
|
||||
ROOT = path.abspath(__file__)
|
||||
while not path.exists(path.join(ROOT, 'WORKSPACE')):
|
||||
ROOT = path.dirname(ROOT)
|
||||
ROOT = os.path.abspath(__file__)
|
||||
while not os.path.exists(os.path.join(ROOT, 'WORKSPACE')):
|
||||
ROOT = os.path.dirname(ROOT)
|
||||
|
||||
opts = OptionParser()
|
||||
opts.add_option('--plugins', help='create eclipse projects for plugins',
|
||||
action='store_true')
|
||||
opts.add_option('--name', help='name of the generated project',
|
||||
action='store', default='gerrit', dest='project_name')
|
||||
opts.add_option('-b', '--batch', action='store_true',
|
||||
dest='batch', help='Bazel batch option')
|
||||
opts.add_option('-j', '--java', action='store',
|
||||
dest='java', help='Post Java 8 support (9)')
|
||||
opts.add_option('-e', '--edge_java', action='store',
|
||||
dest='edge_java', help='Post Java 9 support (10|11|...)')
|
||||
opts.add_option('--bazel', help='name of the bazel executable',
|
||||
action='store', default='bazel', dest='bazel_exe')
|
||||
opts = argparse.ArgumentParser("Create Eclipse Project")
|
||||
opts.add_argument('--plugins', help='create eclipse projects for plugins',
|
||||
action='store_true')
|
||||
opts.add_argument('--name', help='name of the generated project',
|
||||
action='store', default='gerrit', dest='project_name')
|
||||
opts.add_argument('-b', '--batch', action='store_true',
|
||||
dest='batch', help='Bazel batch option')
|
||||
opts.add_argument('-j', '--java', action='store',
|
||||
dest='java', help='Post Java 8 support (9)')
|
||||
opts.add_argument('-e', '--edge_java', action='store',
|
||||
dest='edge_java', help='Post Java 9 support (10|11|...)')
|
||||
opts.add_argument('--bazel',
|
||||
help=('name of the bazel executable. Defaults to using'
|
||||
' bazelisk if found, or bazel if bazelisk is not'
|
||||
' found.'),
|
||||
action='store', default=None, dest='bazel_exe')
|
||||
|
||||
args = opts.parse_args()
|
||||
|
||||
|
||||
def find_bazel():
|
||||
if args.bazel_exe:
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
['which', args.bazel_exe]).strip().decode('UTF-8')
|
||||
except subprocess.CalledProcessError:
|
||||
print('Bazel command: %s not found' % args.bazel_exe, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
['which', 'bazelisk']).strip().decode('UTF-8')
|
||||
except subprocess.CalledProcessError:
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
['which', 'bazel']).strip().decode('UTF-8')
|
||||
except subprocess.CalledProcessError:
|
||||
print("Neither bazelisk nor bazel found. Please see"
|
||||
" Documentation/dev-bazel for instructions on installing"
|
||||
" one of them.")
|
||||
sys.exit(1)
|
||||
|
||||
args, _ = opts.parse_args()
|
||||
|
||||
batch_option = '--batch' if args.batch else None
|
||||
custom_java = args.java
|
||||
edge_java = args.edge_java
|
||||
bazel_exe = args.bazel_exe
|
||||
bazel_exe = find_bazel()
|
||||
|
||||
|
||||
def _build_bazel_cmd(*args):
|
||||
build = False
|
||||
@ -82,23 +104,23 @@ def _build_bazel_cmd(*args):
|
||||
|
||||
|
||||
def retrieve_ext_location():
|
||||
return check_output(_build_bazel_cmd('info', 'output_base')).strip()
|
||||
return subprocess.check_output(_build_bazel_cmd('info', 'output_base')).strip()
|
||||
|
||||
|
||||
def gen_bazel_path(ext_location):
|
||||
bazel = check_output(['which', bazel_exe]).strip().decode('UTF-8')
|
||||
with open(path.join(ROOT, ".bazel_path"), 'w') as fd:
|
||||
bazel = subprocess.check_output(['which', bazel_exe]).strip().decode('UTF-8')
|
||||
with open(os.path.join(ROOT, ".bazel_path"), 'w') as fd:
|
||||
fd.write("output_base=%s\n" % ext_location)
|
||||
fd.write("bazel=%s\n" % bazel)
|
||||
fd.write("PATH=%s\n" % environ["PATH"])
|
||||
fd.write("PATH=%s\n" % os.environ["PATH"])
|
||||
|
||||
|
||||
def _query_classpath(target):
|
||||
deps = []
|
||||
t = cp_targets[target]
|
||||
try:
|
||||
check_call(_build_bazel_cmd('build', t))
|
||||
except CalledProcessError:
|
||||
subprocess.check_call(_build_bazel_cmd('build', t))
|
||||
except subprocess.CalledProcessError:
|
||||
exit(1)
|
||||
name = 'bazel-bin/tools/eclipse/' + t.split(':')[1] + '.runtime_classpath'
|
||||
deps = [line.rstrip('\n') for line in open(name)]
|
||||
@ -106,7 +128,7 @@ def _query_classpath(target):
|
||||
|
||||
|
||||
def gen_project(name='gerrit', root=ROOT):
|
||||
p = path.join(root, '.project')
|
||||
p = os.path.join(root, '.project')
|
||||
with open(p, 'w') as fd:
|
||||
print("""\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@ -125,9 +147,9 @@ def gen_project(name='gerrit', root=ROOT):
|
||||
|
||||
|
||||
def gen_plugin_classpath(root):
|
||||
p = path.join(root, '.classpath')
|
||||
p = os.path.join(root, '.classpath')
|
||||
with open(p, 'w') as fd:
|
||||
if path.exists(path.join(root, 'src', 'test', 'java')):
|
||||
if os.path.exists(os.path.join(root, 'src', 'test', 'java')):
|
||||
testpath = """
|
||||
<classpathentry excluding="**/BUILD" kind="src" path="src/test/java"\
|
||||
out="eclipse-out/test">
|
||||
@ -147,7 +169,7 @@ def gen_plugin_classpath(root):
|
||||
|
||||
def gen_classpath(ext):
|
||||
def make_classpath():
|
||||
impl = minidom.getDOMImplementation()
|
||||
impl = xml.dom.minidom.getDOMImplementation()
|
||||
return impl.createDocument(None, 'classpath', None)
|
||||
|
||||
def classpathentry(kind, path, src=None, out=None, exported=None):
|
||||
@ -222,7 +244,7 @@ def gen_classpath(ext):
|
||||
"external/bazel_tools/tools/jdk/TestRunner_deploy.jar"):
|
||||
continue
|
||||
if p.startswith("external"):
|
||||
p = path.join(ext, p)
|
||||
p = os.path.join(ext, p)
|
||||
lib.add(p)
|
||||
|
||||
classpathentry('src', 'java')
|
||||
@ -239,11 +261,11 @@ def gen_classpath(ext):
|
||||
continue
|
||||
out = 'eclipse-out/' + s
|
||||
|
||||
p = path.join(s, 'java')
|
||||
if path.exists(p):
|
||||
p = os.path.join(s, 'java')
|
||||
if os.path.exists(p):
|
||||
classpathentry('src', p, out=out + '/main')
|
||||
p = path.join(s, 'javatests')
|
||||
if path.exists(p):
|
||||
p = os.path.join(s, 'javatests')
|
||||
if os.path.exists(p):
|
||||
classpathentry('src', p, out=out + '/test')
|
||||
continue
|
||||
|
||||
@ -255,8 +277,8 @@ def gen_classpath(ext):
|
||||
o = 'eclipse-out/test'
|
||||
|
||||
for srctype in ['java', 'resources']:
|
||||
p = path.join(s, 'src', env, srctype)
|
||||
if path.exists(p):
|
||||
p = os.path.join(s, 'src', env, srctype)
|
||||
if os.path.exists(p):
|
||||
classpathentry('src', p, out=o)
|
||||
|
||||
for libs in [lib]:
|
||||
@ -266,8 +288,8 @@ def gen_classpath(ext):
|
||||
if m:
|
||||
prefix = m.group(1)
|
||||
suffix = m.group(2)
|
||||
p = path.join(prefix, "jar", "%s-src.jar" % suffix)
|
||||
if path.exists(p):
|
||||
p = os.path.join(prefix, "jar", "%s-src.jar" % suffix)
|
||||
if os.path.exists(p):
|
||||
s = p
|
||||
if args.plugins:
|
||||
classpathentry('lib', j, s, exported=True)
|
||||
@ -285,13 +307,13 @@ def gen_classpath(ext):
|
||||
classpathentry('src', '.apt_generated')
|
||||
classpathentry('src', '.apt_generated_tests', out="eclipse-out/test")
|
||||
|
||||
p = path.join(ROOT, '.classpath')
|
||||
p = os.path.join(ROOT, '.classpath')
|
||||
with open(p, 'w') as fd:
|
||||
doc.writexml(fd, addindent='\t', newl='\n', encoding='UTF-8')
|
||||
|
||||
if args.plugins:
|
||||
for plugin in plugins:
|
||||
plugindir = path.join(ROOT, plugin)
|
||||
plugindir = os.path.join(ROOT, plugin)
|
||||
try:
|
||||
gen_project(plugin.replace('plugins/', ""), plugindir)
|
||||
gen_plugin_classpath(plugindir)
|
||||
@ -301,17 +323,17 @@ def gen_classpath(ext):
|
||||
|
||||
|
||||
def gen_factorypath(ext):
|
||||
doc = minidom.getDOMImplementation().createDocument(None, 'factorypath',
|
||||
None)
|
||||
doc = xml.dom.minidom.getDOMImplementation().createDocument(
|
||||
None, 'factorypath', None)
|
||||
for jar in _query_classpath(AUTO):
|
||||
e = doc.createElement('factorypathentry')
|
||||
e.setAttribute('kind', 'EXTJAR')
|
||||
e.setAttribute('id', path.join(ext, jar))
|
||||
e.setAttribute('id', os.path.join(ext, jar))
|
||||
e.setAttribute('enabled', 'true')
|
||||
e.setAttribute('runInBatchMode', 'false')
|
||||
doc.documentElement.appendChild(e)
|
||||
|
||||
p = path.join(ROOT, '.factorypath')
|
||||
p = os.path.join(ROOT, '.factorypath')
|
||||
with open(p, 'w') as fd:
|
||||
doc.writexml(fd, addindent='\t', newl='\n', encoding='UTF-8')
|
||||
|
||||
@ -324,8 +346,8 @@ try:
|
||||
gen_bazel_path(ext_location)
|
||||
|
||||
try:
|
||||
check_call(_build_bazel_cmd('build', MAIN))
|
||||
except CalledProcessError:
|
||||
subprocess.check_call(_build_bazel_cmd('build', MAIN))
|
||||
except subprocess.CalledProcessError:
|
||||
exit(1)
|
||||
except KeyboardInterrupt:
|
||||
print('Interrupted by user', file=sys.stderr)
|
||||
|
Loading…
Reference in New Issue
Block a user