Merge branch 'stable-2.8' * stable-2.8: PatchListCacheImpl: explicitly check for null revision ChangeField: skip PatchSets with null revisions Rename methods in PluginConfigFactory to be more explicit Explain limitation of storing plugin config in existing config files Change-Id: Id34a619c8979e2d3048244a9fb3d2c03482ca952
diff --git a/BUCK b/BUCK index 616a0fe..3d1541c 100644 --- a/BUCK +++ b/BUCK
@@ -3,8 +3,8 @@ gerrit_war(name = 'gerrit') gerrit_war(name = 'chrome', ui = 'ui_chrome') gerrit_war(name = 'firefox', ui = 'ui_firefox') -gerrit_war(name = 'withdocs', context = DOCS) -gerrit_war(name = 'release', context = DOCS + ['//plugins:core.zip']) +gerrit_war(name = 'withdocs', docs = True) +gerrit_war(name = 'release', docs = True, context = ['//plugins:core.zip']) API_DEPS = [ ':extension-api',
diff --git a/Documentation/BUCK b/Documentation/BUCK index 71d8664..b2b7d2a 100644 --- a/Documentation/BUCK +++ b/Documentation/BUCK
@@ -3,7 +3,6 @@ include_defs('//tools/git.defs') DOC_DIR = 'Documentation' -INDEX_DIR = DOC_DIR + '/.index' MAIN = ['//gerrit-pgm:pgm', '//gerrit-gwtui:ui_module'] SRCS = glob(['*.txt'], excludes = ['licenses.txt']) @@ -11,12 +10,10 @@ name = 'html', cmd = 'cd $TMP;' + 'mkdir -p %s/images;' % DOC_DIR + - 'unzip -q $SRCDIR/index.zip -d %s/;' % INDEX_DIR + 'unzip -q $SRCDIR/only_html.zip -d %s/;' % DOC_DIR + 'for s in $SRCS;do ln -s $s %s;done;' % DOC_DIR + 'mv %s/*.{jpg,png} %s/images;' % (DOC_DIR, DOC_DIR) + 'rm %s/only_html.zip;' % DOC_DIR + - 'rm %s/index.zip;' % DOC_DIR + 'rm %s/licenses.txt;' % DOC_DIR + 'cp $SRCDIR/licenses.txt LICENSES.txt;' + 'zip -qr $OUT *', @@ -27,11 +24,9 @@ 'doc.css', genfile('licenses.txt'), genfile('only_html.zip'), - genfile('index.zip'), ], deps = [ ':generate_html', - ':index', ':licenses.txt', ], out = 'html.zip', @@ -79,3 +74,18 @@ ], out = 'index.zip', ) + +genrule( + name = 'index_jar', + cmd = 'jar cf $OUT -C $SRCDIR index.zip', + srcs = [genfile('index.zip')], + deps = [':index'], + out = 'index.jar', +) + +prebuilt_jar( + name = 'index_lib', + binary_jar = genfile('index.jar'), + deps = [':index_jar'], + visibility = ['PUBLIC'], +)
diff --git a/Documentation/cmd-apropos.txt b/Documentation/cmd-apropos.txt new file mode 100644 index 0000000..a24548d --- /dev/null +++ b/Documentation/cmd-apropos.txt
@@ -0,0 +1,63 @@ +gerrit apropos +============== + +NAME +---- +gerrit apropos - Search Gerrit documentation index + +SYNOPSIS +-------- +[verse] +'ssh' -p <port> <host> 'gerrit apropos' + <query> + +DESCRIPTION +----------- +Queries the documentation index and returns results with the title and URL +from the matched documents. + +ACCESS +------ +Any user who has configured an SSH key. + +SCRIPTING +--------- +This command is intended to be used in scripts. + +Note: this feature is only available if documentation index was built. + +EXAMPLES +-------- + +===== +$ ssh -p 29418 review.example.com gerrit apropos capabilities + Gerrit Code Review - /config/ REST API: + http://localhost:8080/Documentation/rest-api-config.html + + Gerrit Code Review - /accounts/ REST API: + http://localhost:8080/Documentation/rest-api-accounts.html + + Gerrit Code Review - Project Configuration File Format: + http://localhost:8080/Documentation/config-project-config.html + + Gerrit Code Review - Access Controls: + http://localhost:8080/Documentation/access-control.html + + Gerrit Code Review - Plugin Development: + http://localhost:8080/Documentation/dev-plugins.html + + Gerrit Code Review - REST API: + http://localhost:8080/Documentation/rest-api.html + + Gerrit Code Review - /access/ REST API: + http://localhost:8080/Documentation/rest-api-access.html +===== + +SEE ALSO +-------- + +* link:access-control.html[Access Controls] + +GERRIT +------ +Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt index 3ba66a8..650b0bb 100644 --- a/Documentation/cmd-index.txt +++ b/Documentation/cmd-index.txt
@@ -51,6 +51,9 @@ [[user_commands]]User Commands ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +link:cmd-apropos.html[gerrit apropos]:: + Search Gerrit documentation index. + 'gerrit approve':: 'Deprecated alias for `gerrit review`.'
diff --git a/Documentation/cmd-query.txt b/Documentation/cmd-query.txt index 66bd845..f7a784f 100644 --- a/Documentation/cmd-query.txt +++ b/Documentation/cmd-query.txt
@@ -17,6 +17,7 @@ [--commit-message] [--dependencies] [--submit-records] + [--all-reviewers] [--] <query> [limit:<n>] @@ -89,6 +90,10 @@ Show information about patch sets which depend on, or are needed by, each patch set. +--all-reviewers:: + Show the name and email of all reviewers which are added to a change + (irrespective of whether they have been voting on that change or not). + --submit-records:: Show submit record information about the change, which includes whether the change meets the criteria for submission
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index c644ef9..814472a 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt
@@ -2705,6 +2705,13 @@ + By default, `host/canonical.host.name` +[[sshd.requestLog]]sshd.requestLog:: ++ +Enable (or disable) the `'$site_path'/logs/sshd_log` request log. +If enabled, a request log file is written out by the SSH daemon. ++ +By default, true. + [[suggest]] Section suggest ~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/config-gitweb.txt b/Documentation/config-gitweb.txt index 7ba15b8..711174f 100644 --- a/Documentation/config-gitweb.txt +++ b/Documentation/config-gitweb.txt
@@ -245,6 +245,10 @@ After updating `'$site_path'/etc/gerrit.config`, the Gerrit server must be restarted and clients must reload the host page to see the change. +Note that when using a custom gitweb configuration, values must be +specified for all of the `project`, `revision`, `branch` and `filehistory` +settings, otherwise the configuration will not be used. + Access Control ++++++++++++++
diff --git a/Documentation/dev-inspector.txt b/Documentation/dev-inspector.txt new file mode 100644 index 0000000..485ad7b --- /dev/null +++ b/Documentation/dev-inspector.txt
@@ -0,0 +1,302 @@ +Gerrit Inspector +================ + +NAME +---- +Gerrit Inspector - Interactive Jython environment for Gerrit + +SYNOPSIS +-------- +[verse] +'java' -jar gerrit.war 'daemon' + -d <SITE_PATH> + [\--enable-httpd | \--disable-httpd] + [\--enable-sshd | \--disable-sshd] + [\--console-log] + [\--slave] + -s + +DESCRIPTION +----------- +Runs the Gerrit network daemon on the local system as described +in the link:pgm-daemon.html[Daemon documentation], additionally +starting an interactive Jython shell for inspection +and troubleshooting of live data of the Gerrit instance. + +CAUTION: Gerrit Inspector works directly on instances of Java Virtual +Machine objects and it is possible to read and write instance +members as well as invoke Java functions. Access is granted +also to 'private' and 'protected' members. Therefore it is possible +to introduce changes to the internal state of the system in +an inconsistent way. Care must be taken not to break the running system +and/or destroy the data. + +INSTALLATION +------------ + +Gerrit Inspector requires Jython library ('jython.jar') to be installed +in the '$site_path/lib' directory. Jython, a Python interpreter for +the Java Virtual Machine, can be obtained from the http://www.jython.org/ +website. Only 'jython.jar' file is needed, installation of Jython libraries +is optional. Gerrit Inspector has been tested with Jython 2.5.2 but +might work an earlier version. + +STARTUP +------- + +During startup Jython examines Java libraries found on the classpath. +While libraries are inspected a large amount of messages is displayed on the console: + +---- +*sys-package-mgr*: processing new jar, '/home/user/.gerritcodereview/tmp/gerrit_4890671371398741854_app/sshd-core-0.5.1-r1095809.jar' +---- + +After this a system-wide embedded initialization script is started. This script +is contained in the gerrit's WAR archive. This script produces output similar to +the following on the console: + +---- +"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d" +"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248" +"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c" +"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd" + +Welcome to the Gerrit Inspector +Enter help() to see the above again, EOF to quit and stop Gerrit +---- + +Then an optional user startup script is processed. It should be +located in the gerrit user home directory as '.gerritcodereview/Startup.py'. + +This script can access all variables defined in the system (such +as the ones displayed by the initialization script as shown above). +Variables and functions defined by the startup scripts are available for +the interactive interpreter. + +When interactive interpreter exits (by issuing EOF on the command line), +a whole Gerrit instance is shut down gracefully. + +USING THE INTERPRETER +--------------------- + +Gerrit Inspector launches Jython interpreter in the context of the Gerrit +Java Virtual Machine. All core facilities of the Jython (and Python) +language are available to the user. + +Additional facilities can be provided, for example a 'Lib' directory from the +Jython distribution can be installed under '$site_path/lib/Lib' to provide +access to many standard Python modules. Jython can also use additional Java +classes and libraries and most of the Python modules and scripts. + +The Inspector has by default access to classes and object instances available +in the Java Virtual Machine. Objects are introspected and *private* and *protected* +members are also available. + +For more information on using Jython, especially with regards to its limitations +in interfacing to the Java Virtual Machine, please refer to the +http://www.jython.org/[Jython documentation]. + +After sucessful initialization it is possible to examine components of +Java packages, classes and live instances. + +---- +>>> import com.google.inject +>>> dir(com.google.inject) +['AbstractModule', 'Binder', 'Binding', 'BindingAnnotation', 'ConfigurationException', 'CreationException', 'Exposed', 'Guice', 'ImplementedBy', 'Inject', 'Injector', 'Key', 'MembersInjector', 'Module', 'OutOfScopeException', 'PrivateBinder', 'PrivateModule', 'ProvidedBy', 'Provider', 'Provides', 'ProvisionException', 'Scope', 'ScopeAnnotation', 'Scopes', 'Singleton', 'Stage', 'TypeLiteral', '__name__', 'assistedinject', 'binder', 'internal', 'matcher', 'name', 'servlet', 'spi', 'util'] +>>> type(com.google.inject) +<type 'javapackage'> +>>> dir(com.google.inject.Guice) +['__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__', +'__eq__', '__getattribute__', '__hash__', '__init__', '__ne__', +'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', +'__str__', '__unicode__', 'class', 'clone', 'createInjector', +'equals', 'finalize', 'getClass', 'hashCode', 'notify', 'notifyAll', +'registerNatives', 'toString', 'wait'] +---- + +Startup script provides some convenient variables to access some global Gerrit components, +for example a connection to the review database is kept open: + +---- +>>> ds +org.apache.commons.dbcp.BasicDataSource@61db2215 +>>> ds.driverClassName +u'org.postgresql.Driver' +>>> ds.dataSource +org.apache.commons.dbcp.PoolingDataSource@23226fe1 +>>> ds.dataSource.connection +jdbc:postgresql://localhost/reviewdb, UserName=rv, PostgreSQL Native Driver +---- + +It is also possible to interact with the ORM layer: + +---- +>>> db = schk.schema.open() +>>> db +com.google.gerrit.reviewdb.server.ReviewDb_Schema_GwtOrm$$28@24cbbdf3 +>>> db.getDialect() +com.google.gwtorm.schema.sql.DialectPostgreSQL@4de07d3e +>>> for x in db.patchSets().iterateAllEntities(): +... print x +... +[PatchSet 1,1] +[PatchSet 2,1] +[PatchSet 3,1] +[PatchSet 4,1] +[PatchSet 5,1] +[PatchSet 6,1] +[PatchSet 7,1] +[PatchSet 8,1] +[PatchSet 6,2] +>>> for x in db.patchComments().iterateAllEntities(): +... print x +com.google.gerrit.reviewdb.client.PatchLineComment@5381298a +com.google.gerrit.reviewdb.client.PatchLineComment@44ce4dda +com.google.gerrit.reviewdb.client.PatchLineComment@44594680 +>>> dir(com.google.gerrit.reviewdb.client.PatchLineComment) +['Key', 'STATUS_DRAFT', 'STATUS_PUBLISHED', 'Status', '__class__', +'__copy__', '__deepcopy__', '__delattr__', '__doc__', '__eq__', +'__getattribute__', '__hash__', '__init__', '__ne__', '__new__', +'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', +'__unicode__', 'author', 'class', 'clone', 'equals', 'finalize', +'getAuthor', 'getClass', 'getKey', 'getLine', 'getMessage', +'getParentUuid', 'getSide', 'getStatus', 'getWrittenOn', 'hashCode', +'key', 'line', 'lineNbr', 'message', 'notify', 'notifyAll', +'parentUuid', 'registerNatives', 'setMessage', 'setSide', 'setStatus', +'side', 'status', 'toString', 'updated', 'wait', 'writtenOn'] +>>> for x in db.patchComments().iterateAllEntities(): +... print x.status, x.line, x.message +... +P 2 I like it! +P 2 more +P 1 better +---- + +A built-in *help()* function provides values of global variables +defined in the interpreter: + +---- +>>> help() +"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd" +"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c" +"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248" +"q" is "com.google.gerrit.reviewdb.server.ReviewDb_Schema_GwtOrm$$23@56d3384d" +"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d" +"x" is "com.google.gerrit.reviewdb.client.PatchLineComment@518acfa7" +"z" is "com.google.gwtorm.jdbc.Database@668dfd9b" +"db" is "com.google.gerrit.reviewdb.server.ReviewDb_Schema_GwtOrm$$23@6a3ccb09" + +Welcome to the Gerrit Inspector +Enter help() to see the above again, EOF to quit and stop Gerrit +---- + +Java and Python exceptions are intercepted by the Inspector: +---- +>>> import java.lang.RuntimeException +>>> raise java.lang.RuntimeException("Exiting") +Traceback (most recent call last): + File "<stdin>", line 1, in <module> + at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) + at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) + at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) + at java.lang.reflect.Constructor.newInstance(Constructor.java:532) + at org.python.core.PyReflectedConstructor.constructProxy(PyReflectedConstructor.java:210) + +java.lang.RuntimeException: java.lang.RuntimeException: Exiting +>>> +---- + +To exit the interpreter, use EOF character (Ctrl-D on Unix systems, Ctrl-Z on Windows). + +It is also possible to shut down the JVM by using *System.exit()* + +---- +>>> import java.lang.System +>>> java.lang.System.exit(1) +---- + +And Gerrit should shut down all its subsystems and exit: + +---- +[2012-04-17 15:31:08,458] INFO com.google.gerrit.pgm.Daemon : caught shutdown, cleaning up +---- + +TROUBLESHOOTING +--------------- + +Gerrit Inspector is logging to the Gerrit error log. + +A successful startup is indicated in the logfile: + +---- + [2012-04-17 13:43:44,888] INFO com.google.gerrit.pgm.shell.JythonShell : Jython shell instance created. +---- + +If 'jython.jar' library is not available, Gerrit refuses to start when given *-s* option: + +---- +[2012-04-17 13:57:29,611] ERROR com.google.gerrit.pgm.Daemon : Unable to start daemon +com.google.inject.ProvisionException: Guice provision errors: + +1) Error injecting constructor, java.lang.UnsupportedOperationException: Cannot create Jython shell: Class org.python.util.InteractiveConsole not found + (You might need to install jython.jar in the lib directory) + at com.google.gerrit.pgm.shell.JythonShell.<init>(JythonShell.java:47) + while locating com.google.gerrit.pgm.shell.JythonShell + while locating com.google.gerrit.pgm.shell.InteractiveShell +---- + +Errors during processing of the startup script, 'Startup.py', are logged +to the error log: + +---- +[2012-04-17 14:20:30,558] INFO com.google.gerrit.pgm.shell.JythonShell : Jython shell instance created. +[2012-04-17 14:20:38,005] ERROR com.google.gerrit.pgm.shell.JythonShell : Exception occured while loading file Startup.py : +java.lang.reflect.InvocationTargetException + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at com.google.gerrit.pgm.shell.JythonShell.runMethod0(JythonShell.java:112) + at com.google.gerrit.pgm.shell.JythonShell.execFile(JythonShell.java:194) + at com.google.gerrit.pgm.shell.JythonShell.reload(JythonShell.java:178) + at com.google.gerrit.pgm.shell.JythonShell.run(JythonShell.java:152) + at com.google.gerrit.pgm.Daemon.run(Daemon.java:190) + at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:67) + at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) + at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.lang.reflect.Method.invoke(Method.java:616) + at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:167) + at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:91) + at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:49) + at Main.main(Main.java:25) +Caused by: Traceback (most recent call last): + File "/home/user/.gerritcodereview/Startup.py", line 1, in <module> + Test +NameError: name 'Test' is not defined +---- + +Those errors are non-fatal. System and user scripts can be loaded again +by issuing the following command in the Gerrit Inspector console: + +---- +Shell.reload() +---- + +LOGGING +------- +Error and warning messages from the server are automatically written +to the log file under '$site_path/logs/error_log'. + +Output and error messages (including Java and Python exceptions) +resulting from interactive work are logged to the console. + +KNOWN ISSUES +------------ +The Inspector does not yet recognize Google Guice bindings. + +IMPORTANT: Using the Inspector may void your warranty. + +GERRIT +------ +Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt index 5e10a62..8daacad 100644 --- a/Documentation/dev-plugins.txt +++ b/Documentation/dev-plugins.txt
@@ -38,7 +38,7 @@ ---- mvn archetype:generate -DarchetypeGroupId=com.google.gerrit \ -DarchetypeArtifactId=gerrit-plugin-archetype \ - -DarchetypeVersion=2.8-SNAPSHOT \ + -DarchetypeVersion=2.9-SNAPSHOT \ -DgroupId=com.google.gerrit \ -DartifactId=testPlugin ---- @@ -191,6 +191,29 @@ } ---- +A plugin can get its canonical web URL injected at runtime: + +[source,java] +---- +public class MyClass { + + private final String url; + + @Inject + public MyClass(@PluginCanonicalWebUrl String url) { + this.url = url; + } + + [...] +} +---- + +The URL is composed of the server's canonical web URL and the plugin's +name, i.e. `http://review.example.com:8080/plugin-name`. + +The canonical web URL may be injected into any .jar plugin regardless of +whether or not the plugin provides an HTTP servlet. + [[reload_method]] Reload Method ~~~~~~~~~~~~~
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt index ced8648..728c8dc 100644 --- a/Documentation/dev-readme.txt +++ b/Documentation/dev-readme.txt
@@ -106,6 +106,43 @@ java -jar buck-out/gen/gerrit.war daemon -d ../test_site ---- +Running the Daemon with Gerrit Inspector +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +link:dev-inspector.html[Gerrit Inspector] is an interactive scriptable +environment to inspect and modify internal state of the system. + +This environment is available on the system console after +the system starts. Leaving the Inspector will shutdown the Gerrit +instance. + +The environment allows interactive work as well as running of +Python scripts for troubleshooting. + +Gerrit Inspect can be started by adding '-s' option to the +command used to launch the daemon: + +---- + java -jar buck-out/gen/gerrit.war daemon -d ../test_site -s +---- + +Gerrit Inspector examines Java libraries first, then loads +its initialization scripts and then starts a command line +prompt on the console: + +---- + Welcome to the Gerrit Inspector + Enter help() to see the above again, EOF to quit and stop Gerrit + Jython 2.5.2 (Release_2_5_2:7206, Mar 2 2011, 23:12:06) + [OpenJDK 64-Bit Server VM (Sun Microsystems Inc.)] on java1.6.0 running for Gerrit 2.3-rc0-163-g01967ef + >>> +---- + +With the Inspector enabled Gerrit can be used normally and all +interfaces (HTTP, SSH etc.) are available. + +Care must be taken not to modify internal state of the system +when using the Inspector. Querying the Database ~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/json.txt b/Documentation/json.txt index 2836e5b..9278cde 100644 --- a/Documentation/json.txt +++ b/Documentation/json.txt
@@ -72,6 +72,9 @@ submitRecords:: The <<submitRecord,submitRecord attribute>> contains information about whether this change has been or can be submitted. +allReviewers:: List of all reviewers in <<account,account attribute>> +which are added to a change. + [[trackingid]] trackingid ----------
diff --git a/Documentation/pgm-daemon.txt b/Documentation/pgm-daemon.txt index ce88ab7..4b920ea 100644 --- a/Documentation/pgm-daemon.txt +++ b/Documentation/pgm-daemon.txt
@@ -16,6 +16,7 @@ [\--slave] [\--headless] [\--init] + [-s] DESCRIPTION ----------- @@ -68,6 +69,14 @@ Run init before starting the daemon. This will create a new site or upgrade an existing site. +\--s:: + Start link:dev-inspector.html[Gerrit Inspector] on the console, a + built-in interactive inspection environment to assist debugging and + troubleshooting of Gerrit code. ++ +This options requires 'jython.jar' from the http://www.jython.org[Jython distribution] +to be present in '$site_path/lib' directory. + CONTEXT ------- This command can only be run on a server which has direct
diff --git a/Documentation/rest-api-documentation.txt b/Documentation/rest-api-documentation.txt new file mode 100644 index 0000000..db7dc35 --- /dev/null +++ b/Documentation/rest-api-documentation.txt
@@ -0,0 +1,151 @@ +Gerrit Code Review - /Documentation/ REST API +============================================= + +This page describes the documentation search related REST endpoints. +Please also take note of the general information on the +link:rest-api.html[REST API]. + +Please note that this feature is only usable with documentation built-in. +You'll need to +`buck build :withdocs` +or +`buck build :release` +to test this feature. + +[[documentation-endpoints]] +Documentation Search Endpoints +------------------------------ + +[[search-documentation]] +Search Documentation +~~~~~~~~~~~~~~~~~~~~ +[verse] +'GET /Documentation/' + +With `q` parameter, search our documentation index for the terms. + +A list of link:#doc-result[DocResult] entities is returned describing the +results. + +.Request +---- + GET /Documentation/?q=test HTTP/1.0 +---- + +.Response +---- + HTTP/1.1 200 OK + Content-Disposition: attachment + Content-Type: application/json; charset=UTF-8 + + )]}' + [ + { + "title": "Gerrit Code Review - REST API Developers\u0027 Notes", + "url": "Documentation/dev-rest-api.html" + }, + { + "title": "Gerrit Code Review - REST API", + "url": "Documentation/rest-api.html" + }, + { + "title": "Gerrit Code Review - JavaScript API", + "url": "Documentation/js-api.html" + }, + { + "title": "Gerrit Code Review - /plugins/ REST API", + "url": "Documentation/rest-api-plugins.html" + }, + { + "title": "Gerrit Code Review - /config/ REST API", + "url": "Documentation/rest-api-config.html" + }, + { + "title": "Gerrit Code Review for Git", + "url": "Documentation/index.html" + }, + { + "title": "Gerrit Code Review - /access/ REST API", + "url": "Documentation/rest-api-access.html" + }, + { + "title": "Gerrit Code Review - Plugin Development", + "url": "Documentation/dev-plugins.html" + }, + { + "title": "Gerrit Code Review - Developer Setup", + "url": "Documentation/dev-readme.html" + }, + { + "title": "Gerrit Code Review - Hooks", + "url": "Documentation/config-hooks.html" + }, + { + "title": "Change Screen - Introduction", + "url": "Documentation/intro-change-screen.html" + }, + { + "title": "Gerrit Code Review - /groups/ REST API", + "url": "Documentation/rest-api-groups.html" + }, + { + "title": "Gerrit Code Review - /accounts/ REST API", + "url": "Documentation/rest-api-accounts.html" + }, + { + "title": "Gerrit Code Review - /projects/ REST API", + "url": "Documentation/rest-api-documentation.html" + }, + { + "title": "Gerrit Code Review - /projects/ REST API", + "url": "Documentation/rest-api-projects.html" + }, + { + "title": "Gerrit Code Review - Prolog Submit Rules Cookbook", + "url": "Documentation/prolog-cookbook.html" + }, + { + "title": "Gerrit Code Review - /changes/ REST API", + "url": "Documentation/rest-api-changes.html" + }, + { + "title": "Gerrit Code Review - Configuration", + "url": "Documentation/config-gerrit.html" + }, + { + "title": "Gerrit Code Review - Access Controls", + "url": "Documentation/access-control.html" + }, + { + "title": "Gerrit Code Review - Licenses", + "url": "Documentation/licenses.html" + } + ] +---- + +.Query documentation +**** +get::/Documentation/?q=keyword +**** + + +[[json-entities]] +JSON Entities +------------- + +[[doc-result]] +DocResult +~~~~~~~~~ +The `DocResult` entity contains information about a document. + +[options="header",width="50%",cols="1,^2,4"] +|========================= +|Field Name ||Description +|`title` ||The title of the document. +|`url` ||The URL of the document. +|========================= + + +GERRIT +------ +Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/rest-api-plugins.txt b/Documentation/rest-api-plugins.txt index 2cc80f0..0c69f7d 100644 --- a/Documentation/rest-api-plugins.txt +++ b/Documentation/rest-api-plugins.txt
@@ -45,12 +45,12 @@ "delete-project": { "kind": "gerritcodereview#plugin", "id": "delete-project", - "version": "2.8-SNAPSHOT" + "version": "2.9-SNAPSHOT" }, "reviewers-by-blame": { "kind": "gerritcodereview#plugin", "id": "reviewers-by-blame", - "version": "2.8-SNAPSHOT", + "version": "2.9-SNAPSHOT", "disabled": true } }
diff --git a/Documentation/rest-api.txt b/Documentation/rest-api.txt index 7eed6ef..788f222 100644 --- a/Documentation/rest-api.txt +++ b/Documentation/rest-api.txt
@@ -23,6 +23,8 @@ Plugin related REST endpoints link:rest-api-projects.html[/projects/]:: Project related REST endpoints +link:rest-api-documentation.html[/Documentation/]:: + Documentation related REST endpoints Protocol Details ----------------
diff --git a/VERSION b/VERSION index 23c7033..6a132bb 100644 --- a/VERSION +++ b/VERSION
@@ -2,4 +2,4 @@ # Used by :api_install and :api_deploy targets # when talking to the destination repository. # -GERRIT_VERSION = '2.8-SNAPSHOT' +GERRIT_VERSION = '2.9-SNAPSHOT'
diff --git a/gerrit-acceptance-tests/BUCK b/gerrit-acceptance-tests/BUCK index f762c1e..11311e8 100644 --- a/gerrit-acceptance-tests/BUCK +++ b/gerrit-acceptance-tests/BUCK
@@ -11,6 +11,7 @@ '//gerrit-pgm:pgm', '//gerrit-reviewdb:server', '//gerrit-server:server', + '//gerrit-server:testutil', '//gerrit-sshd:sshd', '//lib:args4j',
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java index adb346f..784b461 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -30,7 +30,8 @@ return new Statement() { @Override public void evaluate() throws Throwable { - beforeTest(config(description)); + boolean mem = description.getAnnotation(UseLocalDisk.class) == null; + beforeTest(config(description), mem); base.evaluate(); afterTest(); } @@ -53,8 +54,8 @@ } } - private void beforeTest(Config cfg) throws Exception { - server = GerritServer.start(cfg); + private void beforeTest(Config cfg, boolean memory) throws Exception { + server = GerritServer.start(cfg, memory); server.getTestInjector().injectMembers(this); }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java index f97d2b9..daf9d38 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
@@ -14,18 +14,19 @@ package com.google.gerrit.acceptance; -import com.google.gerrit.lifecycle.LifecycleManager; +import com.google.common.collect.ImmutableList; import com.google.gerrit.pgm.Daemon; import com.google.gerrit.pgm.Init; import com.google.gerrit.server.config.FactoryModule; +import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.util.SocketUtil; import com.google.inject.Injector; +import com.google.inject.Key; import com.google.inject.Module; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.RepositoryCache; -import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.FS; import java.io.File; @@ -46,8 +47,7 @@ public class GerritServer { /** Returns fully started Gerrit server */ - static GerritServer start(Config base) throws Exception { - final File site = initSite(base); + static GerritServer start(Config base, boolean memory) throws Exception { final CyclicBarrier serverStarted = new CyclicBarrier(2); final Daemon daemon = new Daemon(new Runnable() { public void run() { @@ -61,21 +61,34 @@ } }); - ExecutorService daemonService = Executors.newSingleThreadExecutor(); - daemonService.submit(new Callable<Void>() { - public Void call() throws Exception { - int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" }); - if (rc != 0) { - System.out.println("Failed to start Gerrit daemon. Check " - + site.getPath() + "/logs/error_log"); - serverStarted.reset(); - } - return null; - }; - }); - - serverStarted.await(); - System.out.println("Gerrit Server Started"); + final File site; + ExecutorService daemonService = null; + if (memory) { + site = null; + Config cfg = base != null ? base : new Config(); + mergeTestConfig(cfg); + cfg.setBoolean("httpd", null, "requestLog", false); + cfg.setBoolean("sshd", null, "requestLog", false); + daemon.setDatabaseForTesting(ImmutableList.<Module>of( + new InMemoryTestingDatabaseModule(cfg))); + daemon.start(); + } else { + site = initSite(base); + daemonService = Executors.newSingleThreadExecutor(); + daemonService.submit(new Callable<Void>() { + public Void call() throws Exception { + int rc = daemon.main(new String[] {"-d", site.getPath(), "--headless" }); + if (rc != 0) { + System.out.println("Failed to start Gerrit daemon. Check " + + site.getPath() + "/logs/error_log"); + serverStarted.reset(); + } + return null; + }; + }); + serverStarted.await(); + System.out.println("Gerrit Server Started"); + } Injector i = createTestInjector(daemon); return new GerritServer(site, i, daemon, daemonService); @@ -91,14 +104,22 @@ throw new RuntimeException("Couldn't initialize site"); } - InetSocketAddress http = newPort(); - InetSocketAddress sshd = newPort(); - String url = "http://" + format(http) + "/"; MergeableFileBasedConfig cfg = new MergeableFileBasedConfig( new File(new File(tmp, "etc"), "gerrit.config"), FS.DETECTED); cfg.load(); cfg.merge(base); + mergeTestConfig(cfg); + cfg.save(); + return tmp; + } + + private static void mergeTestConfig(Config cfg) + throws IOException { + InetSocketAddress http = newPort(); + InetSocketAddress sshd = newPort(); + String url = "http://" + format(http) + "/"; + cfg.setString("gerrit", null, "canonicalWebUrl", url); cfg.setString("httpd", null, "listenUrl", url); cfg.setString("sshd", null, "listenAddress", format(sshd)); @@ -106,8 +127,6 @@ cfg.setBoolean("sendemail", null, "enable", false); cfg.setInt("cache", "projects", "checkFrequency", 0); cfg.setInt("plugins", null, "checkFrequency", 0); - cfg.save(); - return tmp; } private static String format(InetSocketAddress s) { @@ -169,11 +188,8 @@ this.daemon = daemon; this.daemonService = daemonService; - FileBasedConfig cfg = new FileBasedConfig( - new File(new File(sitePath, "etc"), "gerrit.config"), - FS.DETECTED); - cfg.load(); - + Config cfg = testInjector.getInstance( + Key.get(Config.class, GerritServerConfig.class)); url = cfg.getString("gerrit", null, "canonicalWebUrl"); URI uri = URI.create(url); @@ -200,12 +216,15 @@ } void stop() throws Exception { - LifecycleManager manager = get(daemon, "manager"); - System.out.println("Gerrit Server Shutdown"); - manager.stop(); - daemonService.shutdownNow(); - daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); - TempFileUtil.recursivelyDelete(sitePath); + daemon.getLifecycleManager().stop(); + if (daemonService != null) { + System.out.println("Gerrit Server Shutdown"); + daemonService.shutdownNow(); + daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); + } + if (sitePath != null) { + TempFileUtil.recursivelyDelete(sitePath); + } RepositoryCache.clear(); } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java new file mode 100644 index 0000000..5576c4f --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -0,0 +1,129 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.acceptance; + +import static com.google.inject.Scopes.SINGLETON; + +import com.google.gerrit.extensions.events.LifecycleListener; +import com.google.gerrit.lifecycle.LifecycleModule; +import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.config.GerritServerConfig; +import com.google.gerrit.server.config.SitePath; +import com.google.gerrit.server.config.SitePaths; +import com.google.gerrit.server.config.TrackingFooters; +import com.google.gerrit.server.config.TrackingFootersProvider; +import com.google.gerrit.server.git.GitRepositoryManager; +import com.google.gerrit.server.schema.DataSourceType; +import com.google.gerrit.server.schema.SchemaModule; +import com.google.gerrit.server.schema.SchemaVersion; +import com.google.gerrit.testutil.InMemoryDatabase; +import com.google.gerrit.testutil.InMemoryH2Type; +import com.google.gerrit.testutil.InMemoryRepositoryManager; +import com.google.gwtorm.server.OrmException; +import com.google.gwtorm.server.OrmRuntimeException; +import com.google.gwtorm.server.SchemaFactory; +import com.google.inject.AbstractModule; +import com.google.inject.Inject; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.TypeLiteral; + +import org.apache.sshd.common.KeyPairProvider; +import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; +import org.eclipse.jgit.lib.Config; + +import java.io.File; + +class InMemoryTestingDatabaseModule extends AbstractModule { + private final Config cfg; + + InMemoryTestingDatabaseModule(Config cfg) { + this.cfg = cfg; + } + + @Override + protected void configure() { + bind(Config.class) + .annotatedWith(GerritServerConfig.class) + .toInstance(cfg); + + bind(File.class) + .annotatedWith(SitePath.class) + .toInstance(new File("UNIT_TEST_GERRIT_SITE")); + + bind(GitRepositoryManager.class) + .toInstance(new InMemoryRepositoryManager()); + + bind(DataSourceType.class).to(InMemoryH2Type.class); + bind(InMemoryDatabase.class).in(SINGLETON); + bind(new TypeLiteral<SchemaFactory<ReviewDb>>() {}) + .to(InMemoryDatabase.class); + + install(new LifecycleModule() { + @Override + protected void configure() { + listener().to(CreateDatabase.class); + } + }); + + bind(SitePaths.class); + bind(TrackingFooters.class) + .toProvider(TrackingFootersProvider.class) + .in(SINGLETON); + + install(new SchemaModule()); + bind(SchemaVersion.class).to(SchemaVersion.C); + } + + @Provides + @Singleton + KeyPairProvider createHostKey() { + return getHostKeys(); + } + + private static SimpleGeneratorHostKeyProvider keys; + + private static synchronized KeyPairProvider getHostKeys() { + if (keys == null) { + keys = new SimpleGeneratorHostKeyProvider(); + keys.setAlgorithm("RSA"); + keys.loadKeys(); + } + return keys; + } + + static class CreateDatabase implements LifecycleListener { + private final InMemoryDatabase mem; + + @Inject + CreateDatabase(InMemoryDatabase mem) { + this.mem = mem; + } + + @Override + public void start() { + try { + mem.create(); + } catch (OrmException e) { + throw new OrmRuntimeException(e); + } + } + + @Override + public void stop() { + mem.drop(); + } + } +} \ No newline at end of file
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseLocalDisk.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseLocalDisk.java new file mode 100644 index 0000000..f9367ec --- /dev/null +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseLocalDisk.java
@@ -0,0 +1,26 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.acceptance; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({METHOD}) +@Retention(RUNTIME) +public @interface UseLocalDisk { +}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GarbageCollectionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GarbageCollectionIT.java index a1ad627..7057a4f 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GarbageCollectionIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GarbageCollectionIT.java
@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.RestSession; import com.google.gerrit.acceptance.SshSession; import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.acceptance.UseLocalDisk; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.config.AllProjectsName; import com.google.gwtorm.server.OrmException; @@ -83,8 +84,8 @@ } @Test + @UseLocalDisk public void testGcOneProject() throws JSchException, IOException { - assertEquals(HttpStatus.SC_OK, POST("/projects/" + allProjects.get() + "/gc")); gcAssert.assertHasPackFile(allProjects); gcAssert.assertHasNoPackFile(project1, project2);
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java index e93973b..f10258c 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/GarbageCollectionIT.java
@@ -24,6 +24,7 @@ import com.google.gerrit.acceptance.GcAssert; import com.google.gerrit.acceptance.SshSession; import com.google.gerrit.acceptance.TestAccount; +import com.google.gerrit.acceptance.UseLocalDisk; import com.google.gerrit.common.data.GarbageCollectionResult; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.config.AllProjectsName; @@ -83,6 +84,7 @@ } @Test + @UseLocalDisk public void testGc() throws JSchException, IOException { String response = sshSession.exec("gerrit gc \"" + project1.get() + "\" \"" @@ -94,6 +96,7 @@ } @Test + @UseLocalDisk public void testGcAll() throws JSchException, IOException { String response = sshSession.exec("gerrit gc --all"); assertFalse(sshSession.hasError()); @@ -110,6 +113,7 @@ } @Test + @UseLocalDisk public void testGcAlreadyScheduled() { gcQueue.addAll(Arrays.asList(project1)); GarbageCollectionResult result = garbageCollectionFactory.create().run(
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginCanonicalWebUrl.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginCanonicalWebUrl.java new file mode 100644 index 0000000..fd14429 --- /dev/null +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/annotations/PluginCanonicalWebUrl.java
@@ -0,0 +1,42 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.extensions.annotations; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import com.google.inject.BindingAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Annotation applied to a String containing the plugin canonical web URL. + * <p> + * A plugin or extension may receive this string by Guice injection to discover + * the canonical web URL under which the plugin is available: + * + * <pre> + * @Inject + * MyType(@PluginCanonicalWebUrl String myUrl) { + * ... + * } + * </pre> + */ +@Target({ElementType.PARAMETER, ElementType.FIELD}) +@Retention(RUNTIME) +@BindingAnnotation +public @interface PluginCanonicalWebUrl { +}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java index 331afee..da88034 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
@@ -102,9 +102,11 @@ protected void initColumnHeaders() { super.initColumnHeaders(); if (Gerrit.getGitwebLink() != null) { - table.setText(0, 3, Util.C.projectRepoBrowser()); + table.setText(0, ProjectsTable.C_REPO_BROWSER, + Util.C.projectRepoBrowser()); table.getFlexCellFormatter(). - addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader()); + addStyleName(0, ProjectsTable.C_REPO_BROWSER, + Gerrit.RESOURCES.css().dataHeader()); } } @@ -122,7 +124,8 @@ super.insert(row, k); if (Gerrit.getGitwebLink() != null) { table.getFlexCellFormatter(). - addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell()); + addStyleName(row, ProjectsTable.C_REPO_BROWSER, + Gerrit.RESOURCES.css().dataCell()); } } @@ -131,11 +134,12 @@ FlowPanel fp = new FlowPanel(); fp.add(new ProjectSearchLink(k.name_key())); fp.add(new HighlightingInlineHyperlink(k.name(), link(k), subname)); - table.setWidget(row, 1, fp); - table.setText(row, 2, k.description()); + table.setWidget(row, ProjectsTable.C_NAME, fp); + table.setText(row, ProjectsTable.C_DESCRIPTION, k.description()); GitwebLink l = Gerrit.getGitwebLink(); if (l != null) { - table.setWidget(row, 3, new Anchor(l.getLinkName(), false, l.toProject(k + table.setWidget(row, ProjectsTable.C_REPO_BROWSER, + new Anchor(l.getLinkName(), false, l.toProject(k .name_key()))); }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java index 052878b..a99348d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
@@ -25,6 +25,9 @@ import java.util.List; public class ProjectsTable extends NavigationTable<ProjectInfo> { + public static final int C_NAME = 1; + public static final int C_DESCRIPTION = 2; + public static final int C_REPO_BROWSER = 3; public ProjectsTable() { super(Util.C.projectItemHelp()); @@ -32,12 +35,12 @@ } protected void initColumnHeaders() { - table.setText(0, 1, Util.C.projectName()); - table.setText(0, 2, Util.C.projectDescription()); + table.setText(0, C_NAME, Util.C.projectName()); + table.setText(0, C_DESCRIPTION, Util.C.projectDescription()); final FlexCellFormatter fmt = table.getFlexCellFormatter(); - fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader()); - fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader()); + fmt.addStyleName(0, C_NAME, Gerrit.RESOURCES.css().dataHeader()); + fmt.addStyleName(0, C_DESCRIPTION, Gerrit.RESOURCES.css().dataHeader()); } @Override @@ -75,16 +78,16 @@ applyDataRowStyle(row); final FlexCellFormatter fmt = table.getFlexCellFormatter(); - fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell()); - fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().projectNameColumn()); - fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell()); + fmt.addStyleName(row, C_NAME, Gerrit.RESOURCES.css().dataCell()); + fmt.addStyleName(row, C_NAME, Gerrit.RESOURCES.css().projectNameColumn()); + fmt.addStyleName(row, C_DESCRIPTION, Gerrit.RESOURCES.css().dataCell()); populate(row, k); } protected void populate(final int row, final ProjectInfo k) { - table.setText(row, 1, k.name()); - table.setText(row, 2, k.description()); + table.setText(row, C_NAME, k.name()); + table.setText(row, C_DESCRIPTION, k.description()); setRowItem(row, k); }
diff --git a/gerrit-httpd/BUCK b/gerrit-httpd/BUCK index 512e6e6..c20b589 100644 --- a/gerrit-httpd/BUCK +++ b/gerrit-httpd/BUCK
@@ -1,4 +1,6 @@ -SRCS = glob(['src/main/java/**/*.java']) +SRCS = glob( + ['src/main/java/**/*.java'], +) RESOURCES = glob(['src/main/resources/**/*']) java_library2( @@ -30,6 +32,7 @@ '//lib/jgit:jgit', '//lib/jgit:jgit-servlet', '//lib/log:api', + '//lib/lucene:core', ], compile_deps = ['//lib:servlet-api-3_0'], visibility = ['PUBLIC'],
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java index 2980159..79aca6d 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -136,7 +136,7 @@ config.setReportBugUrl(null); } - config.setGitBasicAuth(authConfig.isGitBasichAuth()); + config.setGitBasicAuth(authConfig.isGitBasicAuth()); final Set<Account.FieldName> fields = new HashSet<Account.FieldName>(); for (final Account.FieldName n : Account.FieldName.values()) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpModule.java index 6ca9949..4f4c783 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpModule.java
@@ -34,7 +34,7 @@ Class<? extends Filter> authFilter; if (authConfig.isTrustContainerAuth()) { authFilter = ContainerAuthFilter.class; - } else if (authConfig.isGitBasichAuth()) { + } else if (authConfig.isGitBasicAuth()) { authFilter = ProjectBasicAuthFilter.class; } else { authFilter = ProjectDigestFilter.class;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java index bf39bfb..3c4dfc5 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -30,6 +30,7 @@ import com.google.gerrit.httpd.rpc.change.ChangesRestApiServlet; import com.google.gerrit.httpd.rpc.change.DeprecatedChangeQueryServlet; import com.google.gerrit.httpd.rpc.config.ConfigRestApiServlet; +import com.google.gerrit.httpd.rpc.doc.QueryDocumentationFilter; import com.google.gerrit.httpd.rpc.group.GroupsRestApiServlet; import com.google.gerrit.httpd.rpc.project.ProjectsRestApiServlet; import com.google.gerrit.reviewdb.client.Change; @@ -110,6 +111,8 @@ serveRegex("^/(?:a/)?groups/(.*)?$").with(GroupsRestApiServlet.class); serveRegex("^/(?:a/)?projects/(.*)?$").with(ProjectsRestApiServlet.class); + filter("/Documentation/").through(QueryDocumentationFilter.class); + if (cfg.deprecatedQuery) { serve("/query").with(DeprecatedChangeQueryServlet.class); }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java index 28e361c..2dde16e 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -168,7 +168,7 @@ Element userlistElement = HtmlDomUtil.find(doc, "userlist"); ReviewDb db = schema.open(); try { - ResultSet<Account> accounts = db.accounts().firstNById(5); + ResultSet<Account> accounts = db.accounts().firstNById(100); for (Account a : accounts) { String displayName; if (a.getUserName() != null) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java index 517b017..2e1cc06 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -607,7 +607,7 @@ throw new InstantiationException("Cannot make " + type); } - private static void replyJson(@Nullable HttpServletRequest req, + public static void replyJson(@Nullable HttpServletRequest req, HttpServletResponse res, Multimap<String, String> config, Object result)
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/doc/QueryDocumentationFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/doc/QueryDocumentationFilter.java new file mode 100644 index 0000000..002b520 --- /dev/null +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/doc/QueryDocumentationFilter.java
@@ -0,0 +1,74 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.httpd.rpc.doc; + +import com.google.common.base.Strings; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import com.google.gerrit.httpd.restapi.RestApiServlet; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor.DocQueryException; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor.DocResult; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Singleton +public class QueryDocumentationFilter implements Filter { + private final QueryDocumentationExecutor searcher; + + @Inject + QueryDocumentationFilter(QueryDocumentationExecutor searcher) { + this.searcher = searcher; + } + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + if ("GET".equals(req.getMethod()) + && !Strings.isNullOrEmpty(req.getParameter("q"))) { + HttpServletResponse rsp = (HttpServletResponse) response; + try { + List<DocResult> result = searcher.doQuery(request.getParameter("q")); + Multimap<String, String> config = LinkedHashMultimap.create(); + RestApiServlet.replyJson(req, rsp, config, result); + } catch (DocQueryException e) { + rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } else { + chain.doFilter(request, response); + } + } +}
diff --git a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java index 2dd20a2..44226bc 100644 --- a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java +++ b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -302,6 +302,7 @@ } private volatile static File myArchive; + private volatile static File myHome; /** * Locate the JAR/WAR file we were launched from. @@ -459,42 +460,26 @@ return tmp; } + /** + * Provide path to a working directory + * + * @return local path of the working directory or null if cannot be determined + */ + public static File getHomeDirectory() { + if (myHome == null) { + myHome = locateHomeDirectory(); + } + return myHome; + } + + private static File tmproot() { File tmp; String gerritTemp = System.getenv("GERRIT_TMP"); if (gerritTemp != null && gerritTemp.length() > 0) { tmp = new File(gerritTemp); } else { - // Try to find the user's home directory. If we can't find it - // return null so the JVM's default temporary directory is used - // instead. This is probably /tmp or /var/tmp. - // - String userHome = System.getProperty("user.home"); - if (userHome == null || "".equals(userHome)) { - userHome = System.getenv("HOME"); - if (userHome == null || "".equals(userHome)) { - System.err.println("warning: cannot determine home directory"); - System.err.println("warning: using system temporary directory instead"); - return null; - } - } - - // Ensure the home directory exists. If it doesn't, try to make it. - // - final File home = new File(userHome); - if (!home.exists()) { - if (home.mkdirs()) { - System.err.println("warning: created " + home.getAbsolutePath()); - } else { - System.err.println("warning: " + home.getAbsolutePath() + " not found"); - System.err.println("warning: using system temporary directory instead"); - return null; - } - } - - // Use $HOME/.gerritcodereview/tmp for our temporary file area. - // - tmp = new File(new File(home, ".gerritcodereview"), "tmp"); + tmp = new File(getHomeDirectory(), "tmp"); } if (!tmp.exists() && !tmp.mkdirs()) { System.err.println("warning: cannot create " + tmp.getAbsolutePath()); @@ -527,6 +512,49 @@ } } + private static File locateHomeDirectory() { + // Try to find the user's home directory. If we can't find it + // return null so the JVM's default temporary directory is used + // instead. This is probably /tmp or /var/tmp. + // + String userHome = System.getProperty("user.home"); + if (userHome == null || "".equals(userHome)) { + userHome = System.getenv("HOME"); + if (userHome == null || "".equals(userHome)) { + System.err.println("warning: cannot determine home directory"); + System.err.println("warning: using system temporary directory instead"); + return null; + } + } + + // Ensure the home directory exists. If it doesn't, try to make it. + // + final File home = new File(userHome); + if (!home.exists()) { + if (home.mkdirs()) { + System.err.println("warning: created " + home.getAbsolutePath()); + } else { + System.err.println("warning: " + home.getAbsolutePath() + " not found"); + System.err.println("warning: using system temporary directory instead"); + return null; + } + } + + // Use $HOME/.gerritcodereview/tmp for our temporary file area. + // + final File gerrithome = new File(home, ".gerritcodereview"); + if (!gerrithome.exists() && !gerrithome.mkdirs()) { + System.err.println("warning: cannot create " + gerrithome.getAbsolutePath()); + System.err.println("warning: using system temporary directory instead"); + return null; + } + try { + return gerrithome.getCanonicalFile(); + } catch (IOException e) { + return gerrithome; + } + } + private GerritLauncher() { } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java index 891dadc..35d8e76 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
@@ -16,6 +16,8 @@ import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Objects; import com.google.gerrit.common.ChangeHookRunner; import com.google.gerrit.httpd.AllRequestFilter; import com.google.gerrit.httpd.CacheBasedWebSession; @@ -33,6 +35,7 @@ import com.google.gerrit.pgm.http.jetty.JettyEnv; import com.google.gerrit.pgm.http.jetty.JettyModule; import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter; +import com.google.gerrit.pgm.shell.JythonShell; import com.google.gerrit.pgm.util.ErrorLogFile; import com.google.gerrit.pgm.util.GarbageCollectionLogFile; import com.google.gerrit.pgm.util.LogFileCompressor; @@ -57,18 +60,22 @@ import com.google.gerrit.server.patch.IntraLineWorkerPool; import com.google.gerrit.server.plugins.PluginGuiceEnvironment; import com.google.gerrit.server.plugins.PluginRestApiModule; +import com.google.gerrit.server.schema.DataSourceProvider; import com.google.gerrit.server.schema.SchemaVersionCheck; import com.google.gerrit.server.ssh.NoSshKeyCache; import com.google.gerrit.server.ssh.NoSshModule; import com.google.gerrit.solr.SolrIndexModule; +import com.google.gerrit.sshd.SshHostKeyModule; import com.google.gerrit.sshd.SshKeyCacheImpl; import com.google.gerrit.sshd.SshModule; import com.google.gerrit.sshd.commands.MasterCommandModule; import com.google.gerrit.sshd.commands.SlaveCommandModule; import com.google.inject.AbstractModule; +import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Provider; +import com.google.inject.Stage; import org.kohsuke.args4j.Option; import org.slf4j.Logger; @@ -109,6 +116,9 @@ @Option(name = "--console-log", usage = "Log to console (not $site_path/logs)") private boolean consoleLog; + @Option(name = "-s", usage = "Start interactive shell") + private boolean inspector; + @Option(name = "--run-id", usage = "Cookie to store in $site_path/logs/gerrit.run") private String runId; @@ -127,12 +137,14 @@ private Injector webInjector; private Injector httpdInjector; private File runFile; + private boolean test; private Runnable serverStarted; public Daemon() { } + @VisibleForTesting public Daemon(Runnable serverStarted) { this.serverStarted = serverStarted; } @@ -176,22 +188,7 @@ } try { - dbInjector = createDbInjector(MULTI_USER); - cfgInjector = createCfgInjector(); - sysInjector = createSysInjector(); - sysInjector.getInstance(PluginGuiceEnvironment.class) - .setCfgInjector(cfgInjector); - manager.add(dbInjector, cfgInjector, sysInjector); - - if (sshd) { - initSshd(); - } - - if (httpd) { - initHttpd(); - } - - manager.start(); + start(); RuntimeShutdown.add(new Runnable() { @Override public void run() { @@ -224,7 +221,15 @@ serverStarted.run(); } - RuntimeShutdown.waitFor(); + if (inspector) { + JythonShell shell = new JythonShell(); + shell.set("m", manager); + shell.set("ds", dbInjector.getInstance(DataSourceProvider.class)); + shell.set("schk", dbInjector.getInstance(SchemaVersionCheck.class)); + shell.run(); + } else { + RuntimeShutdown.waitFor(); + } return 0; } catch (Throwable err) { log.error("Unable to start daemon", err); @@ -232,6 +237,45 @@ } } + @VisibleForTesting + public LifecycleManager getLifecycleManager() { + return manager; + } + + @VisibleForTesting + public void setDatabaseForTesting(List<Module> modules) { + dbInjector = Guice.createInjector(Stage.PRODUCTION, modules); + test = true; + headless = true; + } + + @VisibleForTesting + public void start() { + if (dbInjector == null) { + dbInjector = createDbInjector(MULTI_USER); + } + cfgInjector = createCfgInjector(); + sysInjector = createSysInjector(); + sysInjector.getInstance(PluginGuiceEnvironment.class) + .setCfgInjector(cfgInjector); + manager.add(dbInjector, cfgInjector, sysInjector); + + if (sshd) { + initSshd(); + } + + if (Objects.firstNonNull(httpd, true)) { + initHttpd(); + } + + manager.start(); + } + + @VisibleForTesting + public void stop() { + manager.stop(); + } + private String myVersion() { return com.google.gerrit.common.Version.getVersion(); } @@ -268,7 +312,7 @@ changeIndexModule = new NoIndexModule(); } modules.add(changeIndexModule); - if (httpd) { + if (Objects.firstNonNull(httpd, true)) { modules.add(new CanonicalWebUrlModule() { @Override protected Class<? extends Provider<String>> provider() { @@ -311,6 +355,9 @@ final List<Module> modules = new ArrayList<Module>(); if (sshd) { modules.add(sysInjector.getInstance(SshModule.class)); + if (!test) { + modules.add(new SshHostKeyModule()); + } if (slave) { modules.add(new SlaveCommandModule()); } else {
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java index f54b3c5..4f35f1c 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/GetUserFilter.java
@@ -50,7 +50,7 @@ Module(@GerritServerConfig final Config cfg) { URI[] urls = JettyServer.listenURLs(cfg); boolean reverseProxy = JettyServer.isReverseProxied(urls); - this.loggingEnabled = cfg.getBoolean("httpd", "requestlog", !reverseProxy); + this.loggingEnabled = cfg.getBoolean("httpd", "requestLog", !reverseProxy); } @Override
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java index da08804..e1d1281b 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -136,7 +136,7 @@ httpd.setThreadPool(threadPool(cfg)); Handler app = makeContext(env, cfg); - if (cfg.getBoolean("httpd", "requestlog", !reverseProxy)) { + if (cfg.getBoolean("httpd", "requestLog", !reverseProxy)) { RequestLogHandler handler = new RequestLogHandler(); handler.setRequestLog(new HttpLog(site, cfg)); handler.setHandler(app);
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/shell/JythonShell.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/shell/JythonShell.java new file mode 100644 index 0000000..4ad91d9 --- /dev/null +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/shell/JythonShell.java
@@ -0,0 +1,221 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.pgm.shell; + +import com.google.gerrit.launcher.GerritLauncher; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Properties; + +public class JythonShell { + private static final Logger log = LoggerFactory.getLogger(JythonShell.class); + private static final String STARTUP_RESOURCE = "com/google/gerrit/pgm/Startup.py"; + private static final String STARTUP_FILE = "Startup.py"; + + private Class<?> console; + private Class<?> pyObject; + private Class<?> pySystemState; + private Object shell; + private ArrayList <String> injectedVariables; + + public JythonShell() { + Properties env = new Properties(); + // Let us inspect private class members + env.setProperty("python.security.respectJavaAccessibility", "false"); + + File home = GerritLauncher.getHomeDirectory(); + if (home != null) { + env.setProperty("python.cachedir", new File(home, "jythoncache").getPath()); + } + + // For package introspection and "import com.google" to work, + // Jython needs to inspect actual .jar files (not just classloader) + StringBuilder classPath = new StringBuilder(); + final ClassLoader cl = getClass().getClassLoader(); + if (cl instanceof java.net.URLClassLoader) { + URLClassLoader ucl = (URLClassLoader) cl; + for (URL u : ucl.getURLs()) { + if ("file".equals(u.getProtocol())) { + if (classPath.length() > 0) { + classPath.append(java.io.File.pathSeparatorChar); + } + classPath.append(u.getFile()); + } + } + } + env.setProperty("java.class.path", classPath.toString()); + + console = findClass("org.python.util.InteractiveConsole"); + pyObject = findClass("org.python.core.PyObject"); + pySystemState = findClass("org.python.core.PySystemState"); + + runMethod(pySystemState, pySystemState, "initialize", + new Class[] { Properties.class, Properties.class }, + new Object[] { null, env } + ); + + try { + shell = console.newInstance(); + log.info("Jython shell instance created."); + } catch (InstantiationException e) { + throw noInterpreter(e); + } catch (IllegalAccessException e) { + throw noInterpreter(e); + } + injectedVariables = new ArrayList<String>(); + set("Shell", this); + } + + protected Object runMethod0(Class<?> klazz, Object instance, + String name, Class<?>[] sig, Object[] args) + throws InvocationTargetException { + try { + Method m; + m = klazz.getMethod(name, sig); + return m.invoke(instance, args); + } catch (NoSuchMethodException e) { + throw cannotStart(e); + } catch (SecurityException e) { + throw cannotStart(e); + } catch (IllegalArgumentException e) { + throw cannotStart(e); + } catch (IllegalAccessException e) { + throw cannotStart(e); + } + } + + protected Object runMethod(Class<?> klazz, Object instance, + String name, Class<?>[] sig, Object[] args) { + try { + return runMethod0(klazz, instance, name, sig, args); + } catch (InvocationTargetException e) { + throw cannotStart(e); + } + } + + protected Object runInterpreter(String name, Class<?>[] sig, Object[] args) { + return runMethod(console, shell, name, sig, args); + } + + protected String getDefaultBanner() { + return (String)runInterpreter("getDefaultBanner", + new Class[] { }, new Object[] { }); + } + + protected void printInjectedVariable(String id) { + runInterpreter("exec", + new Class[] { String.class }, + new Object[] { "print '\"%s\" is \"%s\"' % (\"" + id + "\", " + id + ")" } + ); + } + + public void run() { + for (String key : injectedVariables) { + printInjectedVariable(key); + } + reload(); + runInterpreter("interact", + new Class[] { String.class, pyObject }, + new Object[] { getDefaultBanner() + + " running for Gerrit " + com.google.gerrit.common.Version.getVersion(), + null }); + } + + public void set(String key, Object content) { + runInterpreter("set", + new Class[] { String.class, Object.class }, + new Object[] { key, content } + ); + injectedVariables.add(key); + } + + private static Class<?> findClass(String klazzname) { + try { + return Class.forName(klazzname); + } catch (ClassNotFoundException e) { + throw noShell("Class " + klazzname + " not found", e); + } + } + + public void reload() { + execResource(STARTUP_RESOURCE); + execFile(GerritLauncher.getHomeDirectory(), STARTUP_FILE); + } + + protected void execResource(final String p) { + InputStream in = JythonShell.class.getClassLoader().getResourceAsStream(p); + if (in != null) { + execStream(in, "resource " + p); + } else { + log.error("Cannot load resource " + p); + } + } + + protected void execFile(final File parent, final String p) { + try { + File script = new File(parent, p); + if (script.canExecute()) { + runMethod0(console, shell, "execfile", + new Class[] { String.class }, + new Object[] { script.getAbsolutePath() } + ); + } else { + log.info("User initialization file " + + script.getAbsolutePath() + + " is not found or not executable"); + } + } catch (InvocationTargetException e) { + log.error("Exception occured while loading file " + p + " : ", e); + } catch (SecurityException e) { + log.error("SecurityException occured while loading file " + p + " : ", e); + } + } + + protected void execStream(final InputStream in, final String p) { + try { + runMethod0(console, shell, "execfile", + new Class[] { InputStream.class, String.class }, + new Object[] { in, p } + ); + } catch (InvocationTargetException e) { + log.error("Exception occured while loading " + p + " : ", e); + } + } + + private static UnsupportedOperationException noShell(final String m, Throwable why) { + final String prefix = "Cannot create Jython shell: "; + final String postfix = "\n (You might need to install jython.jar in the lib directory)"; + return new UnsupportedOperationException(prefix + m + postfix, why); + } + + private static UnsupportedOperationException noInterpreter(Throwable why) { + final String msg = "Cannot create Python interpreter"; + return noShell(msg, why); + } + + private static UnsupportedOperationException cannotStart(Throwable why) { + final String msg = "Cannot start Jython shell"; + return new UnsupportedOperationException(msg, why); + } +}
diff --git a/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/Startup.py b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/Startup.py new file mode 100644 index 0000000..92d6e56 --- /dev/null +++ b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/Startup.py
@@ -0,0 +1,31 @@ +# Copyright (C) 2013 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ----------------------------------------------------------------------- +# Startup script for Gerrit Inspector - a Jython introspector +# ----------------------------------------------------------------------- + +import sys + +def help(): + for (n, v) in vars(sys.modules['__main__']).items(): + if not n.startswith("__") and not n in ['help', 'reload'] \ + and str(type(v)) != "<type 'javapackage'>" \ + and not str(v).startswith("<module"): + print "\"%s\" is \"%s\"" % (n, v) + print + print "Welcome to the Gerrit Inspector" + print "Enter help() to see the above again, EOF to quit and stop Gerrit" + +help()
diff --git a/gerrit-plugin-archetype/pom.xml b/gerrit-plugin-archetype/pom.xml index 1b33510..401f126 100644 --- a/gerrit-plugin-archetype/pom.xml +++ b/gerrit-plugin-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-archetype</artifactId> - <version>2.8-SNAPSHOT</version> + <version>2.9-SNAPSHOT</version> <name>Gerrit Code Review - Plugin Archetype</name> <properties>
diff --git a/gerrit-plugin-gwt-archetype/pom.xml b/gerrit-plugin-gwt-archetype/pom.xml index 3c4dc99..56e6c95 100644 --- a/gerrit-plugin-gwt-archetype/pom.xml +++ b/gerrit-plugin-gwt-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-gwt-archetype</artifactId> - <version>2.8-SNAPSHOT</version> + <version>2.9-SNAPSHOT</version> <name>Gerrit Code Review - Web Ui GWT Plugin Archetype</name> <properties>
diff --git a/gerrit-plugin-js-archetype/pom.xml b/gerrit-plugin-js-archetype/pom.xml index 681d7a9..eb32b11 100644 --- a/gerrit-plugin-js-archetype/pom.xml +++ b/gerrit-plugin-js-archetype/pom.xml
@@ -20,7 +20,7 @@ <groupId>com.google.gerrit</groupId> <artifactId>gerrit-plugin-js-archetype</artifactId> - <version>2.8-SNAPSHOT</version> + <version>2.9-SNAPSHOT</version> <name>Gerrit Code Review - Web UI JavaScript Plugin Archetype</name> <properties>
diff --git a/gerrit-server/BUCK b/gerrit-server/BUCK index 1db7555..8119502 100644 --- a/gerrit-server/BUCK +++ b/gerrit-server/BUCK
@@ -1,15 +1,28 @@ +CONSTANTS_SRC = [ + 'src/main/java/com/google/gerrit/server/documentation/Constants.java', +] + SRCS = glob([ - 'src/main/java/**/*.java', - 'src/test/java/com/google/gerrit/server/project/Util.java' -]) + 'src/main/java/**/*.java', + 'src/test/java/com/google/gerrit/server/project/Util.java', + ], + excludes = CONSTANTS_SRC, +) RESOURCES = glob(['src/main/resources/**/*']) +java_library2( + name = 'constants', + srcs = CONSTANTS_SRC, + visibility = ['PUBLIC'], +) + # TODO(sop) break up gerrit-server java_library(), its too big java_library2( name = 'server', srcs = SRCS, resources = RESOURCES, deps = [ + ':constants', '//gerrit-antlr:query_exception', '//gerrit-antlr:query_parser', '//gerrit-common:server', @@ -48,6 +61,9 @@ '//lib/joda:joda-time', '//lib/log:api', '//lib/prolog:prolog-cafe', + '//lib/lucene:analyzers-common', + '//lib/lucene:core', + '//lib/lucene:query-parser', ], compile_deps = [ '//lib/bouncycastle:bcprov',
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java index 0b414f2..6d01e7c5 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java
@@ -197,7 +197,7 @@ } /** Whether git-over-http should use Gerrit basic authentication scheme. */ - public boolean isGitBasichAuth() { + public boolean isGitBasicAuth() { return gitBasicAuth; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index 6a90165..1ed0baed 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -67,6 +67,7 @@ import com.google.gerrit.server.auth.UniversalAuthBackend; import com.google.gerrit.server.avatar.AvatarProvider; import com.google.gerrit.server.cache.CacheRemovalListener; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor; import com.google.gerrit.server.events.EventFactory; import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.git.ChangeCache; @@ -135,6 +136,7 @@ protected void configure() { bind(EmailExpander.class).toProvider(EmailExpanderProvider.class).in( SINGLETON); + bind(QueryDocumentationExecutor.class).in(SINGLETON); bind(IdGenerator.class); bind(RulesCache.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/data/ChangeAttribute.java b/gerrit-server/src/main/java/com/google/gerrit/server/data/ChangeAttribute.java index 7339829..5f5fd33 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/data/ChangeAttribute.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/data/ChangeAttribute.java
@@ -43,4 +43,5 @@ public List<DependencyAttribute> dependsOn; public List<DependencyAttribute> neededBy; public List<SubmitRecordAttribute> submitRecords; + public List<AccountAttribute> allReviewers; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/documentation/Constants.java b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/Constants.java new file mode 100644 index 0000000..bfa2de2 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/Constants.java
@@ -0,0 +1,24 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.documentation; + +public class Constants { + + public static final String DOC_FIELD = "doc"; + public static final String TITLE_FIELD = "title"; + public static final String URL_FIELD = "url"; + + private Constants() {} +}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java new file mode 100644 index 0000000..c9d68e8 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/documentation/QueryDocumentationExecutor.java
@@ -0,0 +1,150 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.documentation; + +import com.google.common.collect.Lists; +import com.google.inject.Inject; + +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.queryparser.classic.QueryParser; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.ScoreDoc; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.IndexOutput; +import org.apache.lucene.store.RAMDirectory; +import org.apache.lucene.util.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class QueryDocumentationExecutor { + private static final Logger log = + LoggerFactory.getLogger(QueryDocumentationExecutor.class); + + private static final String INDEX_PATH = "index.zip"; + private static final Version LUCENE_VERSION = Version.LUCENE_44; + + private IndexSearcher searcher; + private QueryParser parser; + + public static class DocResult { + public String title; + public String url; + public String content; + } + + @Inject + public QueryDocumentationExecutor() { + try { + Directory dir = readIndexDirectory(); + if (dir == null) { + searcher = null; + parser = null; + return; + } + IndexReader reader = DirectoryReader.open(dir); + searcher = new IndexSearcher(reader); + StandardAnalyzer analyzer = new StandardAnalyzer(LUCENE_VERSION); + parser = new QueryParser(LUCENE_VERSION, Constants.DOC_FIELD, analyzer); + } catch (IOException e) { + log.error("Cannot initialize documentation full text index", e); + searcher = null; + parser = null; + } + } + + public List<DocResult> doQuery(String q) throws DocQueryException { + if (parser == null || searcher == null) { + throw new DocQueryException("Documentation search not available"); + } + try { + Query query = parser.parse(q); + TopDocs results = searcher.search(query, Integer.MAX_VALUE); + ScoreDoc[] hits = results.scoreDocs; + int totalHits = results.totalHits; + + List<DocResult> out = Lists.newArrayListWithCapacity(totalHits); + for (int i = 0; i < totalHits; i++) { + DocResult result = new DocResult(); + Document doc = searcher.doc(hits[i].doc); + result.url = doc.get(Constants.URL_FIELD); + result.title = doc.get(Constants.TITLE_FIELD); + out.add(result); + } + return out; + } catch (IOException e) { + throw new DocQueryException(e); + } catch (ParseException e) { + throw new DocQueryException(e); + } + } + + protected Directory readIndexDirectory() throws IOException { + Directory dir = new RAMDirectory(); + byte[] buffer = new byte[4096]; + InputStream index = + QueryDocumentationExecutor.class.getClassLoader() + .getResourceAsStream(INDEX_PATH); + if (index == null) { + log.warn("No index available"); + return null; + } + ZipInputStream zip = new ZipInputStream(index); + try { + ZipEntry entry; + while ((entry = zip.getNextEntry()) != null) { + IndexOutput out = dir.createOutput(entry.getName(), null); + int count; + while ((count = zip.read(buffer)) != -1) { + out.writeBytes(buffer, count); + } + out.close(); + } + } finally { + zip.close(); + } + // We must NOT call dir.close() here, as DirectoryReader.open() expects an opened directory. + return dir; + } + + @SuppressWarnings("serial") + public static class DocQueryException extends Exception { + DocQueryException() { + } + + DocQueryException(String msg) { + super(msg); + } + + DocQueryException(String msg, Throwable e) { + super(msg, e); + } + + DocQueryException(Throwable e) { + super(e); + } + } +}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java index 98e803f..58d16dc 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
@@ -14,6 +14,8 @@ package com.google.gerrit.server.events; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.google.gerrit.common.Nullable; import com.google.gerrit.common.data.LabelType; import com.google.gerrit.common.data.LabelTypes; @@ -69,6 +71,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; @Singleton public class EventFactory { @@ -158,6 +161,29 @@ } /** + * Add allReviewers to an existing ChangeAttribute. + * + * @param a + * @param change + */ + public void addAllReviewers(ChangeAttribute a, Change change) + throws OrmException { + List<PatchSetApproval> approvals = + db.get().patchSetApprovals().byChange(change.getId()).toList(); + if (!approvals.isEmpty()) { + a.allReviewers = Lists.newArrayList(); + Set<Account.Id> seen = Sets.newHashSet(); + for (PatchSetApproval psa : approvals) { + Account.Id id = psa.getAccountId(); + if (!seen.contains(id)) { + seen.add(id); + a.allReviewers.add(asAccountAttribute(id)); + } + } + } + } + + /** * Add submitRecords to an existing ChangeAttribute. * * @param ca
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPlugin.java index 6adc677..1568997 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPlugin.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarPlugin.java
@@ -17,6 +17,7 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.gerrit.common.Nullable; +import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl; import com.google.gerrit.extensions.annotations.PluginData; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.extensions.registration.RegistrationHandle; @@ -59,6 +60,7 @@ private final JarFile jarFile; private final Manifest manifest; private final File dataDir; + private final String pluginCanonicalWebUrl; private final ClassLoader classLoader; private Class<? extends Module> sysModule; private Class<? extends Module> sshModule; @@ -71,6 +73,7 @@ private List<ReloadableRegistrationHandle<?>> reloadableHandles; public JarPlugin(String name, + String pluginCanonicalWebUrl, PluginUser pluginUser, File srcJar, FileSnapshot snapshot, @@ -83,6 +86,7 @@ @Nullable Class<? extends Module> sshModule, @Nullable Class<? extends Module> httpModule) { super(name, srcJar, pluginUser, snapshot, apiType); + this.pluginCanonicalWebUrl = pluginCanonicalWebUrl; this.jarFile = jarFile; this.manifest = manifest; this.dataDir = dataDir; @@ -193,6 +197,9 @@ bind(String.class) .annotatedWith(PluginName.class) .toInstance(getName()); + bind(String.class) + .annotatedWith(PluginCanonicalWebUrl.class) + .toInstance(pluginCanonicalWebUrl); bind(File.class) .annotatedWith(PluginData.class)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java index 7569744..ea19fe3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java
@@ -14,6 +14,7 @@ package com.google.gerrit.server.plugins; +import com.google.common.base.CharMatcher; import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Predicate; @@ -30,6 +31,7 @@ import com.google.gerrit.extensions.systemstatus.ServerInformation; import com.google.gerrit.extensions.webui.JavaScriptPlugin; import com.google.gerrit.server.PluginUser; +import com.google.gerrit.server.config.CanonicalWebUrl; import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; @@ -86,6 +88,7 @@ private final Queue<Plugin> toCleanup; private final Provider<PluginCleanerTask> cleaner; private final PluginScannerThread scanner; + private final Provider<String> urlProvider; @Inject public PluginLoader(SitePaths sitePaths, @@ -93,7 +96,8 @@ ServerInformationImpl sii, PluginUser.Factory puf, Provider<PluginCleanerTask> pct, - @GerritServerConfig Config cfg) { + @GerritServerConfig Config cfg, + @CanonicalWebUrl Provider<String> provider) { pluginsDir = sitePaths.plugins_dir; dataDir = sitePaths.data_dir; tmpDir = sitePaths.tmp_dir; @@ -106,6 +110,7 @@ toCleanup = Queues.newArrayDeque(); cleanupHandles = Maps.newConcurrentMap(); cleaner = pct; + urlProvider = provider; long checkFrequency = ConfigUtil.getTimeUnit(cfg, "plugins", null, "checkFrequency", @@ -504,7 +509,13 @@ Class<? extends Module> sysModule = load(sysName, pluginLoader); Class<? extends Module> sshModule = load(sshName, pluginLoader); Class<? extends Module> httpModule = load(httpName, pluginLoader); - Plugin plugin = new JarPlugin(name, pluginUserFactory.create(name), + + String url = String.format("%s/plugins/%s/", + CharMatcher.is('/').trimTrailingFrom(urlProvider.get()), + name); + + Plugin plugin = new JarPlugin(name, url, + pluginUserFactory.create(name), srcJar, snapshot, jarFile, manifest, new File(dataDir, name), type, pluginLoader,
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java index 5624f45..e569ff5 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
@@ -113,6 +113,7 @@ private boolean includeCommitMessage; private boolean includeDependencies; private boolean includeSubmitRecords; + private boolean includeAllReviewers; private OutputStream outputStream = DisabledOutputStream.INSTANCE; private PrintWriter out; @@ -200,6 +201,10 @@ includeSubmitRecords = on; } + public void setIncludeAllReviewers(boolean on) { + includeAllReviewers = on; + } + public void setOutput(OutputStream out, OutputFormat fmt) { this.outputStream = out; this.outputFormat = fmt; @@ -304,6 +309,10 @@ eventFactory.extend(c, d.getChange()); eventFactory.addTrackingIds(c, d.trackingIds(db)); + if (includeAllReviewers) { + eventFactory.addAllReviewers(c, d.getChange()); + } + if (includeSubmitRecords) { PatchSet.Id psId = d.getChange().currentPatchSetId(); PatchSet patchSet = db.get().patchSets().get(psId);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java index 9032bb0..006c759 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_55.java
@@ -17,6 +17,7 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.SystemConfig; import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.LocalDiskRepositoryManager; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; @@ -30,10 +31,10 @@ import java.util.Collections; public class Schema_55 extends SchemaVersion { - private final LocalDiskRepositoryManager mgr; + private final GitRepositoryManager mgr; @Inject - Schema_55(Provider<Schema_54> prior, LocalDiskRepositoryManager mgr) { + Schema_55(Provider<Schema_54> prior, GitRepositoryManager mgr) { super(prior); this.mgr = mgr; } @@ -46,7 +47,7 @@ if ("-- All Projects --".equals(oldName)) { ui.message("Renaming \"" + oldName + "\" to \"" + newName + "\""); - File base = mgr.getBasePath(); + File base = ((LocalDiskRepositoryManager) mgr).getBasePath(); File oldDir = FileKey.resolve(new File(base, oldName), FS.DETECTED); File newDir = new File(base, newName + Constants.DOT_GIT_EXT); if (!oldDir.renameTo(newDir)) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java index 27bf0bc..3ba77ec 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_56.java
@@ -17,11 +17,9 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.git.LocalDiskRepositoryManager; import com.google.inject.Inject; import com.google.inject.Provider; -import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; @@ -34,12 +32,12 @@ import java.util.Set; public class Schema_56 extends SchemaVersion { - private final LocalDiskRepositoryManager mgr; + private final GitRepositoryManager mgr; private final Set<String> keysOne; private final Set<String> keysTwo; @Inject - Schema_56(Provider<Schema_55> prior, LocalDiskRepositoryManager mgr) { + Schema_56(Provider<Schema_55> prior, GitRepositoryManager mgr) { super(prior); this.mgr = mgr; @@ -57,7 +55,7 @@ Repository git; try { git = mgr.openRepository(name); - } catch (RepositoryNotFoundException e) { + } catch (IOException e) { ui.message("warning: Cannot open " + name.get()); continue; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java index bf488e3..0edbc06 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java
@@ -27,7 +27,7 @@ import com.google.gerrit.server.config.AllProjectsNameProvider; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.extensions.events.GitReferenceUpdated; -import com.google.gerrit.server.git.LocalDiskRepositoryManager; +import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.ProjectConfig; import com.google.gwtorm.jdbc.JdbcSchema; @@ -48,12 +48,12 @@ public class Schema_57 extends SchemaVersion { private final SitePaths site; - private final LocalDiskRepositoryManager mgr; + private final GitRepositoryManager mgr; private final PersonIdent serverUser; @Inject Schema_57(Provider<Schema_56> prior, SitePaths site, - LocalDiskRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) { + GitRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) { super(prior); this.site = site; this.mgr = mgr;
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java index 880d0e1..5039cc2 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
@@ -25,9 +25,9 @@ import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.git.GitRepositoryManager; -import com.google.gerrit.server.git.LocalDiskRepositoryManager; import com.google.gerrit.testutil.InMemoryDatabase; import com.google.gerrit.testutil.InMemoryH2Type; +import com.google.gerrit.testutil.InMemoryRepositoryManager; import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.SchemaFactory; import com.google.gwtorm.server.StatementExecutor; @@ -74,7 +74,6 @@ install(new SchemaVersion.Module()); Config cfg = new Config(); - cfg.setString("gerrit", null, "basePath", "git"); cfg.setString("user", null, "name", "Gerrit Code Review"); cfg.setString("user", null, "email", "gerrit@localhost"); @@ -89,8 +88,8 @@ bind(AllProjectsName.class) .toInstance(new AllProjectsName("All-Projects")); - bind(GitRepositoryManager.class) // - .to(LocalDiskRepositoryManager.class); + bind(GitRepositoryManager.class) + .toInstance(new InMemoryRepositoryManager()); bind(String.class) // .annotatedWith(AnonymousCowardName.class) //
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshHostKeyModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshHostKeyModule.java new file mode 100644 index 0000000..fdf34a2 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshHostKeyModule.java
@@ -0,0 +1,28 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd; + +import static com.google.inject.Scopes.SINGLETON; + +import com.google.inject.AbstractModule; + +import org.apache.sshd.common.KeyPairProvider; + +public class SshHostKeyModule extends AbstractModule { + @Override + protected void configure() { + bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON); + } +}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshLog.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshLog.java index b3b6815..a78f9f5 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshLog.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshLog.java
@@ -72,24 +72,28 @@ this.context = context; this.auditService = auditService; - final DailyRollingFileAppender dst = new DailyRollingFileAppender(); - dst.setName(LOG_NAME); - dst.setLayout(new MyLayout()); - dst.setEncoding("UTF-8"); - dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath()); - dst.setImmediateFlush(true); - dst.setAppend(true); - dst.setThreshold(Level.INFO); - dst.setErrorHandler(new DieErrorHandler()); - dst.activateOptions(); - dst.setErrorHandler(new LogLogHandler()); + if (config.getBoolean("sshd", "requestLog", true)) { + final DailyRollingFileAppender dst = new DailyRollingFileAppender(); + dst.setName(LOG_NAME); + dst.setLayout(new MyLayout()); + dst.setEncoding("UTF-8"); + dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath()); + dst.setImmediateFlush(true); + dst.setAppend(true); + dst.setThreshold(Level.INFO); + dst.setErrorHandler(new DieErrorHandler()); + dst.activateOptions(); + dst.setErrorHandler(new LogLogHandler()); - async = new AsyncAppender(); - async.setBlocking(true); - async.setBufferSize(config.getInt("core", "asyncLoggingBufferSize", 64)); - async.setLocationInfo(false); - async.addAppender(dst); - async.activateOptions(); + async = new AsyncAppender(); + async.setBlocking(true); + async.setBufferSize(config.getInt("core", "asyncLoggingBufferSize", 64)); + async.setLocationInfo(false); + async.addAppender(dst); + async.activateOptions(); + } else { + async = null; + } } @Override @@ -98,11 +102,17 @@ @Override public void stop() { - async.close(); + if (async != null) { + async.close(); + } } void onLogin() { - async.append(log("LOGIN FROM " + session.get().getRemoteAddressAsString())); + LoggingEvent entry = + log("LOGIN FROM " + session.get().getRemoteAddressAsString()); + if (async != null) { + async.append(entry); + } audit(context.get(), "0", "LOGIN"); } @@ -127,8 +137,9 @@ if (error != null) { event.setProperty(P_STATUS, error); } - - async.append(event); + if (async != null) { + async.append(event); + } audit(null, "FAIL", "AUTH"); } @@ -162,7 +173,9 @@ } event.setProperty(P_STATUS, status); - async.append(event); + if (async != null) { + async.append(event); + } audit(context.get(), status, dcmd); } @@ -209,7 +222,10 @@ } void onLogout() { - async.append(log("LOGOUT")); + LoggingEvent entry = log("LOGOUT"); + if (async != null) { + async.append(entry); + } audit(context.get(), "0", "LOGOUT"); }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java index 48c565d..39b7f16 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
@@ -38,7 +38,6 @@ import com.google.inject.internal.UniqueAnnotations; import com.google.inject.servlet.RequestScoped; -import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.server.CommandFactory; import org.apache.sshd.server.PublickeyAuthenticator; import org.apache.sshd.server.auth.gss.GSSAuthenticator; @@ -85,7 +84,6 @@ bind(GSSAuthenticator.class).to(GerritGSSAuthenticator.class); bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class); - bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON); install(new DefaultCommandModule());
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AproposCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AproposCommand.java new file mode 100644 index 0000000..813f132 --- /dev/null +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AproposCommand.java
@@ -0,0 +1,46 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.sshd.commands; + +import com.google.gerrit.server.config.CanonicalWebUrl; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor; +import com.google.gerrit.server.documentation.QueryDocumentationExecutor.DocResult; +import com.google.gerrit.sshd.CommandMetaData; +import com.google.gerrit.sshd.SshCommand; +import com.google.inject.Inject; + +import org.kohsuke.args4j.Argument; + +import java.util.List; + +@CommandMetaData(name = "apropos", description = "Search in Gerrit documentation") +final class AproposCommand extends SshCommand { + @Inject + private QueryDocumentationExecutor searcher; + @Inject + @CanonicalWebUrl String url; + + @Argument(index=0, required = true, metaVar = "QUERY") + private String q; + + @Override + public void run() throws Exception { + List<QueryDocumentationExecutor.DocResult> res = searcher.doQuery(q); + for (DocResult docResult : res) { + stdout.println(String.format("%s:\n%s%s\n", docResult.title, url, + docResult.url)); + } + } +}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java index 521103b..429caf6 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -36,6 +36,7 @@ // SlaveCommandModule. command(gerrit).toProvider(new DispatchCommandProvider(gerrit)); + command(gerrit, AproposCommand.class); command(gerrit, BanCommitCommand.class); command(gerrit, FlushCaches.class); command(gerrit, ListProjectsCommand.class);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java index 185bb67..af42e1b 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Query.java
@@ -72,6 +72,11 @@ processor.setIncludeDependencies(on); } + @Option(name = "--all-reviewers", usage = "Include all reviewers") + void setAllReviewers(boolean on) { + processor.setIncludeAllReviewers(on); + } + @Option(name = "--submit-records", usage = "Include submit and label status") void setSubmitRecords(boolean on) { processor.setIncludeSubmitRecords(on);
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java index bccd0de..5936911 100644 --- a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java +++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
@@ -52,6 +52,7 @@ import com.google.gerrit.server.schema.SchemaModule; import com.google.gerrit.server.schema.SchemaVersionCheck; import com.google.gerrit.solr.SolrIndexModule; +import com.google.gerrit.sshd.SshHostKeyModule; import com.google.gerrit.sshd.SshKeyCacheImpl; import com.google.gerrit.sshd.SshModule; import com.google.gerrit.sshd.commands.MasterCommandModule; @@ -294,6 +295,7 @@ private Injector createSshInjector() { final List<Module> modules = new ArrayList<Module>(); modules.add(sysInjector.getInstance(SshModule.class)); + modules.add(new SshHostKeyModule()); modules.add(new MasterCommandModule()); return sysInjector.createChildInjector(modules); }
diff --git a/lib/asciidoctor/BUCK b/lib/asciidoctor/BUCK index 0b07b69..b1d5933 100644 --- a/lib/asciidoctor/BUCK +++ b/lib/asciidoctor/BUCK
@@ -31,6 +31,7 @@ srcs = ['java/DocIndexer.java'], deps = [ ':asciidoc_lib', + '//gerrit-server:constants', '//lib:args4j', '//lib:guava', '//lib/lucene:analyzers-common',
diff --git a/lib/asciidoctor/java/DocIndexer.java b/lib/asciidoctor/java/DocIndexer.java index 497cba5..96b1449 100644 --- a/lib/asciidoctor/java/DocIndexer.java +++ b/lib/asciidoctor/java/DocIndexer.java
@@ -13,6 +13,7 @@ // limitations under the License. import com.google.common.io.Files; +import com.google.gerrit.server.documentation.Constants; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.analysis.util.CharArraySet; @@ -43,9 +44,6 @@ public class DocIndexer { private static final Version LUCENE_VERSION = Version.LUCENE_44; - private static final String DOC_FIELD = "doc"; - private static final String URL_FIELD = "url"; - private static final String TITLE_FIELD = "title"; @Option(name = "-z", usage = "output zip file") private String zipFile; @@ -100,10 +98,10 @@ inputFile, inExt, outExt); FileReader reader = new FileReader(file); Document doc = new Document(); - doc.add(new TextField(DOC_FIELD, reader)); + doc.add(new TextField(Constants.DOC_FIELD, reader)); doc.add(new StringField( - URL_FIELD, prefix + outputFile, Field.Store.YES)); - doc.add(new TextField(TITLE_FIELD, title, Field.Store.YES)); + Constants.URL_FIELD, prefix + outputFile, Field.Store.YES)); + doc.add(new TextField(Constants.TITLE_FIELD, title, Field.Store.YES)); iwriter.addDocument(doc); reader.close(); }
diff --git a/lib/jgit/BUCK b/lib/jgit/BUCK index b8ff017..3e481bf 100644 --- a/lib/jgit/BUCK +++ b/lib/jgit/BUCK
@@ -1,15 +1,16 @@ include_defs('//lib/maven.defs') -REPO = GERRIT -VERS = '3.0.0.201306101825-r.41-g84d2738' +REPO = ECLIPSE +VERS = '3.1.0.201310021548-r' maven_jar( name = 'jgit', id = 'org.eclipse.jgit:org.eclipse.jgit:' + VERS, - bin_sha1 = 'fec8584e9e60ab3f43c3dd136f72662818e07766', - src_sha1 = '398e49984b281dbcd913b3894b8b9582c8b2cf9a', + bin_sha1 = 'df1410e5d1deaacfb70a2441b4766b61f2795bc3', + src_sha1 = 'b4e3d9c9c3da39b72acf72bd913ce9dbee88a9d4', license = 'jgit', repository = REPO, + unsign = True, deps = [':ewah'], exclude = [ 'META-INF/eclipse.inf', @@ -21,7 +22,7 @@ maven_jar( name = 'jgit-servlet', id = 'org.eclipse.jgit:org.eclipse.jgit.http.server:' + VERS, - sha1 = 'b20c36982aa90fc08180ef4a570bf28de5e1a0ab', + sha1 = 'bcac91120afac59c195230537bde07175578fe79', license = 'jgit', repository = REPO, deps = [':jgit'], @@ -34,7 +35,7 @@ maven_jar( name = 'junit', id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS, - sha1 = 'ee899f2d96b51e400ae84cd9405330a7e8ce1cb9', + sha1 = 'a8b47bb41cec25b1d128f7d267badbc7dcf6d9aa', license = 'DO_NOT_DISTRIBUTE', repository = REPO, deps = [':jgit'],
diff --git a/lib/lucene/BUCK b/lib/lucene/BUCK index 38ece4c..5973473 100644 --- a/lib/lucene/BUCK +++ b/lib/lucene/BUCK
@@ -41,6 +41,14 @@ ) maven_jar( + name = 'query-parser', + id = 'org.apache.lucene:lucene-queryparser:4.4.0', + bin_sha1 = 'e2fca26d9c64f3aad7b8a3461dbab14782107a06', + src_sha1 = 'f23e42ab90b5b7eb888d394282eba65362e88606', + license = 'Apache2.0', +) + +maven_jar( name = 'spellchecker', id = 'org.apache.lucene:lucene-spellchecker:3.6.2', bin_sha1 = '15db0c0cfee44e275f15ad046e46b9a05910ad24',
diff --git a/lib/maven.defs b/lib/maven.defs index 7049bfa..54840e8 100644 --- a/lib/maven.defs +++ b/lib/maven.defs
@@ -13,6 +13,7 @@ # limitations under the License. GERRIT = 'GERRIT:' +ECLIPSE = 'ECLIPSE:' MAVEN_CENTRAL = 'MAVEN_CENTRAL:' MAVEN_LOCAL = 'MAVEN_LOCAL:' @@ -32,6 +33,7 @@ license, exclude = [], exclude_java_sources = False, + unsign = False, deps = [], sha1 = '', bin_sha1 = '', src_sha1 = '', repository = MAVEN_CENTRAL, @@ -72,6 +74,8 @@ cmd.extend(['-x', x]) if exclude_java_sources: cmd.append('--exclude_java_sources') + if unsign: + cmd.append('--unsign') genrule( name = name + '__download_bin',
diff --git a/plugins/commit-message-length-validator b/plugins/commit-message-length-validator index 45f347d..c173419 160000 --- a/plugins/commit-message-length-validator +++ b/plugins/commit-message-length-validator
@@ -1 +1 @@ -Subproject commit 45f347d0e258ef7b871b046bfa96b9f902063b10 +Subproject commit c1734194c6a47492b1a5462206f59b585155406e
diff --git a/plugins/cookbook-plugin b/plugins/cookbook-plugin index 5ee3f28..1b1aca1 160000 --- a/plugins/cookbook-plugin +++ b/plugins/cookbook-plugin
@@ -1 +1 @@ -Subproject commit 5ee3f28739700e97b91231a2b694f3ba78065e86 +Subproject commit 1b1aca1dd61c033840bc465fa8646c22f5467f3a
diff --git a/plugins/download-commands b/plugins/download-commands index eaeb186..32254d3 160000 --- a/plugins/download-commands +++ b/plugins/download-commands
@@ -1 +1 @@ -Subproject commit eaeb1862180782bd5f696c79379a909dce7320b7 +Subproject commit 32254d3b75d65aceb485950fbf30d464574e02fc
diff --git a/plugins/replication b/plugins/replication index fa66d17..6cb2938 160000 --- a/plugins/replication +++ b/plugins/replication
@@ -1 +1 @@ -Subproject commit fa66d17b1d6ed3266d0e9061a852fc530ec2ea73 +Subproject commit 6cb293834907a7c059aa05168646ebc9f6b68c5a
diff --git a/plugins/reviewnotes b/plugins/reviewnotes index 9905f7a..c9fc694 160000 --- a/plugins/reviewnotes +++ b/plugins/reviewnotes
@@ -1 +1 @@ -Subproject commit 9905f7af6c4e258365413a03f092898b167ea25a +Subproject commit c9fc694ebd17d8331710c5193e729cee70fab325
diff --git a/tools/build.defs b/tools/build.defs index b62c850..4bb48ea 100644 --- a/tools/build.defs +++ b/tools/build.defs
@@ -14,7 +14,12 @@ # These definitions support building a runnable version of Gerrit. -DOCS = ['//Documentation:html.zip'] +DOCS_SRC = genfile('Documentation/html.zip') +DOCS_LIB = '//Documentation:index_lib' +DOCS_DEP = [ + '//Documentation:html', + '//Documentation:index_lib', +] LIBS = [ '//gerrit-war:log4j-config', '//gerrit-war:init', @@ -36,7 +41,8 @@ libs = [], pgmlibs = [], context = [], - visibility = [] + visibility = [], + docs = False ): cmd = ['$(exe //tools:pack_war)', '-o', '$OUT', '--tmp', '$TMP'] for l in libs: @@ -46,6 +52,10 @@ src = [] dep = [] + if docs: + src.append(DOCS_SRC) + dep.extend(DOCS_DEP) + cmd.extend(['--lib', DOCS_LIB]) if context: root = get_base_path() if root: @@ -56,6 +66,7 @@ r = root + r[2:] r = r.replace(':', '/') src.append(genfile(r)) + if src: cmd.append('$SRCS') genrule( @@ -67,7 +78,7 @@ visibility = visibility, ) -def gerrit_war(name, ui = 'ui_optdbg', context = []): +def gerrit_war(name, ui = 'ui_optdbg', context = [], docs = False): war( name = name, libs = LIBS + ['//gerrit-war:version'], @@ -77,4 +88,5 @@ '//gerrit-war:webapp_assets.zip', '//gerrit-gwtui:' + ui + '.zip', ] + context, + docs = docs, )
diff --git a/tools/download_file.py b/tools/download_file.py index 4c6e19f..8d76a40 100755 --- a/tools/download_file.py +++ b/tools/download_file.py
@@ -25,6 +25,7 @@ REPO_ROOTS = { 'GERRIT': 'http://gerrit-maven.storage.googleapis.com', + 'ECLIPSE': 'https://repo.eclipse.org/content/groups/releases', 'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2', 'MAVEN_LOCAL': 'file://' + path.expanduser('~/.m2/repository'), } @@ -108,6 +109,7 @@ opts.add_option('-v', help='expected content SHA-1') opts.add_option('-x', action='append', help='file to delete from ZIP') opts.add_option('--exclude_java_sources', action='store_true') +opts.add_option('--unsign', action='store_true') args, _ = opts.parse_args() root_dir = args.o @@ -165,7 +167,22 @@ finally: zf.close() except (BadZipfile, LargeZipFile) as err: - print("error opening %s: %s" % (cache_ent, err), file=stderr) + print('error opening %s: %s' % (cache_ent, err), file=stderr) + exit(1) + +if args.unsign: + try: + zf = ZipFile(cache_ent, 'r') + try: + for n in zf.namelist(): + if (n.endswith('.RSA') + or n.endswith('.SF') + or n.endswith('.LIST')): + exclude.append(n) + finally: + zf.close() + except (BadZipfile, LargeZipFile) as err: + print('error opening %s: %s' % (cache_ent, err), file=stderr) exit(1) safe_mkdirs(path.dirname(args.o)) @@ -173,7 +190,7 @@ try: shutil.copyfile(cache_ent, args.o) except (shutil.Error, IOError) as err: - print("error copying to %s: %s" % (args.o, err), file=stderr) + print('error copying to %s: %s' % (args.o, err), file=stderr) exit(1) try: check_call(['zip', '-d', args.o] + exclude) @@ -187,5 +204,5 @@ try: shutil.copyfile(cache_ent, args.o) except (shutil.Error, IOError) as err: - print("error copying to %s: %s" % (args.o, err), file=stderr) + print('error copying to %s: %s' % (args.o, err), file=stderr) exit(1)
diff --git a/tools/eclipse/BUCK b/tools/eclipse/BUCK index 9d6dd53..264e4eb 100644 --- a/tools/eclipse/BUCK +++ b/tools/eclipse/BUCK
@@ -13,5 +13,6 @@ '//lib/asciidoctor:asciidoc_lib', '//lib/asciidoctor:doc_indexer_lib', '//lib/prolog:compiler_lib', + '//Documentation:index_lib', ] + scan_plugins(), )