Merge branch 'stable-2.8'

* stable-2.8:
  Inject right plugin name @PluginName in init step
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-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/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-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-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
index 2dd20a2..fb117767 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 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-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/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/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/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/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