Merge branch 'stable-3.0' into stable-3.1
* stable-3.0: UrlFormatter: Fix Javadoc of getSettingsUrl() Add a separator between blame and the edit icon Remove target=_self from commentlinks Update .mailmap ReceiveCommits: Factor repeated "internal server error" text to a constant Update .mailmap Documentation: Add site-path arg to reindex command Isolate log4j dep Update .mailmap Cancel deprecation of change identifiers FakeGroupAuditService: Make auditEvents final ErrorProne: Increase severity of MutableConstantField to ERROR ConfigUpdatedEvent: Use immutable type in field declaration Add missing slf4j dependencies in BUILD file JGitMetricModule: fix WindowCache miss ration which wasn't reported Revert "JGitMetricModule: Replace anonymous Supplier instances with method references" Suppress generic logging on docker start for ElasticSearch container Replace deprecated OptionParser with ArgumentParser Documentation: Replace plugins list with home page Change-Id: Idae7755cb887a8df60028a96fff0a01d5d637f8a
This commit is contained in:
		
							
								
								
									
										15
									
								
								.mailmap
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								.mailmap
									
									
									
									
									
								
							| @@ -5,6 +5,7 @@ Alex Blewitt <alex.blewitt@gmail.com> | |||||||
| Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex <alex.ryazantsev@gmail.com> | Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex <alex.ryazantsev@gmail.com> | ||||||
| Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex.ryazantsev <alex.ryazantsev@gmail.com> | Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex.ryazantsev <alex.ryazantsev@gmail.com> | ||||||
| Alice Kober-Sotzek <aliceks@google.com>                                                     <aliceks@google.com> | Alice Kober-Sotzek <aliceks@google.com>                                                     <aliceks@google.com> | ||||||
|  | Alexandre Philbert <alexandre.philbert@ericsson.com>                                        <alexandre.philbert@hotmail.com> | ||||||
| Andrew Bonventre <andybons@chromium.org>                                                    <andybons@google.com> | Andrew Bonventre <andybons@chromium.org>                                                    <andybons@google.com> | ||||||
| Becky Siegel <beckysiegel@google.com>                                                       beckysiegel <beckysiegel@google.com> | Becky Siegel <beckysiegel@google.com>                                                       beckysiegel <beckysiegel@google.com> | ||||||
| Ben Rohlfs <brohlfs@google.com>                                                             brohlfs <brohlfs@google.com> | Ben Rohlfs <brohlfs@google.com>                                                             brohlfs <brohlfs@google.com> | ||||||
| @@ -12,6 +13,7 @@ Brad Larson <bklarson@gmail.com> | |||||||
| Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonyericsson.com> | Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonyericsson.com> | ||||||
| Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonymobile.com> | Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonymobile.com> | ||||||
| Carlos Eduardo Baldacin <carloseduardo.baldacin@sonyericsson.com>                           carloseduardo.baldacin <carloseduardo.baldacin@sonyericsson.com> | Carlos Eduardo Baldacin <carloseduardo.baldacin@sonyericsson.com>                           carloseduardo.baldacin <carloseduardo.baldacin@sonyericsson.com> | ||||||
|  | Chad Horohoe <chorohoe@wikimedia.org>                                                       <chadh@wikimedia.org> | ||||||
| Changcheng Xiao <xchangcheng@google.com>                                                    xchangcheng | Changcheng Xiao <xchangcheng@google.com>                                                    xchangcheng | ||||||
| Cheng Ke <chengke.info@gmail.com>                                                           <chengke.info@gmail.com> | Cheng Ke <chengke.info@gmail.com>                                                           <chengke.info@gmail.com> | ||||||
| Dariusz Luksza <dluksza@collab.net>                                                         <dariusz@luksza.org> | Dariusz Luksza <dluksza@collab.net>                                                         <dariusz@luksza.org> | ||||||
| @@ -29,13 +31,17 @@ Edwin Kempin <ekempin@google.com> | |||||||
| Eryk Szymanski <eryksz@gmail.com>                                                           <eryksz@google.com> | Eryk Szymanski <eryksz@gmail.com>                                                           <eryksz@google.com> | ||||||
| Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik@gandaraj.com> | Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik@gandaraj.com> | ||||||
| Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik.luthander@sonyericsson.com> | Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik.luthander@sonyericsson.com> | ||||||
|  | Gerrit Code Review <no-reply@gerritcodereview.com>                                          <noreply-gerritcodereview@google.com> | ||||||
| Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@axis.com> | Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@axis.com> | ||||||
| Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonyericsson.com> | Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonyericsson.com> | ||||||
| Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonymobile.com> | Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonymobile.com> | ||||||
| Han-Wen Nienhuys <hanwen@google.com>                                                        <hanwen@google.com> | Han-Wen Nienhuys <hanwen@google.com>                                                        <hanwen@google.com> | ||||||
|  | Hector Oswaldo Caballero <hector.caballero@ericsson.com>                                    <hector.caballero@ericsson.com> | ||||||
| Hugo Arès <hugo.ares@ericsson.com>                                                          Hugo Ares <hugo.ares@ericsson.com> | Hugo Arès <hugo.ares@ericsson.com>                                                          Hugo Ares <hugo.ares@ericsson.com> | ||||||
|  | Hugo Arès <hugo.ares@ericsson.com>                                                          <hugares@gmail.com> | ||||||
| Jacek Centkowski <jcentkowski@collab.net>                                                   <gemincia.programs@gmail.com> | Jacek Centkowski <jcentkowski@collab.net>                                                   <gemincia.programs@gmail.com> | ||||||
| Jacek Centkowski <jcentkowski@collab.net>                                                   <geminica.programs@gmail.com> | Jacek Centkowski <jcentkowski@collab.net>                                                   <geminica.programs@gmail.com> | ||||||
|  | James E. Blair <jeblair@redhat.com>                                                         <jeblair@hp.com> | ||||||
| Jason Huntley <jhuntley@houghtonassociates.com>                                             jhuntley <jhuntley@houghtonassociates.com> | Jason Huntley <jhuntley@houghtonassociates.com>                                             jhuntley <jhuntley@houghtonassociates.com> | ||||||
| Jiří Engelthaler <EngyCZ@gmail.com>                                                         <engycz@gmail.com> | Jiří Engelthaler <EngyCZ@gmail.com>                                                         <engycz@gmail.com> | ||||||
| Joe Onorato <onoratoj@gmail.com>                                                            <joeo@android.com> | Joe Onorato <onoratoj@gmail.com>                                                            <joeo@android.com> | ||||||
| @@ -49,16 +55,24 @@ Lincoln Oliveira Campos Do Nascimento <lincoln.oliveiracamposdonascimento@sonyer | |||||||
| Luca Milanesio <luca.milanesio@gmail.com>                                                   <luca@gitent-scm.com> | Luca Milanesio <luca.milanesio@gmail.com>                                                   <luca@gitent-scm.com> | ||||||
| Magnus Bäck <magnus.back@axis.com>                                                          <baeck@google.com> | Magnus Bäck <magnus.back@axis.com>                                                          <baeck@google.com> | ||||||
| Magnus Bäck <magnus.back@axis.com>                                                          <magnus.back@sonyericsson.com> | Magnus Bäck <magnus.back@axis.com>                                                          <magnus.back@sonyericsson.com> | ||||||
|  | Marco Miller <marco.miller@ericsson.com>                                                    <marco.mmiller@gmail.com> | ||||||
| Mark Derricutt <mark.derricutt@smxemail.com>                                                <mark@talios.com> | Mark Derricutt <mark.derricutt@smxemail.com>                                                <mark@talios.com> | ||||||
| Martin Fick <mfick@codeaurora.org>                                                          <mogulguy10@gmail.com> | Martin Fick <mfick@codeaurora.org>                                                          <mogulguy10@gmail.com> | ||||||
| Martin Fick <mfick@codeaurora.org>                                                          <mogulguy@yahoo.com> | Martin Fick <mfick@codeaurora.org>                                                          <mogulguy@yahoo.com> | ||||||
|  | Martin Wallgren <martinwa@axis.com>                                                         <martin.wallgren@axis.com> | ||||||
|  | Matthias Sohn <matthias.sohn@sap.com>                                                       <matthias.sohn@gmail.com> | ||||||
| Maxime Guerreiro <maximeg@google.com>                                                       <maximeg@google.com> | Maxime Guerreiro <maximeg@google.com>                                                       <maximeg@google.com> | ||||||
| Michael Zhou <moz@google.com>                                                               <zhoumotongxue008@gmail.com> | Michael Zhou <moz@google.com>                                                               <zhoumotongxue008@gmail.com> | ||||||
|  | Monty Taylor <mordred@inaugust.com>                                                         <monty.taylor@gmail.com> | ||||||
| Mônica Dionísio <monica.dionisio@sonyericsson.com>                                          monica.dionisio <monica.dionisio@sonyericsson.com> | Mônica Dionísio <monica.dionisio@sonyericsson.com>                                          monica.dionisio <monica.dionisio@sonyericsson.com> | ||||||
| Nasser Grainawi <nasser@grainawi.org>                                                       <nasser@codeaurora.org> | Nasser Grainawi <nasser@grainawi.org>                                                       <nasser@codeaurora.org> | ||||||
| Nasser Grainawi <nasser@grainawi.org>                                                       <nasserg@quicinc.com> | Nasser Grainawi <nasser@grainawi.org>                                                       <nasserg@quicinc.com> | ||||||
|  | Orgad Shaneh <orgads@gmail.com>                                                             <orgad.shaneh@audiocodes.com> | ||||||
|  | Paladox <thomasmulhall410@yahoo.com>                                                        <thomasmulhall410@yahoo.com> | ||||||
|  | Patrick Hiesel <hiesel@google.com>                                                          <hiesel@hiesel-macbookpro2.roam.corp.google.com> | ||||||
| Peter Jönsson <peter.joensson@gmail.com>                                                    Peter Jönsson <peter.joensson@gmail.com> | Peter Jönsson <peter.joensson@gmail.com>                                                    Peter Jönsson <peter.joensson@gmail.com> | ||||||
| Rafael Rabelo Silva <rafael.rabelosilva@sonyericsson.com>                                   rafael.rabelosilva <rafael.rabelosilva@sonyericsson.com> | Rafael Rabelo Silva <rafael.rabelosilva@sonyericsson.com>                                   rafael.rabelosilva <rafael.rabelosilva@sonyericsson.com> | ||||||
|  | Réda Housni Alaoui <reda.housnialaoui@gmail.com>                                            <alaoui.rda@gmail.com> | ||||||
| Richard Möhn <richard.moehn@posteo.de>                                                      <richard.moehn@fu-berlin.de> | Richard Möhn <richard.moehn@posteo.de>                                                      <richard.moehn@fu-berlin.de> | ||||||
| Sam Saccone <samccone@google.com>                                                           <samccone@gmail.com> | Sam Saccone <samccone@google.com>                                                           <samccone@gmail.com> | ||||||
| Sam Saccone <samccone@google.com>                                                           <samccone@google.com> | Sam Saccone <samccone@google.com>                                                           <samccone@google.com> | ||||||
| @@ -70,6 +84,7 @@ Shawn Pearce <sop@google.com> | |||||||
| Sixin Li <sixin210@gmail.com>                                                               sixin li <sixin210@gmail.com> | Sixin Li <sixin210@gmail.com>                                                               sixin li <sixin210@gmail.com> | ||||||
| Sven Selberg <svense@axis.com>                                                              <sven.selberg@axis.com> | Sven Selberg <svense@axis.com>                                                              <sven.selberg@axis.com> | ||||||
| Sven Selberg <svense@axis.com>                                                              <sven.selberg@sonymobile.com> | Sven Selberg <svense@axis.com>                                                              <sven.selberg@sonymobile.com> | ||||||
|  | Thomas Dräbing <thomas.draebing@sap.com>                                                    <thomas.draebing@sap.com> | ||||||
| Tom Wang <twang10@gmail.com>                                                                Tom <twang10@gmail.com> | Tom Wang <twang10@gmail.com>                                                                Tom <twang10@gmail.com> | ||||||
| Tomas Westling <thomas.westling@sonyericsson.com>                                           thomas.westling <thomas.westling@sonyericsson.com> | Tomas Westling <thomas.westling@sonyericsson.com>                                           thomas.westling <thomas.westling@sonyericsson.com> | ||||||
| Ulrik Sjölin <ulrik.sjolin@sonyericsson.com>                                                <ulrik.sjolin@gmail.com> | Ulrik Sjölin <ulrik.sjolin@sonyericsson.com>                                                <ulrik.sjolin@gmail.com> | ||||||
|   | |||||||
| @@ -1158,18 +1158,6 @@ Allow blame on side by side diff. If set to false, blame cannot be used. | |||||||
| + | + | ||||||
| Default is true. | Default is true. | ||||||
|  |  | ||||||
| [[change.api.allowedIdentifier]]change.api.allowedIdentifier:: |  | ||||||
| + |  | ||||||
| Change identifier(s) that are allowed on the API. See |  | ||||||
| link:rest-api-changes.html#change-id[Change Id] for more information. |  | ||||||
| + |  | ||||||
| Possible values are `ALL`, `TRIPLET`, `NUMERIC_ID`, `I_HASH`, and |  | ||||||
| `COMMIT_HASH` or any combination of those as a string list. |  | ||||||
| `PROJECT_NUMERIC_ID` is always allowed and doesn't need to be listed |  | ||||||
| explicitly. |  | ||||||
| + |  | ||||||
| Default is `ALL`. |  | ||||||
|  |  | ||||||
| [[change.api.excludeMergeableInChangeInfo]]change.api.excludeMergeableInChangeInfo:: | [[change.api.excludeMergeableInChangeInfo]]change.api.excludeMergeableInChangeInfo:: | ||||||
| + | + | ||||||
| If true, the mergeability bit in | If true, the mergeability bit in | ||||||
|   | |||||||
| @@ -176,649 +176,8 @@ Configuration] | |||||||
| [[other-plugins]] | [[other-plugins]] | ||||||
| == Other Plugins | == Other Plugins | ||||||
|  |  | ||||||
| Besides core plugins there are many other Gerrit plugins available. | Besides core plugins there are many other Gerrit plugins available. This Gerrit home | ||||||
| These plugins are developed and maintained by different parties. | link:https://www.gerritcodereview.com/plugins.html[page for plugins] lists them. | ||||||
| The Gerrit Project doesn't guarantee proper functionality of any of |  | ||||||
| these plugins. |  | ||||||
|  |  | ||||||
| The Gerrit Project doesn't provide binaries for these plugins, but |  | ||||||
| there is one public service that offers the download of pre-built |  | ||||||
| plugin jars: |  | ||||||
|  |  | ||||||
| * link:https://gerrit-ci.gerritforge.com[CI Server from GerritForge] |  | ||||||
|  |  | ||||||
| The following list gives an overview of available plugins, but the |  | ||||||
| list may not be complete. You may discover more plugins on |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/?filter=plugins%252F[ |  | ||||||
| gerrit-review]. |  | ||||||
|  |  | ||||||
| Note that the documentation and configuration links in the list below are |  | ||||||
| to the plugins' master branch. Please refer to the appropriate branch for |  | ||||||
| the Gerrit version you are using. Be aware that in some cases a stable |  | ||||||
| branch might not exist when the master branch is compatible with multiple |  | ||||||
| versions, or the plugin might not be compatible at all with your version. |  | ||||||
|  |  | ||||||
| [[admin-console]] |  | ||||||
| === admin-console |  | ||||||
|  |  | ||||||
| Plugin to provide administrator-only functionality, intended to |  | ||||||
| simplify common administrative tasks. Currently providing user-level |  | ||||||
| information. Also providing access control information by project or |  | ||||||
| project/account. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/admin-console[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/admin-console/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[analytics]] |  | ||||||
| === analytics |  | ||||||
|  |  | ||||||
| Plugin to extract commit and review data from Gerrit projects and |  | ||||||
| expose aggregated metrics over REST and SSH API. |  | ||||||
| Metrics are extracted in JSON format with one record per line, ready to be |  | ||||||
| archived and processed with popular BigData transformation tools such |  | ||||||
| Apache Spark or published and visualized in dashboards. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/analytics[Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/analytics/+doc/master/README.md[Documentation] |  | ||||||
|  |  | ||||||
| [[avatars-external]] |  | ||||||
| === avatars-external |  | ||||||
|  |  | ||||||
| This plugin allows to use an external url to load the avatar images |  | ||||||
| from. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/avatars-external[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/avatars-external/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/avatars-external/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[avatars-gravatar]] |  | ||||||
| === avatars-gravatar |  | ||||||
|  |  | ||||||
| Plugin to display user icons from Gravatar. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/avatars-gravatar[ |  | ||||||
| Project] |  | ||||||
|  |  | ||||||
| [[branch-network]] |  | ||||||
| === branch-network |  | ||||||
|  |  | ||||||
| This plugin allows the rendering of Git repository branch network in a |  | ||||||
| graphical HTML5 Canvas. It is mainly intended to be used as a |  | ||||||
| "project link" in a gitweb configuration. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/branch-network[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/branch-network/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/branch-network/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[changemessage]] |  | ||||||
| === changemessage |  | ||||||
|  |  | ||||||
| This plugin allows to display a static info message on the change screen. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/changemessage[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/changemessage/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Plugin Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/changemessage/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[checks]] |  | ||||||
| === checks |  | ||||||
|  |  | ||||||
| The checks plugin provides a REST API and UI extensions for integrating |  | ||||||
| CI systems with Gerrit. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/checks[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/checks/+doc/master/README.md[ |  | ||||||
| Plugin Documentation] |  | ||||||
|  |  | ||||||
| [[egit]] |  | ||||||
| === egit |  | ||||||
|  |  | ||||||
| This plugin provides extensions for easier usage with EGit. |  | ||||||
|  |  | ||||||
| The plugin adds a download command for EGit that allows to copy only |  | ||||||
| the change ref into the clipboard. The change ref is needed for |  | ||||||
| downloading a Gerrit change from within EGit. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/egit[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/egit/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[emoticons]] |  | ||||||
| === emoticons |  | ||||||
|  |  | ||||||
| This plugin allows users to see emoticons in comments as images. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/emoticons[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/emoticons/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/emoticons/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[find-owners]] |  | ||||||
| === find-owners |  | ||||||
| This plugin provides (1) a change review action button `[FIND OWNERS]` |  | ||||||
| that shows owners of changed files to be included as code reviewers, and |  | ||||||
| (2) Prolog predicates to make sure that a CL is submittable |  | ||||||
| only with owner Code-Review +1 votes. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/find-owners[Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/find-owners/+doc/master/src/main/resources/Documentation/about.md[Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/find-owners/+doc/master/src/main/resources/Documentation/config.md[Configuration] |  | ||||||
|  |  | ||||||
| [[gitblit]] |  | ||||||
| === gitblit |  | ||||||
|  |  | ||||||
| GitBlit code-viewer plugin with SSO and Security Access Control. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/gitblit[ |  | ||||||
| Project] |  | ||||||
|  |  | ||||||
| [[github]] |  | ||||||
| === github |  | ||||||
|  |  | ||||||
| Plugin to integrate with GitHub: replication, pull-request to Change-Sets |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/github[ |  | ||||||
| Project] |  | ||||||
|  |  | ||||||
| [[healthcheck]] |  | ||||||
| === healthcheck |  | ||||||
|  |  | ||||||
| Plugin for monitoring and alerting when Gerrit does not behave properrly. |  | ||||||
|  |  | ||||||
| When Gerrit Server needs to be available 24x7, it is important to know |  | ||||||
| *beforehand* if something isn't working correctly: this plugin exposes a |  | ||||||
| REST-API that provides the real-time status of the Gerrit internals and can |  | ||||||
| be integrated with real-time monitoring systems and paging platforms. |  | ||||||
|  |  | ||||||
| Healthcheck metrics (latency and subsystem healthiness) are published as |  | ||||||
| Gerrit internal metrics and can be published to dashboards. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/healthcheck[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/healthcheck/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/healthcheck/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[imagare]] |  | ||||||
| === imagare |  | ||||||
|  |  | ||||||
| The imagare plugin allows Gerrit users to upload and share images. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/imagare[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/imagare/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/imagare/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[importer]] |  | ||||||
| === importer |  | ||||||
|  |  | ||||||
| The importer plugin allows to import projects from one Gerrit server |  | ||||||
| into another Gerrit server. |  | ||||||
|  |  | ||||||
| Projects can be imported while both source and target Gerrit server |  | ||||||
| are online. There is no downtime required. |  | ||||||
|  |  | ||||||
| The git repository and all changes of the project, including approvals |  | ||||||
| and review comments, are imported. Historic timestamps are preserved. |  | ||||||
|  |  | ||||||
| Project imports can be resumed. This means a project team can continue |  | ||||||
| to work in the source system while the import to the target system is |  | ||||||
| done. By resuming the import the project in the target system can be |  | ||||||
| updated with the missing delta. |  | ||||||
|  |  | ||||||
| The importer plugin can also be used to copy a project within one Gerrit |  | ||||||
| server, and in combination with the link:#delete-project[delete-project] |  | ||||||
| plugin it can be used to rename a project. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/importer[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/importer/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[its-plugins]] |  | ||||||
| === Issue Tracker System Plugins |  | ||||||
|  |  | ||||||
| Plugins to integrate with issue tracker systems (ITS), that (based |  | ||||||
| on events in Gerrit) allows to take actions in the ITS. For example, |  | ||||||
| they can add comments to bugs, or change status of bugs. |  | ||||||
|  |  | ||||||
| All its-plugins have a common base implementation which is stored in |  | ||||||
| the `its-base` project. `its-base` is not a plugin, but just a |  | ||||||
| framework for the ITS plugins which is packaged within each ITS plugin. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-base[ |  | ||||||
| its-base Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-base/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| its-base Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-base/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| its-base Configuration] |  | ||||||
|  |  | ||||||
| [[its-bugzilla]] |  | ||||||
| ==== its-bugzilla |  | ||||||
|  |  | ||||||
| Plugin to integrate with Bugzilla. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-bugzilla[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-bugzilla/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[its-jira]] |  | ||||||
| ==== its-jira |  | ||||||
|  |  | ||||||
| Plugin to integrate with Jira. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-jira[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-jira/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[its-phabricator]] |  | ||||||
| ==== its-phabricator |  | ||||||
|  |  | ||||||
| Plugin to integrate with Phabricator. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-phabricator[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-phabricator/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[its-rtc]] |  | ||||||
| ==== its-rtc |  | ||||||
|  |  | ||||||
| Plugin to integrate with IBM Rational Team Concert (RTC). |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-rtc[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-rtc/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[its-storyboard]] |  | ||||||
| ==== its-storyboard |  | ||||||
|  |  | ||||||
| Plugin to integrate with Storyboard task tracking system. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-storyboard[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/its-storyboard/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[javamelody]] |  | ||||||
| === javamelody |  | ||||||
|  |  | ||||||
| This plugin allows to monitor the Gerrit server. |  | ||||||
|  |  | ||||||
| This plugin integrates JavaMelody in Gerrit in order to retrieve live |  | ||||||
| instrumentation data from Gerrit. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/javamelody[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/javamelody/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| https://gerrit.googlesource.com/plugins/javamelody/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[labelui]] |  | ||||||
| === labelui |  | ||||||
|  |  | ||||||
| The labelui plugin adds a user preference that allows users to choose a |  | ||||||
| table control to render the labels/approvals on the change screen |  | ||||||
| (similar to how labels/approvals were rendered on the old change |  | ||||||
| screen). |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/labelui[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/labelui/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[menuextender]] |  | ||||||
| === menuextender |  | ||||||
|  |  | ||||||
| The menuextender plugin allows Gerrit administrators to configure |  | ||||||
| additional menu entries from the WebUI. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/menuextender[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/menuextender/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/menuextender/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[metrics-reporter-elasticsearch]] |  | ||||||
| === metrics-reporter-elasticsearch |  | ||||||
|  |  | ||||||
| This plugin reports Gerrit metrics to Elasticsearch. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/metrics-reporter-elasticsearch[ |  | ||||||
| Project]. |  | ||||||
|  |  | ||||||
| [[metrics-reporter-graphite]] |  | ||||||
| === metrics-reporter-graphite |  | ||||||
|  |  | ||||||
| This plugin reports Gerrit metrics to Graphite. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/metrics-reporter-graphite[ |  | ||||||
| Project]. |  | ||||||
|  |  | ||||||
| [[metrics-reporter-jmx]] |  | ||||||
| === metrics-reporter-jmx |  | ||||||
|  |  | ||||||
| This plugin reports Gerrit metrics to JMX. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/metrics-reporter-jmx[ |  | ||||||
| Project]. |  | ||||||
|  |  | ||||||
| [[metrics-reporter-prometheus]] |  | ||||||
| === metrics-reporter-prometheus |  | ||||||
|  |  | ||||||
| This plugin exposes Gerrit metrics for consumption by Prometheus. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/metrics-reporter-prometheus[ |  | ||||||
| Project]. |  | ||||||
|  |  | ||||||
| [[motd]] |  | ||||||
| === motd |  | ||||||
|  |  | ||||||
| This plugin can output messages to clients when pulling/fetching/cloning |  | ||||||
| code from Gerrit Code Review. If the client (and transport mechanism) |  | ||||||
| can support sending the message to the client, it will be displayed to |  | ||||||
| the user (usually prefixed by “remote: ”), but will be silently |  | ||||||
| discarded otherwise. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/motd[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/motd/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/motd/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[oauth-authentication-provider]] |  | ||||||
| === OAuth authentication provider |  | ||||||
| This plugin enables Gerrit to use OAuth2 protocol for authentication. |  | ||||||
| Several OAuth2 providers are supported: |  | ||||||
|  |  | ||||||
| * AirVantage |  | ||||||
| * Bitbucket |  | ||||||
| * CAS |  | ||||||
| * CoreOS Dex |  | ||||||
| * Facebook |  | ||||||
| * GitHub |  | ||||||
| * GitLab |  | ||||||
| * Google |  | ||||||
| * Keycloak |  | ||||||
| * Office365 |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/oauth[Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/oauth/+doc/master/src/main/resources/Documentation/config.md[Configuration] |  | ||||||
|  |  | ||||||
| [[owners]] |  | ||||||
| === owners |  | ||||||
| This plugin provides a Prolog predicate `add_owner_approval/3` that |  | ||||||
| appends `label('Owner-Approval', need(_))` to a provided list. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/owners[Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/owners/+doc/master/README.md[Documentation] |  | ||||||
|  |  | ||||||
| [[project-download-commands]] |  | ||||||
| === project-download-commands |  | ||||||
|  |  | ||||||
| This plugin adds support for project specific download commands. |  | ||||||
|  |  | ||||||
| Project specific download commands that are defined on a parent project |  | ||||||
| are inherited by the child projects. Child projects can overwrite the |  | ||||||
| inherited download command or remove it by assigning no value to it. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/project-download-commands[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/project-download-commands/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/project-download-commands/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[quota]] |  | ||||||
| === quota |  | ||||||
|  |  | ||||||
| This plugin allows to enforce quotas in Gerrit. |  | ||||||
|  |  | ||||||
| To protect a Gerrit installation it makes sense to limit the resources |  | ||||||
| that a project or group can consume. To do this a Gerrit administrator |  | ||||||
| can use this plugin to define quotas on project namespaces. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/quota[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/quota/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
| link:https://gerrit.googlesource.com/plugins/quota/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[rabbitmq]] |  | ||||||
| === rabbitmq |  | ||||||
|  |  | ||||||
| A plugin that publishes Gerrit events to a |  | ||||||
| link:https://www.rabbitmq.com/[RabbitMQ] exchange. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/rabbitmq[Project] |  | ||||||
| link:https://gerrit.googlesource.com/plugins/rabbitmq/+/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[readonly]] |  | ||||||
| === readonly |  | ||||||
|  |  | ||||||
| A plugin that makes the Gerrit server read-only by rejecting git pushes, |  | ||||||
| blocking HTTP PUT/POST/DELETE requests, and disabling SSH commands. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/readonly[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/readonly/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/readonly/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[ref-protection]] |  | ||||||
| === ref-protection |  | ||||||
|  |  | ||||||
| A plugin that protects against commits being lost. |  | ||||||
|  |  | ||||||
| Backups of deleted or non-fast-forward updated refs are created under the |  | ||||||
| `refs/backups/` namespace. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/ref-protection[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/ref-protection/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[reparent]] |  | ||||||
| === reparent |  | ||||||
|  |  | ||||||
| A plugin that provides project reparenting as a self-service for project owners. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/reparent[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reparent/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reparent/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[review-strategy]] |  | ||||||
| === review-strategy |  | ||||||
|  |  | ||||||
| This plugin allows users to configure different review strategies. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/review-strategy[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/review-strategy/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[reviewers]] |  | ||||||
| === reviewers |  | ||||||
|  |  | ||||||
| A plugin that allows adding default reviewers to a change. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/reviewers[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reviewers/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reviewers/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[reviewers-by-blame]] |  | ||||||
| === reviewers-by-blame |  | ||||||
|  |  | ||||||
| A plugin that allows automatically adding reviewers to a change from |  | ||||||
| the git blame computation on the changed files. It will add the users |  | ||||||
| that authored most of the lines touched by the change, since these |  | ||||||
| users should be familiar with the code and can mostly review the |  | ||||||
| change. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/reviewers-by-blame[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reviewers-by-blame/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/reviewers-by-blame/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[groovy-provider]] |  | ||||||
| === scripting/groovy-provider |  | ||||||
|  |  | ||||||
| This plugin provides a Groovy runtime environment for Gerrit plugins in Groovy. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/scripting/groovy-provider[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/scripting/groovy-provider/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[saml-authentication-provider]] |  | ||||||
| === SAML2 authentication provider |  | ||||||
|  |  | ||||||
| This plugin enables Gerrit to use SAML2 protocol for authentication. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/saml[Project] |  | ||||||
|  |  | ||||||
| [[scala-provider]] |  | ||||||
| === scripting/scala-provider |  | ||||||
|  |  | ||||||
| This plugin provides a Scala runtime environment for Gerrit plugins in Scala. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/scripting/scala-provider[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/scripting/scala-provider/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] |  | ||||||
|  |  | ||||||
| [[scripts]] |  | ||||||
| === scripts |  | ||||||
|  |  | ||||||
| Repository containing a collection of Gerrit scripting plugins that are intended |  | ||||||
| to provide simple and useful extensions. |  | ||||||
|  |  | ||||||
| Groovy and Scala scripts require the installation of the corresponding |  | ||||||
| scripting/*-provider plugin in order to be loaded into Gerrit. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/scripts[Project] |  | ||||||
| link:https://gerrit.googlesource.com/plugins/scripts/+doc/master/README.md[Documentation] |  | ||||||
|  |  | ||||||
| [[server-config]] |  | ||||||
| === server-config |  | ||||||
|  |  | ||||||
| This plugin enables access (download and upload) to the server config |  | ||||||
| files.  It may be used to change Gerrit config files (like |  | ||||||
| `etc/gerrit.config`) in cases where direct access to the file system |  | ||||||
| where Gerrit's config files are stored is difficult or impossible to |  | ||||||
| get. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/server-config[ |  | ||||||
| Project] |  | ||||||
|  |  | ||||||
| [[serviceuser]] |  | ||||||
| === serviceuser |  | ||||||
|  |  | ||||||
| This plugin allows to create service users in Gerrit. |  | ||||||
|  |  | ||||||
| A service user is a user that is used by another service to communicate |  | ||||||
| with Gerrit. E.g. a service user is needed to run the Gerrit Trigger |  | ||||||
| Plugin in Jenkins. A service user is not able to login into the Gerrit |  | ||||||
| WebUI and it cannot push commits or tags. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/serviceuser[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/serviceuser/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/serviceuser/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[uploadvalidator]] |  | ||||||
| === uploadvalidator |  | ||||||
|  |  | ||||||
| This plugin allows to configure upload validations per project. |  | ||||||
|  |  | ||||||
| Project owners can configure blocked file extensions, required footers |  | ||||||
| and a maximum allowed path length. Pushes of commits that violate these |  | ||||||
| settings are rejected by Gerrit. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/uploadvalidator[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/uploadvalidator/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/uploadvalidator/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[verify-status]] |  | ||||||
| === verify-status |  | ||||||
|  |  | ||||||
| This plugin adds a separate channel for Gerrit to store test metadata and |  | ||||||
| view them on the Gerrit UI.  The metadata can be stored in the Gerrit database |  | ||||||
| or in a completely separate datastore. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/verify-status[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/verify-status/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/verify-status/+doc/master/src/main/resources/Documentation/database.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[websession-flatfile]] |  | ||||||
| === websession-flatfile |  | ||||||
|  |  | ||||||
| This plugin replaces the built-in Gerrit H2 based websession cache with |  | ||||||
| a flatfile based implementation. This implementation is shareable |  | ||||||
| among multiple Gerrit servers, making it useful for cluster |  | ||||||
| Gerrit installations having multiple primary Gerrit nodes. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/websession-flatfile[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/websession-flatfile/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/websession-flatfile/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
| [[x-docs]] |  | ||||||
| === x-docs |  | ||||||
|  |  | ||||||
| This plugin serves project documentation as HTML pages. |  | ||||||
|  |  | ||||||
| link:https://gerrit-review.googlesource.com/admin/repos/plugins/x-docs[ |  | ||||||
| Project] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/x-docs/+doc/master/src/main/resources/Documentation/about.md[ |  | ||||||
| Documentation] | |  | ||||||
| link:https://gerrit.googlesource.com/plugins/x-docs/+doc/master/src/main/resources/Documentation/config.md[ |  | ||||||
| Configuration] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| GERRIT | GERRIT | ||||||
| ------ | ------ | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ reindex - Rebuild the secondary index | |||||||
| [verse] | [verse] | ||||||
| -- | -- | ||||||
| _java_ -jar gerrit.war _reindex_ | _java_ -jar gerrit.war _reindex_ | ||||||
|  |   -d <SITE_PATH> | ||||||
|   [--threads] |   [--threads] | ||||||
|   [--changes-schema-version] |   [--changes-schema-version] | ||||||
|   [--verbose] |   [--verbose] | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
| # See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and | ||||||
| # limitations under the License. | # limitations under the License. | ||||||
|  |  | ||||||
| from optparse import OptionParser | import argparse | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
|  |  | ||||||
| @@ -239,34 +239,34 @@ LINK_SCRIPT = """ | |||||||
|  |  | ||||||
| """ | """ | ||||||
|  |  | ||||||
| opts = OptionParser() | parser = argparse.ArgumentParser() | ||||||
| opts.add_option('-o', '--out', help='output file') | parser.add_argument('-o', '--out', help='output file') | ||||||
| opts.add_option('-s', '--src', help='source file') | parser.add_argument('-s', '--src', help='source file') | ||||||
| opts.add_option('-x', '--suffix', help='suffix for included filenames') | parser.add_argument('-x', '--suffix', help='suffix for included filenames') | ||||||
| opts.add_option('-b', '--searchbox', action="store_true", default=True, | parser.add_argument('-b', '--searchbox', action="store_true", default=True, | ||||||
|                 help="generate the search boxes") |                 help="generate the search boxes") | ||||||
| opts.add_option('--no-searchbox', action="store_false", dest='searchbox', | parser.add_argument('--no-searchbox', action="store_false", dest='searchbox', | ||||||
|                 help="don't generate the search boxes") |                 help="don't generate the search boxes") | ||||||
| opts.add_option('--site-search', action="store", metavar="SITE", | parser.add_argument('--site-search', action="store", metavar="SITE", | ||||||
|                 help=("generate the search box using google. SITE should " + |                 help=("generate the search box using google. SITE should " + | ||||||
|                       "point to the domain/path of the site, eg. " + |                       "point to the domain/path of the site, eg. " + | ||||||
|                       "gerrit-review.googlesource.com/Documentation")) |                       "gerrit-review.googlesource.com/Documentation")) | ||||||
| options, _ = opts.parse_args() | args = parser.parse_args() | ||||||
|  |  | ||||||
| if options.site_search: | if args.site_search: | ||||||
|   SEARCH_BOX = (SEARCH_BOX % |   SEARCH_BOX = (SEARCH_BOX % | ||||||
|                 GOOGLE_SITE_SEARCH.replace("@SITE@", options.site_search)) |                 GOOGLE_SITE_SEARCH.replace("@SITE@", args.site_search)) | ||||||
| else: | else: | ||||||
|   SEARCH_BOX = SEARCH_BOX % BUILTIN_SEARCH |   SEARCH_BOX = SEARCH_BOX % BUILTIN_SEARCH | ||||||
|  |  | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     try: |     try: | ||||||
|         out_file = open(options.out, 'w', errors='ignore') |         out_file = open(args.out, 'w', errors='ignore') | ||||||
|         src_file = open(options.src, 'r', errors='ignore') |         src_file = open(args.src, 'r', errors='ignore') | ||||||
|     except TypeError: |     except TypeError: | ||||||
|         out_file = open(options.out, 'w') |         out_file = open(args.out, 'w') | ||||||
|         src_file = open(options.src, 'r') |         src_file = open(args.src, 'r') | ||||||
|     last_line = '' |     last_line = '' | ||||||
|     ignore_next_line = False |     ignore_next_line = False | ||||||
|     last_title = '' |     last_title = '' | ||||||
| @@ -277,14 +277,14 @@ try: | |||||||
|             last_line = '' |             last_line = '' | ||||||
|         elif PAT_SEARCHBOX.match(last_line): |         elif PAT_SEARCHBOX.match(last_line): | ||||||
|             # Case of 'SEARCHBOX\n---------' |             # Case of 'SEARCHBOX\n---------' | ||||||
|             if options.searchbox: |             if args.searchbox: | ||||||
|                 out_file.write(SEARCH_BOX) |                 out_file.write(SEARCH_BOX) | ||||||
|             last_line = '' |             last_line = '' | ||||||
|         elif PAT_INCLUDE.match(line): |         elif PAT_INCLUDE.match(line): | ||||||
|             # Case of 'include::<filename>' |             # Case of 'include::<filename>' | ||||||
|             match = PAT_INCLUDE.match(line) |             match = PAT_INCLUDE.match(line) | ||||||
|             out_file.write(last_line) |             out_file.write(last_line) | ||||||
|             last_line = match.group(1) + options.suffix + match.group(2) + '\n' |             last_line = match.group(1) + args.suffix + match.group(2) + '\n' | ||||||
|         elif PAT_STARS.match(line): |         elif PAT_STARS.match(line): | ||||||
|             if PAT_TITLE.match(last_line): |             if PAT_TITLE.match(last_line): | ||||||
|                 # Case of the title in '.<title>\n****\nget::<url>\n****' |                 # Case of the title in '.<title>\n****\nget::<url>\n****' | ||||||
| @@ -310,5 +310,5 @@ try: | |||||||
|     out_file.close() |     out_file.close() | ||||||
| except IOError as err: | except IOError as err: | ||||||
|     sys.stderr.write( |     sys.stderr.write( | ||||||
|         "error while expanding %s to %s: %s" % (options.src, options.out, err)) |         "error while expanding %s to %s: %s" % (args.src, args.out, err)) | ||||||
|     exit(1) |     exit(1) | ||||||
|   | |||||||
| @@ -5557,8 +5557,7 @@ In this case, use a POST request instead: | |||||||
| Identifier that uniquely identifies one change. It contains the URL-encoded | Identifier that uniquely identifies one change. It contains the URL-encoded | ||||||
| project name as well as the change number: "'$$<project>~<numericId>$$'" | project name as well as the change number: "'$$<project>~<numericId>$$'" | ||||||
|  |  | ||||||
| Depending on the server's configuration, Gerrit can still support the following | Gerrit also supports the following identifiers: | ||||||
| deprecated identifiers. These will be removed in a future release: |  | ||||||
|  |  | ||||||
| * an ID of the change in the format "'$$<project>~<branch>~<Change-Id>$$'", | * an ID of the change in the format "'$$<project>~<branch>~<Change-Id>$$'", | ||||||
|   where for the branch the `refs/heads/` prefix can be omitted |   where for the branch the `refs/heads/` prefix can be omitted | ||||||
| @@ -5567,10 +5566,6 @@ deprecated identifiers. These will be removed in a future release: | |||||||
|   ("I8473b95934b5732ac55d26311a706c9c2bde9940") |   ("I8473b95934b5732ac55d26311a706c9c2bde9940") | ||||||
| * a numeric change ID ("4247") | * a numeric change ID ("4247") | ||||||
|  |  | ||||||
| If you need more time to migrate off of old change IDs, please see |  | ||||||
| link:config-gerrit.html#change.api.allowedIdentifier[change.api.allowedIdentifier] |  | ||||||
| for more information on how to enable the use of deprecated identifiers. |  | ||||||
|  |  | ||||||
| [[change-message-id]] | [[change-message-id]] | ||||||
| === \{change-message-id\} | === \{change-message-id\} | ||||||
| ID of a change message returned in a link:#change-message-info[ChangeMessageInfo]. | ID of a change message returned in a link:#change-message-info[ChangeMessageInfo]. | ||||||
|   | |||||||
| @@ -22,9 +22,9 @@ TODO(hiesel): Add comments | |||||||
| """ | """ | ||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
|  | import argparse | ||||||
| import atexit | import atexit | ||||||
| import json | import json | ||||||
| import optparse |  | ||||||
| import os | import os | ||||||
| import random | import random | ||||||
| import shutil | import shutil | ||||||
| @@ -275,22 +275,22 @@ def clean_up(): | |||||||
|  |  | ||||||
|  |  | ||||||
| def main(): | def main(): | ||||||
|     p = optparse.OptionParser() |     p = argparse.ArgumentParser() | ||||||
|     p.add_option("-u", "--user_count", action="store", |     p.add_argument("-u", "--user_count", action="store", | ||||||
|                  default=100, |                  default=100, | ||||||
|                  type='int', |                  type=int, | ||||||
|                  help="number of users to generate") |                  help="number of users to generate") | ||||||
|     p.add_option("-p", "--port", action="store", |     p.add_argument("-p", "--port", action="store", | ||||||
|                  default=8080, |                  default=8080, | ||||||
|                  type='int', |                  type=int, | ||||||
|                  help="port of server") |                  help="port of server") | ||||||
|     (options, _) = p.parse_args() |     args = p.parse_args() | ||||||
|     global BASE_URL |     global BASE_URL | ||||||
|     BASE_URL = BASE_URL % options.port |     BASE_URL = BASE_URL % args.port | ||||||
|     print(BASE_URL) |     print(BASE_URL) | ||||||
|  |  | ||||||
|     set_up() |     set_up() | ||||||
|     gerrit_users = get_random_users(options.user_count) |     gerrit_users = get_random_users(args.user_count) | ||||||
|  |  | ||||||
|     group_names = create_gerrit_groups() |     group_names = create_gerrit_groups() | ||||||
|     for idx, u in enumerate(gerrit_users): |     for idx, u in enumerate(gerrit_users): | ||||||
|   | |||||||
| @@ -1,25 +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.extensions.restapi; |  | ||||||
|  |  | ||||||
| /** Named resource was accessed using a deprecated identifier. */ |  | ||||||
| public class DeprecatedIdentifierException extends BadRequestException { |  | ||||||
|   private static final long serialVersionUID = 1L; |  | ||||||
|  |  | ||||||
|   /** Requested resource using a deprecated identifier. */ |  | ||||||
|   public DeprecatedIdentifierException(String msg) { |  | ||||||
|     super(msg); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @@ -14,6 +14,7 @@ | |||||||
|  |  | ||||||
| package com.google.gerrit.metrics.proc; | package com.google.gerrit.metrics.proc; | ||||||
|  |  | ||||||
|  | import com.google.common.base.Supplier; | ||||||
| import com.google.gerrit.metrics.CallbackMetric1; | import com.google.gerrit.metrics.CallbackMetric1; | ||||||
| import com.google.gerrit.metrics.Description; | import com.google.gerrit.metrics.Description; | ||||||
| import com.google.gerrit.metrics.Description.Units; | import com.google.gerrit.metrics.Description.Units; | ||||||
| @@ -34,13 +35,23 @@ public class JGitMetricModule extends MetricModule { | |||||||
|         new Description("Bytes of memory retained in JGit block cache.") |         new Description("Bytes of memory retained in JGit block cache.") | ||||||
|             .setGauge() |             .setGauge() | ||||||
|             .setUnit(Units.BYTES), |             .setUnit(Units.BYTES), | ||||||
|         WindowCacheStats.getStats()::getOpenByteCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getOpenByteCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/open_files", |         "jgit/block_cache/open_files", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("File handles held open by JGit block cache.").setGauge().setUnit("fds"), |         new Description("File handles held open by JGit block cache.").setGauge().setUnit("fds"), | ||||||
|         WindowCacheStats.getStats()::getOpenFileCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getOpenFileCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/avg_load_time", |         "jgit/block_cache/avg_load_time", | ||||||
| @@ -48,61 +59,110 @@ public class JGitMetricModule extends MetricModule { | |||||||
|         new Description("Average time to load a cache entry for JGit block cache.") |         new Description("Average time to load a cache entry for JGit block cache.") | ||||||
|             .setGauge() |             .setGauge() | ||||||
|             .setUnit(Units.NANOSECONDS), |             .setUnit(Units.NANOSECONDS), | ||||||
|         WindowCacheStats.getStats()::getAverageLoadTime); |         new Supplier<Double>() { | ||||||
|  |           @Override | ||||||
|  |           public Double get() { | ||||||
|  |             return WindowCacheStats.getStats().getAverageLoadTime(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/eviction_count", |         "jgit/block_cache/eviction_count", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("Cache evictions for JGit block cache.").setGauge(), |         new Description("Cache evictions for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getEvictionCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getEvictionCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/eviction_ratio", |         "jgit/block_cache/eviction_ratio", | ||||||
|         Double.class, |         Double.class, | ||||||
|         new Description("Cache eviction ratio for JGit block cache.").setGauge(), |         new Description("Cache eviction ratio for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getEvictionRatio); |         new Supplier<Double>() { | ||||||
|  |           @Override | ||||||
|  |           public Double get() { | ||||||
|  |             return WindowCacheStats.getStats().getEvictionRatio(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/hit_count", |         "jgit/block_cache/hit_count", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("Cache hits for JGit block cache.").setGauge(), |         new Description("Cache hits for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getHitCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getHitCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/hit_ratio", |         "jgit/block_cache/hit_ratio", | ||||||
|         Double.class, |         Double.class, | ||||||
|         new Description("Cache hit ratio for JGit block cache.").setGauge(), |         new Description("Cache hit ratio for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getHitRatio); |         new Supplier<Double>() { | ||||||
|  |           @Override | ||||||
|  |           public Double get() { | ||||||
|  |             return WindowCacheStats.getStats().getHitRatio(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/load_failure_count", |         "jgit/block_cache/load_failure_count", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("Failed cache loads for JGit block cache.").setGauge(), |         new Description("Failed cache loads for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getLoadFailureCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getLoadFailureCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/load_failure_ratio", |         "jgit/block_cache/load_failure_ratio", | ||||||
|         Double.class, |         Double.class, | ||||||
|         new Description("Failed cache load ratio for JGit block cache.").setGauge(), |         new Description("Failed cache load ratio for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getLoadFailureRatio); |         new Supplier<Double>() { | ||||||
|  |           @Override | ||||||
|  |           public Double get() { | ||||||
|  |             return WindowCacheStats.getStats().getLoadFailureRatio(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/load_success_count", |         "jgit/block_cache/load_success_count", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("Successfull cache loads for JGit block cache.").setGauge(), |         new Description("Successfull cache loads for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getLoadSuccessCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getLoadSuccessCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/miss_count", |         "jgit/block_cache/miss_count", | ||||||
|         Long.class, |         Long.class, | ||||||
|         new Description("Cache misses for JGit block cache.").setGauge(), |         new Description("Cache misses for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getMissCount); |         new Supplier<Long>() { | ||||||
|  |           @Override | ||||||
|  |           public Long get() { | ||||||
|  |             return WindowCacheStats.getStats().getMissCount(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     metrics.newCallbackMetric( |     metrics.newCallbackMetric( | ||||||
|         "jgit/block_cache/miss_ratio", |         "jgit/block_cache/miss_ratio", | ||||||
|         Double.class, |         Double.class, | ||||||
|         new Description("Cache miss ratio for JGit block cache.").setGauge(), |         new Description("Cache miss ratio for JGit block cache.").setGauge(), | ||||||
|         WindowCacheStats.getStats()::getMissRatio); |         new Supplier<Double>() { | ||||||
|  |           @Override | ||||||
|  |           public Double get() { | ||||||
|  |             return WindowCacheStats.getStats().getMissRatio(); | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|     CallbackMetric1<String, Long> repoEnt = |     CallbackMetric1<String, Long> repoEnt = | ||||||
|         metrics.newCallbackMetric( |         metrics.newCallbackMetric( | ||||||
|   | |||||||
| @@ -10,10 +10,10 @@ java_library( | |||||||
|         "//java/com/google/gerrit/lifecycle", |         "//java/com/google/gerrit/lifecycle", | ||||||
|         "//java/com/google/gerrit/metrics", |         "//java/com/google/gerrit/metrics", | ||||||
|         "//java/com/google/gerrit/server", |         "//java/com/google/gerrit/server", | ||||||
|         "//java/com/google/gerrit/server/logging", |  | ||||||
|         "//java/com/google/gerrit/server/util/time", |         "//java/com/google/gerrit/server/util/time", | ||||||
|         "//java/com/google/gerrit/sshd", |         "//java/com/google/gerrit/sshd", | ||||||
|         "//java/com/google/gerrit/util/http", |         "//java/com/google/gerrit/util/http", | ||||||
|  |         "//java/com/google/gerrit/util/logging", | ||||||
|         "//lib:gson", |         "//lib:gson", | ||||||
|         "//lib:guava", |         "//lib:guava", | ||||||
|         "//lib:jgit", |         "//lib:jgit", | ||||||
|   | |||||||
| @@ -24,8 +24,8 @@ import static com.google.gerrit.pgm.http.jetty.HttpLog.P_STATUS; | |||||||
| import static com.google.gerrit.pgm.http.jetty.HttpLog.P_USER; | import static com.google.gerrit.pgm.http.jetty.HttpLog.P_USER; | ||||||
| import static com.google.gerrit.pgm.http.jetty.HttpLog.P_USER_AGENT; | import static com.google.gerrit.pgm.http.jetty.HttpLog.P_USER_AGENT; | ||||||
|  |  | ||||||
| import com.google.gerrit.server.logging.JsonLayout; | import com.google.gerrit.util.logging.JsonLayout; | ||||||
| import com.google.gerrit.server.logging.JsonLogEntry; | import com.google.gerrit.util.logging.JsonLogEntry; | ||||||
| import java.time.format.DateTimeFormatter; | import java.time.format.DateTimeFormatter; | ||||||
| import org.apache.log4j.spi.LoggingEvent; | import org.apache.log4j.spi.LoggingEvent; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,13 +17,11 @@ package com.google.gerrit.server.change; | |||||||
| import com.google.common.base.Throwables; | import com.google.common.base.Throwables; | ||||||
| import com.google.common.cache.Cache; | import com.google.common.cache.Cache; | ||||||
| import com.google.common.collect.ImmutableList; | import com.google.common.collect.ImmutableList; | ||||||
| import com.google.common.collect.ImmutableSet; |  | ||||||
| import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||||
| import com.google.common.primitives.Ints; | import com.google.common.primitives.Ints; | ||||||
| import com.google.gerrit.entities.Change; | import com.google.gerrit.entities.Change; | ||||||
| import com.google.gerrit.entities.Project; | import com.google.gerrit.entities.Project; | ||||||
| import com.google.gerrit.exceptions.StorageException; | import com.google.gerrit.exceptions.StorageException; | ||||||
| import com.google.gerrit.extensions.restapi.DeprecatedIdentifierException; |  | ||||||
| import com.google.gerrit.extensions.restapi.Url; | import com.google.gerrit.extensions.restapi.Url; | ||||||
| import com.google.gerrit.git.ObjectIds; | import com.google.gerrit.git.ObjectIds; | ||||||
| import com.google.gerrit.index.IndexConfig; | import com.google.gerrit.index.IndexConfig; | ||||||
| @@ -32,8 +30,6 @@ import com.google.gerrit.metrics.Description; | |||||||
| import com.google.gerrit.metrics.Field; | import com.google.gerrit.metrics.Field; | ||||||
| import com.google.gerrit.metrics.MetricMaker; | import com.google.gerrit.metrics.MetricMaker; | ||||||
| import com.google.gerrit.server.cache.CacheModule; | import com.google.gerrit.server.cache.CacheModule; | ||||||
| import com.google.gerrit.server.config.ConfigUtil; |  | ||||||
| import com.google.gerrit.server.config.GerritServerConfig; |  | ||||||
| import com.google.gerrit.server.logging.Metadata; | import com.google.gerrit.server.logging.Metadata; | ||||||
| import com.google.gerrit.server.notedb.ChangeNotes; | import com.google.gerrit.server.notedb.ChangeNotes; | ||||||
| import com.google.gerrit.server.project.NoSuchChangeException; | import com.google.gerrit.server.project.NoSuchChangeException; | ||||||
| @@ -50,7 +46,6 @@ import java.util.List; | |||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import org.eclipse.jgit.errors.RepositoryNotFoundException; | import org.eclipse.jgit.errors.RepositoryNotFoundException; | ||||||
| import org.eclipse.jgit.lib.Config; |  | ||||||
|  |  | ||||||
| @Singleton | @Singleton | ||||||
| public class ChangeFinder { | public class ChangeFinder { | ||||||
| @@ -79,7 +74,6 @@ public class ChangeFinder { | |||||||
|   private final Provider<InternalChangeQuery> queryProvider; |   private final Provider<InternalChangeQuery> queryProvider; | ||||||
|   private final ChangeNotes.Factory changeNotesFactory; |   private final ChangeNotes.Factory changeNotesFactory; | ||||||
|   private final Counter1<ChangeIdType> changeIdCounter; |   private final Counter1<ChangeIdType> changeIdCounter; | ||||||
|   private final ImmutableSet<ChangeIdType> allowedIdTypes; |  | ||||||
|  |  | ||||||
|   @Inject |   @Inject | ||||||
|   ChangeFinder( |   ChangeFinder( | ||||||
| @@ -87,8 +81,7 @@ public class ChangeFinder { | |||||||
|       @Named(CACHE_NAME) Cache<Change.Id, String> changeIdProjectCache, |       @Named(CACHE_NAME) Cache<Change.Id, String> changeIdProjectCache, | ||||||
|       Provider<InternalChangeQuery> queryProvider, |       Provider<InternalChangeQuery> queryProvider, | ||||||
|       ChangeNotes.Factory changeNotesFactory, |       ChangeNotes.Factory changeNotesFactory, | ||||||
|       MetricMaker metricMaker, |       MetricMaker metricMaker) { | ||||||
|       @GerritServerConfig Config config) { |  | ||||||
|     this.indexConfig = indexConfig; |     this.indexConfig = indexConfig; | ||||||
|     this.changeIdProjectCache = changeIdProjectCache; |     this.changeIdProjectCache = changeIdProjectCache; | ||||||
|     this.queryProvider = queryProvider; |     this.queryProvider = queryProvider; | ||||||
| @@ -101,11 +94,6 @@ public class ChangeFinder { | |||||||
|                 .setUnit("requests"), |                 .setUnit("requests"), | ||||||
|             Field.ofEnum(ChangeIdType.class, "change_id_type", Metadata.Builder::changeIdType) |             Field.ofEnum(ChangeIdType.class, "change_id_type", Metadata.Builder::changeIdType) | ||||||
|                 .build()); |                 .build()); | ||||||
|     List<ChangeIdType> configuredChangeIdTypes = |  | ||||||
|         ConfigUtil.getEnumList(config, "change", "api", "allowedIdentifier", ChangeIdType.ALL); |  | ||||||
|     // Ensure that PROJECT_NUMERIC_ID can't be removed |  | ||||||
|     configuredChangeIdTypes.add(ChangeIdType.PROJECT_NUMERIC_ID); |  | ||||||
|     this.allowedIdTypes = ImmutableSet.copyOf(configuredChangeIdTypes); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public ChangeNotes findOne(String id) { |   public ChangeNotes findOne(String id) { | ||||||
| @@ -123,25 +111,6 @@ public class ChangeFinder { | |||||||
|    * @return possibly-empty list of notes for all matching changes; may or may not be visible. |    * @return possibly-empty list of notes for all matching changes; may or may not be visible. | ||||||
|    */ |    */ | ||||||
|   public List<ChangeNotes> find(String id) { |   public List<ChangeNotes> find(String id) { | ||||||
|     try { |  | ||||||
|       return find(id, false); |  | ||||||
|     } catch (DeprecatedIdentifierException e) { |  | ||||||
|       // This can't happen because we don't enforce deprecation |  | ||||||
|       throw new StorageException(e); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Find changes matching the given identifier. |  | ||||||
|    * |  | ||||||
|    * @param id change identifier. |  | ||||||
|    * @param enforceDeprecation boolean to see if we should throw {@link |  | ||||||
|    *     DeprecatedIdentifierException} in case the identifier is deprecated |  | ||||||
|    * @return possibly-empty list of notes for all matching changes; may or may not be visible. |  | ||||||
|    * @throws DeprecatedIdentifierException if the identifier is deprecated. |  | ||||||
|    */ |  | ||||||
|   public List<ChangeNotes> find(String id, boolean enforceDeprecation) |  | ||||||
|       throws DeprecatedIdentifierException { |  | ||||||
|     if (id.isEmpty()) { |     if (id.isEmpty()) { | ||||||
|       return Collections.emptyList(); |       return Collections.emptyList(); | ||||||
|     } |     } | ||||||
| @@ -152,7 +121,7 @@ public class ChangeFinder { | |||||||
|       // Try project~numericChangeId |       // Try project~numericChangeId | ||||||
|       Integer n = Ints.tryParse(id.substring(z + 1)); |       Integer n = Ints.tryParse(id.substring(z + 1)); | ||||||
|       if (n != null) { |       if (n != null) { | ||||||
|         checkIdType(ChangeIdType.PROJECT_NUMERIC_ID, enforceDeprecation, n.toString()); |         changeIdCounter.increment(ChangeIdType.PROJECT_NUMERIC_ID); | ||||||
|         return fromProjectNumber(id.substring(0, z), n.intValue()); |         return fromProjectNumber(id.substring(0, z), n.intValue()); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -161,7 +130,7 @@ public class ChangeFinder { | |||||||
|       // Try numeric changeId |       // Try numeric changeId | ||||||
|       Integer n = Ints.tryParse(id); |       Integer n = Ints.tryParse(id); | ||||||
|       if (n != null) { |       if (n != null) { | ||||||
|         checkIdType(ChangeIdType.NUMERIC_ID, enforceDeprecation, n.toString()); |         changeIdCounter.increment(ChangeIdType.NUMERIC_ID); | ||||||
|         return find(Change.id(n)); |         return find(Change.id(n)); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -172,7 +141,7 @@ public class ChangeFinder { | |||||||
|  |  | ||||||
|     // Try commit hash |     // Try commit hash | ||||||
|     if (id.matches("^([0-9a-fA-F]{" + ObjectIds.ABBREV_STR_LEN + "," + ObjectIds.STR_LEN + "})$")) { |     if (id.matches("^([0-9a-fA-F]{" + ObjectIds.ABBREV_STR_LEN + "," + ObjectIds.STR_LEN + "})$")) { | ||||||
|       checkIdType(ChangeIdType.COMMIT_HASH, enforceDeprecation, id); |       changeIdCounter.increment(ChangeIdType.COMMIT_HASH); | ||||||
|       return asChangeNotes(query.byCommit(id)); |       return asChangeNotes(query.byCommit(id)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -181,7 +150,7 @@ public class ChangeFinder { | |||||||
|       Optional<ChangeTriplet> triplet = ChangeTriplet.parse(id, y, z); |       Optional<ChangeTriplet> triplet = ChangeTriplet.parse(id, y, z); | ||||||
|       if (triplet.isPresent()) { |       if (triplet.isPresent()) { | ||||||
|         ChangeTriplet t = triplet.get(); |         ChangeTriplet t = triplet.get(); | ||||||
|         checkIdType(ChangeIdType.TRIPLET, enforceDeprecation, triplet.get().toString()); |         changeIdCounter.increment(ChangeIdType.TRIPLET); | ||||||
|         return asChangeNotes(query.byBranchKey(t.branch(), t.id())); |         return asChangeNotes(query.byBranchKey(t.branch(), t.id())); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -189,7 +158,7 @@ public class ChangeFinder { | |||||||
|     // Try isolated Ihash... format ("Change-Id: Ihash"). |     // Try isolated Ihash... format ("Change-Id: Ihash"). | ||||||
|     List<ChangeNotes> notes = asChangeNotes(query.byKeyPrefix(id)); |     List<ChangeNotes> notes = asChangeNotes(query.byKeyPrefix(id)); | ||||||
|     if (!notes.isEmpty()) { |     if (!notes.isEmpty()) { | ||||||
|       checkIdType(ChangeIdType.I_HASH, enforceDeprecation, id); |       changeIdCounter.increment(ChangeIdType.I_HASH); | ||||||
|     } |     } | ||||||
|     return notes; |     return notes; | ||||||
|   } |   } | ||||||
| @@ -258,18 +227,4 @@ public class ChangeFinder { | |||||||
|     } |     } | ||||||
|     return notes; |     return notes; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private void checkIdType(ChangeIdType type, boolean enforceDeprecation, String val) |  | ||||||
|       throws DeprecatedIdentifierException { |  | ||||||
|     if (enforceDeprecation |  | ||||||
|         && !allowedIdTypes.contains(ChangeIdType.ALL) |  | ||||||
|         && !allowedIdTypes.contains(type)) { |  | ||||||
|       throw new DeprecatedIdentifierException( |  | ||||||
|           String.format( |  | ||||||
|               "The provided change identifier %s is deprecated. " |  | ||||||
|                   + "Use 'project~changeNumber' instead.", |  | ||||||
|               val)); |  | ||||||
|     } |  | ||||||
|     changeIdCounter.increment(type); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -60,7 +60,7 @@ public interface UrlFormatter { | |||||||
|         .map(url -> url + String.format("@%s%d", side == 0 ? "a" : "", startLine)); |         .map(url -> url + String.format("@%s%d", side == 0 ? "a" : "", startLine)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** Returns a URL pointing to a section of the settings page. */ |   /** Returns a URL pointing to the settings page. */ | ||||||
|   default Optional<String> getSettingsUrl() { |   default Optional<String> getSettingsUrl() { | ||||||
|     return getWebUrl().map(url -> url + "settings"); |     return getWebUrl().map(url -> url + "settings"); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -242,6 +242,7 @@ class ReceiveCommits { | |||||||
|   private static final String CANNOT_DELETE_CHANGES = "Cannot delete from '" + REFS_CHANGES + "'"; |   private static final String CANNOT_DELETE_CHANGES = "Cannot delete from '" + REFS_CHANGES + "'"; | ||||||
|   private static final String CANNOT_DELETE_CONFIG = |   private static final String CANNOT_DELETE_CONFIG = | ||||||
|       "Cannot delete project configuration from '" + RefNames.REFS_CONFIG + "'"; |       "Cannot delete project configuration from '" + RefNames.REFS_CONFIG + "'"; | ||||||
|  |   private static final String INTERNAL_SERVER_ERROR = "internal server error"; | ||||||
|  |  | ||||||
|   interface Factory { |   interface Factory { | ||||||
|     ReceiveCommits create( |     ReceiveCommits create( | ||||||
| @@ -582,7 +583,7 @@ class ReceiveCommits { | |||||||
|       commands = |       commands = | ||||||
|           commands.stream().map(c -> wrapReceiveCommand(c, commandProgress)).collect(toList()); |           commands.stream().map(c -> wrapReceiveCommand(c, commandProgress)).collect(toList()); | ||||||
|       processCommandsUnsafe(commands, progress); |       processCommandsUnsafe(commands, progress); | ||||||
|       rejectRemaining(commands, "internal server error"); |       rejectRemaining(commands, INTERNAL_SERVER_ERROR); | ||||||
|  |  | ||||||
|       // This sends error messages before the 'done' string of the progress monitor is sent. |       // This sends error messages before the 'done' string of the progress monitor is sent. | ||||||
|       // Currently, the test framework relies on this ordering to understand if pushes completed |       // Currently, the test framework relies on this ordering to understand if pushes completed | ||||||
| @@ -710,7 +711,7 @@ class ReceiveCommits { | |||||||
|         logger.atFine().log("Added %d additional ref updates", added); |         logger.atFine().log("Added %d additional ref updates", added); | ||||||
|         bu.execute(); |         bu.execute(); | ||||||
|       } catch (UpdateException | RestApiException e) { |       } catch (UpdateException | RestApiException e) { | ||||||
|         rejectRemaining(cmds, "internal server error"); |         rejectRemaining(cmds, INTERNAL_SERVER_ERROR); | ||||||
|         logger.atFine().withCause(e).log("update failed:"); |         logger.atFine().withCause(e).log("update failed:"); | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -946,7 +947,7 @@ class ReceiveCommits { | |||||||
|       } catch (RestApiException | IOException e) { |       } catch (RestApiException | IOException e) { | ||||||
|         logger.atSevere().withCause(e).log( |         logger.atSevere().withCause(e).log( | ||||||
|             "Can't insert change/patch set for %s", project.getName()); |             "Can't insert change/patch set for %s", project.getName()); | ||||||
|         reject(magicBranchCmd, "internal server error: " + e.getMessage()); |         reject(magicBranchCmd, String.format("%s: %s", INTERNAL_SERVER_ERROR, e.getMessage())); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (magicBranch != null && magicBranch.submit) { |       if (magicBranch != null && magicBranch.submit) { | ||||||
| @@ -1886,7 +1887,7 @@ class ReceiveCommits { | |||||||
|             } catch (IOException e) { |             } catch (IOException e) { | ||||||
|               logger.atWarning().withCause(e).log( |               logger.atWarning().withCause(e).log( | ||||||
|                   "Project %s cannot read %s", project.getName(), id.name()); |                   "Project %s cannot read %s", project.getName(), id.name()); | ||||||
|               reject(cmd, "internal server error"); |               reject(cmd, INTERNAL_SERVER_ERROR); | ||||||
|               return; |               return; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| @@ -1912,7 +1913,7 @@ class ReceiveCommits { | |||||||
|       } catch (IOException ex) { |       } catch (IOException ex) { | ||||||
|         logger.atWarning().withCause(ex).log( |         logger.atWarning().withCause(ex).log( | ||||||
|             "Error walking to %s in project %s", destBranch, project.getName()); |             "Error walking to %s in project %s", destBranch, project.getName()); | ||||||
|         reject(cmd, "internal server error"); |         reject(cmd, INTERNAL_SERVER_ERROR); | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  |  | ||||||
| @@ -2329,7 +2330,7 @@ class ReceiveCommits { | |||||||
|         logger.atFine().log("Finished updating groups from GroupCollector"); |         logger.atFine().log("Finished updating groups from GroupCollector"); | ||||||
|       } catch (StorageException e) { |       } catch (StorageException e) { | ||||||
|         logger.atSevere().withCause(e).log("Error collecting groups for changes"); |         logger.atSevere().withCause(e).log("Error collecting groups for changes"); | ||||||
|         reject(magicBranch.cmd, "internal server error"); |         reject(magicBranch.cmd, INTERNAL_SERVER_ERROR); | ||||||
|       } |       } | ||||||
|       return newChanges; |       return newChanges; | ||||||
|     } |     } | ||||||
| @@ -2652,11 +2653,11 @@ class ReceiveCommits { | |||||||
|       } catch (StorageException err) { |       } catch (StorageException err) { | ||||||
|         logger.atSevere().withCause(err).log( |         logger.atSevere().withCause(err).log( | ||||||
|             "Cannot read database before replacement for project %s", project.getName()); |             "Cannot read database before replacement for project %s", project.getName()); | ||||||
|         rejectRemainingRequests(replaceByChange.values(), "internal server error"); |         rejectRemainingRequests(replaceByChange.values(), INTERNAL_SERVER_ERROR); | ||||||
|       } catch (IOException | PermissionBackendException err) { |       } catch (IOException | PermissionBackendException err) { | ||||||
|         logger.atSevere().withCause(err).log( |         logger.atSevere().withCause(err).log( | ||||||
|             "Cannot read repository before replacement for project %s", project.getName()); |             "Cannot read repository before replacement for project %s", project.getName()); | ||||||
|         rejectRemainingRequests(replaceByChange.values(), "internal server error"); |         rejectRemainingRequests(replaceByChange.values(), INTERNAL_SERVER_ERROR); | ||||||
|       } |       } | ||||||
|       logger.atFine().log("Read %d changes to replace", replaceByChange.size()); |       logger.atFine().log("Read %d changes to replace", replaceByChange.size()); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -81,7 +81,7 @@ public class ChangesCollection implements RestCollection<TopLevelResource, Chang | |||||||
|   @Override |   @Override | ||||||
|   public ChangeResource parse(TopLevelResource root, IdString id) |   public ChangeResource parse(TopLevelResource root, IdString id) | ||||||
|       throws RestApiException, PermissionBackendException, IOException { |       throws RestApiException, PermissionBackendException, IOException { | ||||||
|     List<ChangeNotes> notes = changeFinder.find(id.encoded(), true); |     List<ChangeNotes> notes = changeFinder.find(id.encoded()); | ||||||
|     if (notes.isEmpty()) { |     if (notes.isEmpty()) { | ||||||
|       throw new ResourceNotFoundException(id); |       throw new ResourceNotFoundException(id); | ||||||
|     } else if (notes.size() != 1) { |     } else if (notes.size() != 1) { | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ java_library( | |||||||
|         "//java/com/google/gerrit/server/restapi", |         "//java/com/google/gerrit/server/restapi", | ||||||
|         "//java/com/google/gerrit/server/util/time", |         "//java/com/google/gerrit/server/util/time", | ||||||
|         "//java/com/google/gerrit/util/cli", |         "//java/com/google/gerrit/util/cli", | ||||||
|  |         "//java/com/google/gerrit/util/logging", | ||||||
|         "//lib:args4j", |         "//lib:args4j", | ||||||
|         "//lib:gson", |         "//lib:gson", | ||||||
|         "//lib:guava", |         "//lib:guava", | ||||||
|   | |||||||
| @@ -23,8 +23,8 @@ import static com.google.gerrit.sshd.SshLog.P_STATUS; | |||||||
| import static com.google.gerrit.sshd.SshLog.P_USER_NAME; | import static com.google.gerrit.sshd.SshLog.P_USER_NAME; | ||||||
| import static com.google.gerrit.sshd.SshLog.P_WAIT; | import static com.google.gerrit.sshd.SshLog.P_WAIT; | ||||||
|  |  | ||||||
| import com.google.gerrit.server.logging.JsonLayout; | import com.google.gerrit.util.logging.JsonLayout; | ||||||
| import com.google.gerrit.server.logging.JsonLogEntry; | import com.google.gerrit.util.logging.JsonLogEntry; | ||||||
| import java.time.format.DateTimeFormatter; | import java.time.format.DateTimeFormatter; | ||||||
| import org.apache.log4j.spi.LoggingEvent; | import org.apache.log4j.spi.LoggingEvent; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								java/com/google/gerrit/util/logging/BUILD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								java/com/google/gerrit/util/logging/BUILD
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | load("@rules_java//java:defs.bzl", "java_library") | ||||||
|  |  | ||||||
|  | java_library( | ||||||
|  |     name = "logging", | ||||||
|  |     srcs = glob( | ||||||
|  |         ["*.java"], | ||||||
|  |     ), | ||||||
|  |     visibility = ["//visibility:public"], | ||||||
|  |     deps = [ | ||||||
|  |         "//lib:gson", | ||||||
|  |         "//lib/log:log4j", | ||||||
|  |     ], | ||||||
|  | ) | ||||||
| @@ -12,7 +12,7 @@ | |||||||
| // See the License for the specific language governing permissions and | // See the License for the specific language governing permissions and | ||||||
| // limitations under the License. | // limitations under the License. | ||||||
| 
 | 
 | ||||||
| package com.google.gerrit.server.logging; | package com.google.gerrit.util.logging; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.FieldNamingPolicy; | import com.google.gson.FieldNamingPolicy; | ||||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||||
| @@ -12,7 +12,7 @@ | |||||||
| // See the License for the specific language governing permissions and | // See the License for the specific language governing permissions and | ||||||
| // limitations under the License. | // limitations under the License. | ||||||
| 
 | 
 | ||||||
| package com.google.gerrit.server.logging; | package com.google.gerrit.util.logging; | ||||||
| 
 | 
 | ||||||
| import org.apache.log4j.spi.LoggingEvent; | import org.apache.log4j.spi.LoggingEvent; | ||||||
| 
 | 
 | ||||||
| @@ -18,14 +18,12 @@ import static com.google.common.truth.Truth.assertThat; | |||||||
| import static com.google.gerrit.testing.GerritJUnit.assertThrows; | import static com.google.gerrit.testing.GerritJUnit.assertThrows; | ||||||
|  |  | ||||||
| import com.google.gerrit.acceptance.AbstractDaemonTest; | import com.google.gerrit.acceptance.AbstractDaemonTest; | ||||||
| import com.google.gerrit.acceptance.GerritConfig; |  | ||||||
| import com.google.gerrit.acceptance.NoHttpd; | import com.google.gerrit.acceptance.NoHttpd; | ||||||
| import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; | import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; | ||||||
| import com.google.gerrit.entities.Project; | import com.google.gerrit.entities.Project; | ||||||
| import com.google.gerrit.extensions.api.changes.ChangeApi; | import com.google.gerrit.extensions.api.changes.ChangeApi; | ||||||
| import com.google.gerrit.extensions.common.ChangeInfo; | import com.google.gerrit.extensions.common.ChangeInfo; | ||||||
| import com.google.gerrit.extensions.common.ChangeInput; | import com.google.gerrit.extensions.common.ChangeInput; | ||||||
| import com.google.gerrit.extensions.restapi.DeprecatedIdentifierException; |  | ||||||
| import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
| import org.junit.Before; | import org.junit.Before; | ||||||
| @@ -140,28 +138,4 @@ public class ChangeIdIT extends AbstractDaemonTest { | |||||||
|   public void wrongChangeIdReturnsNotFound() throws Exception { |   public void wrongChangeIdReturnsNotFound() throws Exception { | ||||||
|     assertThrows(ResourceNotFoundException.class, () -> gApi.changes().id("I1234567890")); |     assertThrows(ResourceNotFoundException.class, () -> gApi.changes().id("I1234567890")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Test |  | ||||||
|   @GerritConfig( |  | ||||||
|       name = "change.api.allowedIdentifier", |  | ||||||
|       values = {"PROJECT_NUMERIC_ID", "NUMERIC_ID"}) |  | ||||||
|   public void deprecatedChangeIdReturnsBadRequest() throws Exception { |  | ||||||
|     // project~changeNumber still works |  | ||||||
|     ChangeApi cApi1 = gApi.changes().id(project.get(), changeInfo._number); |  | ||||||
|     assertThat(cApi1.get().changeId).isEqualTo(changeInfo.changeId); |  | ||||||
|     // Change number still works |  | ||||||
|     ChangeApi cApi2 = gApi.changes().id(changeInfo._number); |  | ||||||
|     assertThat(cApi2.get().changeId).isEqualTo(changeInfo.changeId); |  | ||||||
|     // IHash throws |  | ||||||
|     ChangeInfo ci = |  | ||||||
|         gApi.changes().create(new ChangeInput(project.get(), "master", "different message")).get(); |  | ||||||
|     DeprecatedIdentifierException thrown = |  | ||||||
|         assertThrows(DeprecatedIdentifierException.class, () -> gApi.changes().id(ci.changeId)); |  | ||||||
|     assertThat(thrown) |  | ||||||
|         .hasMessageThat() |  | ||||||
|         .contains( |  | ||||||
|             "The provided change identifier " |  | ||||||
|                 + ci.changeId |  | ||||||
|                 + " is deprecated. Use 'project~changeNumber' instead."); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ java_library( | |||||||
|         "//lib:junit", |         "//lib:junit", | ||||||
|         "//lib/guice", |         "//lib/guice", | ||||||
|         "//lib/httpcomponents:httpcore", |         "//lib/httpcomponents:httpcore", | ||||||
|  |         "//lib/log:api", | ||||||
|         "//lib/testcontainers", |         "//lib/testcontainers", | ||||||
|         "//lib/testcontainers:testcontainers-elasticsearch", |         "//lib/testcontainers:testcontainers-elasticsearch", | ||||||
|     ], |     ], | ||||||
|   | |||||||
| @@ -16,6 +16,8 @@ package com.google.gerrit.elasticsearch; | |||||||
|  |  | ||||||
| import org.apache.http.HttpHost; | import org.apache.http.HttpHost; | ||||||
| import org.junit.AssumptionViolatedException; | import org.junit.AssumptionViolatedException; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
| import org.testcontainers.elasticsearch.ElasticsearchContainer; | import org.testcontainers.elasticsearch.ElasticsearchContainer; | ||||||
|  |  | ||||||
| /* Helper class for running ES integration tests in docker container */ | /* Helper class for running ES integration tests in docker container */ | ||||||
| @@ -74,6 +76,11 @@ public class ElasticContainer extends ElasticsearchContainer { | |||||||
|     super(getImageName(version)); |     super(getImageName(version)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   protected Logger logger() { | ||||||
|  |     return LoggerFactory.getLogger("org.testcontainers"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public HttpHost getHttpHost() { |   public HttpHost getHttpHost() { | ||||||
|     return new HttpHost(getContainerIpAddress(), getMappedPort(ELASTICSEARCH_DEFAULT_PORT)); |     return new HttpHost(getContainerIpAddress(), getMappedPort(ELASTICSEARCH_DEFAULT_PORT)); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ java_library( | |||||||
|     name = "api", |     name = "api", | ||||||
|     data = ["//lib:LICENSE-slf4j"], |     data = ["//lib:LICENSE-slf4j"], | ||||||
|     visibility = [ |     visibility = [ | ||||||
|  |         "//javatests/com/google/gerrit/elasticsearch:__pkg__", | ||||||
|         "//lib:__pkg__", |         "//lib:__pkg__", | ||||||
|         "//plugins:__pkg__", |         "//plugins:__pkg__", | ||||||
|     ], |     ], | ||||||
|   | |||||||
| @@ -290,13 +290,15 @@ limitations under the License. | |||||||
|             <span class="separator"></span> |             <span class="separator"></span> | ||||||
|           </span> |           </span> | ||||||
|           <template is="dom-if" if="[[_computeIsLoggedIn(_loggedIn)]]"> |           <template is="dom-if" if="[[_computeIsLoggedIn(_loggedIn)]]"> | ||||||
|  |             <span class="separator"></span> | ||||||
|             <span class="editButton"> |             <span class="editButton"> | ||||||
|               <a href$="[[_computeEditURL(_change, _patchRange, _path)]]"> |               <gr-button | ||||||
|                 <iron-icon icon="gr-icons:edit"></iron-icon> |                 link | ||||||
|               </a> |                 title="Edit current file" | ||||||
|               <span class="separator"></span> |                 on-click="_goToEditFile">edit</gr-button> | ||||||
|             </span> |             </span> | ||||||
|           </template> |           </template> | ||||||
|  |           <span class="separator"></span> | ||||||
|           <div class$="diffModeSelector [[_computeModeSelectHideClass(_isImageDiff)]]"> |           <div class$="diffModeSelector [[_computeModeSelectHideClass(_isImageDiff)]]"> | ||||||
|             <span>Diff view:</span> |             <span>Diff view:</span> | ||||||
|             <gr-diff-mode-selector |             <gr-diff-mode-selector | ||||||
|   | |||||||
| @@ -566,12 +566,11 @@ | |||||||
|       return this._getDiffUrl(this._change, this._patchRange, newPath.path); |       return this._getDiffUrl(this._change, this._patchRange, newPath.path); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     _computeEditURL(change, patchRange, path) { |     _goToEditFile() { | ||||||
|       if ([change, patchRange, path].some(arg => arg === undefined)) { |       // TODO(taoalpha): add a shortcut for editing | ||||||
|         return ''; |       const editUrl = Gerrit.Nav.getEditUrlForDiff( | ||||||
|       } |           this._change, this._path, this._patchRange.patchNum); | ||||||
|       return Gerrit.Nav.getEditUrlForDiff( |       return Gerrit.Nav.navigateToRelativeUrl(editUrl); | ||||||
|           change, path, patchRange.patchNum); |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -365,6 +365,53 @@ limitations under the License. | |||||||
|           PARENT), 'Should navigate to /c/42/1'); |           PARENT), 'Should navigate to /c/42/1'); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     test('edit should redirect to edit page', done => { | ||||||
|  |       element._loggedIn = true; | ||||||
|  |       element._path = 't.txt'; | ||||||
|  |       element._patchRange = { | ||||||
|  |         basePatchNum: PARENT, | ||||||
|  |         patchNum: '1', | ||||||
|  |       }; | ||||||
|  |       element._change = { | ||||||
|  |         _number: 42, | ||||||
|  |         revisions: { | ||||||
|  |           a: {_number: 1, commit: {parents: []}}, | ||||||
|  |           b: {_number: 2, commit: {parents: []}}, | ||||||
|  |         }, | ||||||
|  |       }; | ||||||
|  |       const redirectStub = sandbox.stub(Gerrit.Nav, 'navigateToRelativeUrl'); | ||||||
|  |       flush(() => { | ||||||
|  |         const editBtn = Polymer.dom(element.root) | ||||||
|  |             .querySelector('.editButton gr-button'); | ||||||
|  |         assert.isTrue(!!editBtn); | ||||||
|  |         MockInteractions.tap(editBtn); | ||||||
|  |         assert.isTrue(redirectStub.called); | ||||||
|  |         done(); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     test('edit hidden when not logged in', done => { | ||||||
|  |       element._loggedIn = false; | ||||||
|  |       element._path = 't.txt'; | ||||||
|  |       element._patchRange = { | ||||||
|  |         basePatchNum: PARENT, | ||||||
|  |         patchNum: '1', | ||||||
|  |       }; | ||||||
|  |       element._change = { | ||||||
|  |         _number: 42, | ||||||
|  |         revisions: { | ||||||
|  |           a: {_number: 1, commit: {parents: []}}, | ||||||
|  |           b: {_number: 2, commit: {parents: []}}, | ||||||
|  |         }, | ||||||
|  |       }; | ||||||
|  |       flush(() => { | ||||||
|  |         const editBtn = Polymer.dom(element.root) | ||||||
|  |             .querySelector('.editButton gr-button'); | ||||||
|  |         assert.isFalse(!!editBtn); | ||||||
|  |         done(); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     suite('diff prefs hidden', () => { |     suite('diff prefs hidden', () => { | ||||||
|       test('when no prefs or logged out', () => { |       test('when no prefs or logged out', () => { | ||||||
|         element.disableDiffPrefs = false; |         element.disableDiffPrefs = false; | ||||||
|   | |||||||
| @@ -72,10 +72,11 @@ | |||||||
|       // Ensure that external links originating from HTML commentlink configs |       // Ensure that external links originating from HTML commentlink configs | ||||||
|       // open in a new tab. @see Issue 5567 |       // open in a new tab. @see Issue 5567 | ||||||
|       // Ensure links to the same host originating from commentlink configs |       // Ensure links to the same host originating from commentlink configs | ||||||
|       // open in the same tab. @see Issue 4616 |       // open in the same tab. When target is not set - default is _self | ||||||
|  |       // @see Issue 4616 | ||||||
|       output.querySelectorAll('a').forEach(anchor => { |       output.querySelectorAll('a').forEach(anchor => { | ||||||
|         if (anchor.hostname === window.location.hostname) { |         if (anchor.hostname === window.location.hostname) { | ||||||
|           anchor.setAttribute('target', '_self'); |           anchor.removeAttribute('target'); | ||||||
|         } else { |         } else { | ||||||
|           anchor.setAttribute('target', '_blank'); |           anchor.setAttribute('target', '_blank'); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -144,7 +144,7 @@ limitations under the License. | |||||||
|       const linkEl = element.$.output.childNodes[1]; |       const linkEl = element.$.output.childNodes[1]; | ||||||
|       assert.equal(textNode.textContent, prefix); |       assert.equal(textNode.textContent, prefix); | ||||||
|       const url = '/q/' + changeID; |       const url = '/q/' + changeID; | ||||||
|       assert.equal(linkEl.target, '_self'); |       assert.isFalse(linkEl.hasAttribute('target')); | ||||||
|       // Since url is a path, the host is added automatically. |       // Since url is a path, the host is added automatically. | ||||||
|       assert.isTrue(linkEl.href.endsWith(url)); |       assert.isTrue(linkEl.href.endsWith(url)); | ||||||
|       assert.equal(linkEl.textContent, changeID); |       assert.equal(linkEl.textContent, changeID); | ||||||
| @@ -162,7 +162,7 @@ limitations under the License. | |||||||
|       const linkEl = element.$.output.childNodes[1]; |       const linkEl = element.$.output.childNodes[1]; | ||||||
|       assert.equal(textNode.textContent, prefix); |       assert.equal(textNode.textContent, prefix); | ||||||
|       const url = '/r/q/' + changeID; |       const url = '/r/q/' + changeID; | ||||||
|       assert.equal(linkEl.target, '_self'); |       assert.isFalse(linkEl.hasAttribute('target')); | ||||||
|       // Since url is a path, the host is added automatically. |       // Since url is a path, the host is added automatically. | ||||||
|       assert.isTrue(linkEl.href.endsWith(url)); |       assert.isTrue(linkEl.href.endsWith(url)); | ||||||
|       assert.equal(linkEl.textContent, changeID); |       assert.equal(linkEl.textContent, changeID); | ||||||
| @@ -203,7 +203,7 @@ limitations under the License. | |||||||
|  |  | ||||||
|       assert.equal(textNode.textContent, prefix); |       assert.equal(textNode.textContent, prefix); | ||||||
|  |  | ||||||
|       assert.equal(changeLinkEl.target, '_self'); |       assert.isFalse(changeLinkEl.hasAttribute('target')); | ||||||
|       assert.isTrue(changeLinkEl.href.endsWith(changeUrl)); |       assert.isTrue(changeLinkEl.href.endsWith(changeUrl)); | ||||||
|       assert.equal(changeLinkEl.textContent, changeID); |       assert.equal(changeLinkEl.textContent, changeID); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ | |||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
|  |  | ||||||
|  | import argparse | ||||||
| from hashlib import sha1 | from hashlib import sha1 | ||||||
| from optparse import OptionParser |  | ||||||
| from os import link, makedirs, path, remove | from os import link, makedirs, path, remove | ||||||
| import shutil | import shutil | ||||||
| from subprocess import check_call, CalledProcessError | from subprocess import check_call, CalledProcessError | ||||||
| @@ -75,13 +75,13 @@ def cache_entry(args): | |||||||
|     return path.join(CACHE_DIR, name) |     return path.join(CACHE_DIR, name) | ||||||
|  |  | ||||||
|  |  | ||||||
| opts = OptionParser() | parser = argparse.ArgumentParser() | ||||||
| opts.add_option('-o', help='local output file') | parser.add_argument('-o', help='local output file') | ||||||
| opts.add_option('-u', help='URL to download') | parser.add_argument('-u', help='URL to download') | ||||||
| opts.add_option('-v', help='expected content SHA-1') | parser.add_argument('-v', help='expected content SHA-1') | ||||||
| opts.add_option('-x', action='append', help='file to delete from ZIP') | parser.add_argument('-x', action='append', help='file to delete from ZIP') | ||||||
| opts.add_option('--exclude_java_sources', action='store_true') | parser.add_argument('--exclude_java_sources', action='store_true') | ||||||
| args, _ = opts.parse_args() | args = parser.parse_args() | ||||||
|  |  | ||||||
| root_dir = args.o | root_dir = args.o | ||||||
| while root_dir and path.dirname(root_dir) != root_dir: | while root_dir and path.dirname(root_dir) != root_dir: | ||||||
|   | |||||||
| @@ -22,10 +22,10 @@ python tools/js/bower2bazel.py -w lib/js/bower_archives.bzl \ | |||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
|  |  | ||||||
|  | import argparse | ||||||
| import collections | import collections | ||||||
| import json | import json | ||||||
| import hashlib | import hashlib | ||||||
| import optparse |  | ||||||
| import os | import os | ||||||
| import subprocess | import subprocess | ||||||
| import sys | import sys | ||||||
| @@ -141,11 +141,11 @@ def bower_command(args): | |||||||
|             os.getcwd() + "/tools/js/run_npm_binary.py", sorted(fs)[0]] + args |             os.getcwd() + "/tools/js/run_npm_binary.py", sorted(fs)[0]] + args | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(args): | def main(): | ||||||
|     opts = optparse.OptionParser() |     parser = argparse.ArgumentParser() | ||||||
|     opts.add_option('-w', help='.bzl output for WORKSPACE') |     parser.add_argument('-w', help='.bzl output for WORKSPACE') | ||||||
|     opts.add_option('-b', help='.bzl output for //lib:BUILD') |     parser.add_argument('-b', help='.bzl output for //lib:BUILD') | ||||||
|     opts, args = opts.parse_args() |     args = parser.parse_args() | ||||||
|  |  | ||||||
|     target_str = subprocess.check_output([ |     target_str = subprocess.check_output([ | ||||||
|         "bazel", "query", "kind(bower_component_bundle, //polygerrit-ui/...)"]) |         "bazel", "query", "kind(bower_component_bundle, //polygerrit-ui/...)"]) | ||||||
| @@ -166,12 +166,12 @@ def main(args): | |||||||
|     cmd = bower_command(["install"]) |     cmd = bower_command(["install"]) | ||||||
|  |  | ||||||
|     build_out = sys.stdout |     build_out = sys.stdout | ||||||
|     if opts.b: |     if args.b: | ||||||
|         build_out = open(opts.b + ".tmp", 'w') |         build_out = open(args.b + ".tmp", 'w') | ||||||
|  |  | ||||||
|     ws_out = sys.stdout |     ws_out = sys.stdout | ||||||
|     if opts.b: |     if args.b: | ||||||
|         ws_out = open(opts.w + ".tmp", 'w') |         ws_out = open(args.w + ".tmp", 'w') | ||||||
|  |  | ||||||
|     header = """# DO NOT EDIT |     header = """# DO NOT EDIT | ||||||
| # generated with the following command: | # generated with the following command: | ||||||
| @@ -193,8 +193,8 @@ def main(args): | |||||||
|     build_out.close() |     build_out.close() | ||||||
|  |  | ||||||
|     os.chdir(oldwd) |     os.chdir(oldwd) | ||||||
|     os.rename(opts.w + ".tmp", opts.w) |     os.rename(args.w + ".tmp", args.w) | ||||||
|     os.rename(opts.b + ".tmp", opts.b) |     os.rename(args.b + ".tmp", args.b) | ||||||
|  |  | ||||||
|  |  | ||||||
| def dump_workspace(data, seeds, out): | def dump_workspace(data, seeds, out): | ||||||
| @@ -259,4 +259,4 @@ def interpret_bower_json(seeds, ws_out, build_out): | |||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     main(sys.argv[1:]) |     main() | ||||||
|   | |||||||
| @@ -15,9 +15,9 @@ | |||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
|  |  | ||||||
|  | import argparse | ||||||
| import hashlib | import hashlib | ||||||
| import json | import json | ||||||
| import optparse |  | ||||||
| import os | import os | ||||||
| import shutil | import shutil | ||||||
| import subprocess | import subprocess | ||||||
| @@ -80,44 +80,44 @@ def cache_entry(name, package, version, sha1): | |||||||
|     return os.path.join(CACHE_DIR, '%s-%s.zip-%s' % (name, version, sha1)) |     return os.path.join(CACHE_DIR, '%s-%s.zip-%s' % (name, version, sha1)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(args): | def main(): | ||||||
|     opts = optparse.OptionParser() |     parser = argparse.ArgumentParser() | ||||||
|     opts.add_option('-n', help='short name of component') |     parser.add_argument('-n', help='short name of component') | ||||||
|     opts.add_option('-b', help='bower command') |     parser.add_argument('-b', help='bower command') | ||||||
|     opts.add_option('-p', help='full package name of component') |     parser.add_argument('-p', help='full package name of component') | ||||||
|     opts.add_option('-v', help='version number') |     parser.add_argument('-v', help='version number') | ||||||
|     opts.add_option('-s', help='expected content sha1') |     parser.add_argument('-s', help='expected content sha1') | ||||||
|     opts.add_option('-o', help='output file location') |     parser.add_argument('-o', help='output file location') | ||||||
|     opts, args_ = opts.parse_args(args) |     args = parser.parse_args() | ||||||
|  |  | ||||||
|     assert opts.p |     assert args.p | ||||||
|     assert opts.v |     assert args.v | ||||||
|     assert opts.n |     assert args.n | ||||||
|  |  | ||||||
|     cwd = os.getcwd() |     cwd = os.getcwd() | ||||||
|     outzip = os.path.join(cwd, opts.o) |     outzip = os.path.join(cwd, args.o) | ||||||
|     cached = cache_entry(opts.n, opts.p, opts.v, opts.s) |     cached = cache_entry(args.n, args.p, args.v, args.s) | ||||||
|  |  | ||||||
|     if not os.path.exists(cached): |     if not os.path.exists(cached): | ||||||
|         info = bower_info(opts.b, opts.n, opts.p, opts.v) |         info = bower_info(args.b, args.n, args.p, args.v) | ||||||
|         ignore_deps(info) |         ignore_deps(info) | ||||||
|         subprocess.check_call( |         subprocess.check_call( | ||||||
|             bower_cmd( |             bower_cmd( | ||||||
|                 opts.b, '--quiet', 'install', '%s#%s' % (opts.p, opts.v))) |                 args.b, '--quiet', 'install', '%s#%s' % (args.p, args.v))) | ||||||
|         bc = os.path.join(cwd, 'bower_components') |         bc = os.path.join(cwd, 'bower_components') | ||||||
|         subprocess.check_call( |         subprocess.check_call( | ||||||
|             ['zip', '-q', '--exclude', '.bower.json', '-r', cached, opts.n], |             ['zip', '-q', '--exclude', '.bower.json', '-r', cached, args.n], | ||||||
|             cwd=bc) |             cwd=bc) | ||||||
|  |  | ||||||
|         if opts.s: |         if args.s: | ||||||
|             path = os.path.join(bc, opts.n) |             path = os.path.join(bc, args.n) | ||||||
|             sha1 = bowerutil.hash_bower_component( |             sha1 = bowerutil.hash_bower_component( | ||||||
|                 hashlib.sha1(), path).hexdigest() |                 hashlib.sha1(), path).hexdigest() | ||||||
|             if opts.s != sha1: |             if args.s != sha1: | ||||||
|                 print(( |                 print(( | ||||||
|                     '%s#%s:\n' |                     '%s#%s:\n' | ||||||
|                     'expected %s\n' |                     'expected %s\n' | ||||||
|                     'received %s\n') % (opts.p, opts.v, opts.s, sha1), |                     'received %s\n') % (args.p, args.v, args.s, sha1), | ||||||
|                     file=sys.stderr) |                     file=sys.stderr) | ||||||
|                 try: |                 try: | ||||||
|                     os.remove(cached) |                     os.remove(cached) | ||||||
| @@ -132,4 +132,4 @@ def main(args): | |||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     sys.exit(main(sys.argv[1:])) |     sys.exit(main()) | ||||||
|   | |||||||
| @@ -14,20 +14,20 @@ | |||||||
| # limitations under the License. | # limitations under the License. | ||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
| from optparse import OptionParser | import argparse | ||||||
| from os import path, environ | from os import path, environ | ||||||
| from subprocess import check_output, CalledProcessError | from subprocess import check_output, CalledProcessError | ||||||
| from sys import stderr | from sys import stderr | ||||||
|  |  | ||||||
| opts = OptionParser() | parser = argparse.ArgumentParser() | ||||||
| opts.add_option('--repository', help='maven repository id') | parser.add_argument('--repository', help='maven repository id') | ||||||
| opts.add_option('--url', help='maven repository url') | parser.add_argument('--url', help='maven repository url') | ||||||
| opts.add_option('-o') | parser.add_argument('-o') | ||||||
| opts.add_option('-a', help='action (valid actions are: install,deploy)') | parser.add_argument('-a', help='action (valid actions are: install,deploy)') | ||||||
| opts.add_option('-v', help='gerrit version') | parser.add_argument('-v', help='gerrit version') | ||||||
| opts.add_option('-s', action='append', help='triplet of artifactId:type:path') | parser.add_argument('-s', action='append', help='triplet of artifactId:type:path') | ||||||
|  | args = parser.parse_args() | ||||||
|  |  | ||||||
| args, ctx = opts.parse_args() |  | ||||||
| if not args.v: | if not args.v: | ||||||
|     print('version is empty', file=stderr) |     print('version is empty', file=stderr) | ||||||
|     exit(1) |     exit(1) | ||||||
|   | |||||||
| @@ -14,21 +14,16 @@ | |||||||
| # limitations under the License. | # limitations under the License. | ||||||
|  |  | ||||||
| from __future__ import print_function | from __future__ import print_function | ||||||
| from optparse import OptionParser | import argparse | ||||||
| import os.path | import os.path | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
|  |  | ||||||
| parser = OptionParser() | parser = argparse.ArgumentParser() | ||||||
| opts, args = parser.parse_args() | parser.add_argument('version') | ||||||
|  | args = parser.parse_args() | ||||||
| if not len(args): |  | ||||||
|     parser.error('not enough arguments') |  | ||||||
| elif len(args) > 1: |  | ||||||
|     parser.error('too many arguments') |  | ||||||
|  |  | ||||||
| DEST_PATTERN = r'\g<1>%s\g<3>' % args[0] |  | ||||||
|  |  | ||||||
|  | DEST_PATTERN = r'\g<1>%s\g<3>' % args.version | ||||||
|  |  | ||||||
| def replace_in_file(filename, src_pattern): | def replace_in_file(filename, src_pattern): | ||||||
|     try: |     try: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 David Pursehouse
					David Pursehouse