Merge branch 'stable-2.8'

* stable-2.8:
  Update buck
  Remove temporary files created by --list-plugins operation
  --list-plugins should not start init step
  Handle KeyboardInterrupt in Buck build wrapper scripts
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-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-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..bb726e3 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
@@ -33,6 +33,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,6 +58,7 @@
 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;
@@ -109,6 +111,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;
 
@@ -224,7 +229,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);
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-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/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