Merge "Instead of deleting patch-set-approval set vote to zero"
diff --git a/Documentation/dev-contributing.txt b/Documentation/dev-contributing.txt
index 6efabff..dd230d3 100644
--- a/Documentation/dev-contributing.txt
+++ b/Documentation/dev-contributing.txt
@@ -164,7 +164,8 @@
     contributors may also like to open several editors side by
     side while editing new changes.
   * Use 2 spaces for indent (no tabs)
-  * Use brackets in all ifs, spaces before/after if parens.
+  * Use braces in all if/else/for/do/while/catch blocks, spaces before/after
+    if/for/while/catch parens.
   * Use /** */ style Javadocs for variables.
 
 Additionally, you will notice that most of the newline spacing
diff --git a/Documentation/dev-release.txt b/Documentation/dev-release.txt
index 3157214..2a6cb1c 100644
--- a/Documentation/dev-release.txt
+++ b/Documentation/dev-release.txt
@@ -165,6 +165,15 @@
 * Sanity check WAR
 * Test the new Gerrit version
 
+* Verify plugin versions
++
+Sometimes `buck` doesn't rebuild plugins after they are tagged, and the
+versions don't reflect the tag. Verify the versions:
++
+----
+  java -jar ./buck-out/gen/release/release.war init --list-plugins
+----
+
 [[publish-gerrit]]
 === Publish the Gerrit Release
 
@@ -336,16 +345,11 @@
   make -C ReleaseNotes
 ----
 
-* Build the documentation:
-+
-----
-  buck build docs
-----
+* Extract the documentation files from the zip file generated during
+the release build: `buck-out/gen/Documentation/html/html.zip`.
 
-* Extract the documentation html files from the generated zip file
-`buck-out/gen/Documentation/searchfree.zip`.
-
-* Upload the html files manually via web browser to the
+* Upload the files manually via web browser to the appropriate folder
+in the
 link:https://console.developers.google.com/project/164060093628/storage/gerrit-documentation/[
 gerrit-documentation] storage bucket.
 
@@ -383,13 +387,12 @@
 ** A link to the release and the release notes (if a final release)
 ** A link to the docs
 ** Describe the type of release (stable, bug fix, RC)
-
-* Add an entry to the `NEWS` section of the main Gerrit project web page
-** Go to: http://code.google.com/p/gerrit/admin
-** Add entry like:
-----
- * Jun 14, 2012 - Gerrit 2.4.1 [https://groups.google.com/d/topic/repo-discuss/jHg43gixqzs/discussion Released]
-----
+** Hash values (SHA1, SHA256, MD5) for the release WAR file.
++
+The SHA1 and MD5 can be taken from the artifact page on Sonatype. The
+SHA256 can be generated with
+`openssl sha -sha256 buck-out/gen/release/release.war` or an equivalent
+command.
 
 * Update the new discussion group announcement to be sticky
 ** Go to: http://groups.google.com/group/repo-discuss/topics
diff --git a/ReleaseNotes/ReleaseNotes-2.12.2.txt b/ReleaseNotes/ReleaseNotes-2.12.2.txt
new file mode 100644
index 0000000..5582bf9
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.12.2.txt
@@ -0,0 +1,38 @@
+Release notes for Gerrit 2.12.2
+===============================
+
+Gerrit 2.12.2 is now available:
+
+link:https://gerrit-releases.storage.googleapis.com/gerrit-2.12.2.war[
+https://gerrit-releases.storage.googleapis.com/gerrit-2.12.2.war]
+
+There are no schema changes from link:ReleaseNotes-2.12.1.html[2.12.1].
+
+Bug Fixes
+---------
+
+* Upgrade Apache commons-collections to version 3.2.2.
++
+Includes a fix for a link:https://issues.apache.org/jira/browse/COLLECTIONS-580[
+remote code execution exploit].
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=3919[Issue 3919]:
+Explicitly set parent project to 'All-Projects' when a project is created
+without giving the parent.
+
+* Don't add message twice on abandon or restore via ssh review command.
++
+When abandoning or reviewing a change via the ssh `review` command, and
+providing a message with the `--message` option, the message was added to
+the change twice.
+
+* Clear the input box after cancelling add reviewer action.
++
+When the action was cancelled, the content of the input box was still
+there when opening it again.
+
+* Fix internal server error when aborting ssh command.
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=3969[Issue 3969]:
+Fix internal server error when submitting a change with 'Rebase If Necessary'
+strategy.
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index 5e5ba9e..4cab151 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -9,6 +9,7 @@
 [[2_12]]
 Version 2.12.x
 --------------
+* link:ReleaseNotes-2.12.2.html[2.12.2]
 * link:ReleaseNotes-2.12.1.html[2.12.1]
 * link:ReleaseNotes-2.12.html[2.12]
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 7add9a2..def8317 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -19,6 +19,7 @@
 import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
 import static com.google.gerrit.acceptance.PushOneCommit.PATCH;
 import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
+import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.eclipse.jgit.lib.Constants.HEAD;
 import static org.junit.Assert.fail;
@@ -29,6 +30,7 @@
 import com.google.gerrit.acceptance.NoHttpd;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.CherryPickInput;
 import com.google.gerrit.extensions.api.changes.DraftApi;
@@ -38,6 +40,7 @@
 import com.google.gerrit.extensions.api.changes.RevisionApi;
 import com.google.gerrit.extensions.api.changes.SubmitInput;
 import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.client.ChangeStatus;
 import com.google.gerrit.extensions.client.SubmitType;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.ChangeMessageInfo;
@@ -49,9 +52,13 @@
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.ETagView;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Patch;
 import com.google.gerrit.server.change.GetRevisionActions;
 import com.google.gerrit.server.change.RevisionResource;
+import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.project.Util;
 import com.google.inject.Inject;
 
 import org.eclipse.jgit.lib.ObjectId;
@@ -119,18 +126,68 @@
   @Test
   public void submit() throws Exception {
     PushOneCommit.Result r = createChange();
+    String changeId = project.get() + "~master~" + r.getChangeId();
     gApi.changes()
-        .id(project.get() + "~master~" + r.getChangeId())
+        .id(changeId)
         .current()
         .review(ReviewInput.approve());
     gApi.changes()
-        .id(project.get() + "~master~" + r.getChangeId())
+        .id(changeId)
         .current()
         .submit();
+    assertThat(gApi.changes().id(changeId).get().status)
+        .isEqualTo(ChangeStatus.MERGED);
   }
 
-  @Test(expected = AuthException.class)
+  private void allowSubmitOnBehalfOf() throws Exception {
+    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
+    Util.allow(cfg,
+        Permission.SUBMIT_AS,
+        SystemGroupBackend.getGroup(REGISTERED_USERS).getUUID(),
+        "refs/heads/*");
+    saveProjectConfig(project, cfg);
+  }
+
+  @Test
   public void submitOnBehalfOf() throws Exception {
+    allowSubmitOnBehalfOf();
+    PushOneCommit.Result r = createChange();
+    String changeId = project.get() + "~master~" + r.getChangeId();
+    gApi.changes()
+        .id(changeId)
+        .current()
+        .review(ReviewInput.approve());
+    SubmitInput in = new SubmitInput();
+    in.onBehalfOf = admin2.email;
+    gApi.changes()
+        .id(changeId)
+        .current()
+        .submit(in);
+    assertThat(gApi.changes().id(changeId).get().status)
+        .isEqualTo(ChangeStatus.MERGED);
+  }
+
+  @Test
+  public void submitOnBehalfOfInvalidUser() throws Exception {
+    allowSubmitOnBehalfOf();
+    PushOneCommit.Result r = createChange();
+    String changeId = project.get() + "~master~" + r.getChangeId();
+    gApi.changes()
+        .id(changeId)
+        .current()
+        .review(ReviewInput.approve());
+    SubmitInput in = new SubmitInput();
+    in.onBehalfOf = "doesnotexist";
+    exception.expect(UnprocessableEntityException.class);
+    exception.expectMessage("Account Not Found: doesnotexist");
+    gApi.changes()
+        .id(changeId)
+        .current()
+        .submit(in);
+  }
+
+  @Test
+  public void submitOnBehalfOfNotPermitted() throws Exception {
     PushOneCommit.Result r = createChange();
     gApi.changes()
         .id(project.get() + "~master~" + r.getChangeId())
@@ -138,6 +195,8 @@
         .review(ReviewInput.approve());
     SubmitInput in = new SubmitInput();
     in.onBehalfOf = admin2.email;
+    exception.expect(AuthException.class);
+    exception.expectMessage("submit on behalf of not permitted");
     gApi.changes()
         .id(project.get() + "~master~" + r.getChangeId())
         .current()
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/SubmitInput.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/SubmitInput.java
index 4d368f6..053248f 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/SubmitInput.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/SubmitInput.java
@@ -15,5 +15,9 @@
 package com.google.gerrit.extensions.api.changes;
 
 public class SubmitInput {
+  /** Not used anymore, kept for backward compatibility */
+  @Deprecated
+  public boolean waitForMerge;
+
   public String onBehalfOf;
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
index f605abf..2b01b59 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java
@@ -159,15 +159,6 @@
     final Grid formGrid = new Grid(12 + (flashClippy ? 1 : 0), 2);
 
     int row = 0;
-    formGrid.setText(row, labelIdx, "");
-    formGrid.setWidget(row, fieldIdx, showSiteHeader);
-    row++;
-
-    if (flashClippy) {
-      formGrid.setText(row, labelIdx, "");
-      formGrid.setWidget(row, fieldIdx, useFlashClipboard);
-      row++;
-    }
 
     formGrid.setText(row, labelIdx, Util.C.reviewCategoryLabel());
     formGrid.setWidget(row, fieldIdx, reviewCategoryStrategy);
@@ -181,6 +172,18 @@
     formGrid.setWidget(row, fieldIdx, dateTimePanel);
     row++;
 
+    formGrid.setText(row, labelIdx, Util.C.emailFieldLabel());
+    formGrid.setWidget(row, fieldIdx, emailStrategy);
+    row++;
+
+    formGrid.setText(row, labelIdx, Util.C.diffViewLabel());
+    formGrid.setWidget(row, fieldIdx, diffView);
+    row++;
+
+    formGrid.setText(row, labelIdx, "");
+    formGrid.setWidget(row, fieldIdx, showSiteHeader);
+    row++;
+
     formGrid.setText(row, labelIdx, "");
     formGrid.setWidget(row, fieldIdx, relativeDateInChangeTable);
     row++;
@@ -197,15 +200,14 @@
     formGrid.setWidget(row, fieldIdx, muteCommonPathPrefixes);
     row++;
 
-    formGrid.setText(row, labelIdx, Util.C.emailFieldLabel());
-    formGrid.setWidget(row, fieldIdx, emailStrategy);
-
     formGrid.setText(row, labelIdx, "");
     formGrid.setWidget(row, fieldIdx, signedOffBy);
     row++;
 
-    formGrid.setText(row, labelIdx, Util.C.diffViewLabel());
-    formGrid.setWidget(row, fieldIdx, diffView);
+    if (flashClippy) {
+      formGrid.setText(row, labelIdx, "");
+      formGrid.setWidget(row, fieldIdx, useFlashClipboard);
+    }
 
     add(formGrid);
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java
index 2996c07..33a2fb8 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java
@@ -637,17 +637,18 @@
       String contents,
       Element parent) {
     return CodeMirror.create(parent, Configuration.create()
-      .set("readOnly", true)
       .set("cursorBlinkRate", prefs.cursorBlinkRate())
       .set("cursorHeight", 0.85)
-      .set("lineNumbers", prefs.showLineNumbers())
-      .set("tabSize", prefs.tabSize())
-      .set("mode", fileSize == FileSize.SMALL ? getContentType(meta) : null)
-      .set("lineWrapping", false)
-      .set("scrollbarStyle", "overlay")
-      .set("styleSelectedText", true)
-      .set("showTrailingSpace", prefs.showWhitespaceErrors())
       .set("keyMap", "vim_ro")
+      .set("lineNumbers", prefs.showLineNumbers())
+      .set("lineWrapping", false)
+      .set("matchBrackets", prefs.matchBrackets())
+      .set("mode", fileSize == FileSize.SMALL ? getContentType(meta) : null)
+      .set("readOnly", true)
+      .set("scrollbarStyle", "overlay")
+      .set("showTrailingSpace", prefs.showWhitespaceErrors())
+      .set("styleSelectedText", true)
+      .set("tabSize", prefs.tabSize())
       .set("theme", prefs.theme().name().toLowerCase())
       .set("value", meta != null ? contents : "")
       .set("viewportMargin", renderEntireFile() ? POSITIVE_INFINITY : 10));
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java
index 5bbb798..b586bc5 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/RebuildNotedb.java
@@ -37,6 +37,7 @@
 import com.google.gerrit.reviewdb.client.RefNames;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.AllUsersName;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MultiProgressMonitor;
 import com.google.gerrit.server.git.MultiProgressMonitor.Task;
@@ -51,11 +52,11 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
 import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.TypeLiteral;
 
 import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
@@ -85,6 +86,28 @@
   private Injector dbInjector;
   private Injector sysInjector;
 
+  @Inject
+  private AllUsersName allUsersName;
+
+  @Inject
+  private ChangeRebuilder rebuilder;
+
+  @Inject
+  @GerritServerConfig
+  private Config cfg;
+
+  @Inject
+  private GitRepositoryManager repoManager;
+
+  @Inject
+  private NotesMigration notesMigration;
+
+  @Inject
+  private SchemaFactory<ReviewDb> schemaFactory;
+
+  @Inject
+  private WorkQueue workQueue;
+
   @Override
   public int run() throws Exception {
     mustHaveValidSite();
@@ -96,8 +119,7 @@
     dbManager.start();
 
     sysInjector = createSysInjector();
-    NotesMigration notesMigration = sysInjector.getInstance(
-        NotesMigration.class);
+    sysInjector.injectMembers(this);
     if (!notesMigration.enabled()) {
       die("Notedb is not enabled.");
     }
@@ -107,16 +129,11 @@
 
     ListeningExecutorService executor = newExecutor();
     System.out.println("Rebuilding the notedb");
-    ChangeRebuilder rebuilder = sysInjector.getInstance(ChangeRebuilder.class);
 
     Multimap<Project.NameKey, Change.Id> changesByProject =
         getChangesByProject();
     AtomicBoolean ok = new AtomicBoolean(true);
     Stopwatch sw = Stopwatch.createStarted();
-    GitRepositoryManager repoManager =
-        sysInjector.getInstance(GitRepositoryManager.class);
-    Project.NameKey allUsersName =
-        sysInjector.getInstance(AllUsersName.class);
     try (Repository allUsersRepo =
         repoManager.openMetadataRepository(allUsersName)) {
       deleteRefs(RefNames.REFS_DRAFT_COMMENTS, allUsersRepo);
@@ -206,8 +223,7 @@
   private ListeningExecutorService newExecutor() {
     if (threads > 0) {
       return MoreExecutors.listeningDecorator(
-          dbInjector.getInstance(WorkQueue.class)
-            .createQueue(threads, "RebuildChange"));
+          workQueue.createQueue(threads, "RebuildChange"));
     } else {
       return MoreExecutors.newDirectExecutorService();
     }
@@ -217,8 +233,6 @@
       throws OrmException {
     // Memorize all changes so we can close the db connection and allow
     // rebuilder threads to use the full connection pool.
-    SchemaFactory<ReviewDb> schemaFactory = sysInjector.getInstance(Key.get(
-        new TypeLiteral<SchemaFactory<ReviewDb>>() {}));
     Multimap<Project.NameKey, Change.Id> changesByProject =
         ArrayListMultimap.create();
     try (ReviewDb db = schemaFactory.open()) {
diff --git a/polygerrit-ui/app/BUCK b/polygerrit-ui/app/BUCK
index 93cf614..5110350 100644
--- a/polygerrit-ui/app/BUCK
+++ b/polygerrit-ui/app/BUCK
@@ -6,6 +6,7 @@
   ['**'],
   excludes = [
     'BUCK',
+    '**/*_test.html',
     'index.html',
   ] + WCT_TEST_PATTERNS + PY_TEST_PATTERNS)
 
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
index 0a4aec4..39dda7f 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="gr-change-list-item.html">
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
index acb8789..ca9da5b 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
@@ -21,7 +21,7 @@
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <script src="../../../bower_components/page/page.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
index 7b1a2f1..22cf176 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.html
@@ -20,8 +20,6 @@
 <link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
 <link rel="import" href="../gr-reviewer-list/gr-reviewer-list.html">
 
-<script src="../../../scripts/fake-app.js"></script>
-
 <dom-module id="gr-change-metadata">
   <template>
     <style>
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
index 6c97b5a..f437dbc 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.html
@@ -24,6 +24,7 @@
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
 <link rel="import" href="gr-change-metadata.html">
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <test-fixture id="basic">
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index ed9d28d..f5028a9 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -21,7 +21,7 @@
 <script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <script src="../../../bower_components/page/page.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index a1140f5..bc7b2a6 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -21,7 +21,7 @@
 <script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <script src="../../../bower_components/page/page.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.html b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
index 5733acd..7c287db 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.html
@@ -19,6 +19,7 @@
 <link rel="import" href="../../shared/gr-button/gr-button.html">
 <link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
 <link rel="import" href="../../shared/gr-linked-text/gr-linked-text.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <link rel="import" href="../gr-comment-list/gr-comment-list.html">
 
@@ -120,6 +121,7 @@
         <gr-button small on-tap="_handleReplyTap">Reply</gr-button>
       </div>
     </div>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-message.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index 1ab5e6c..26b9fb9 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -57,7 +57,7 @@
     },
 
     ready: function() {
-      app.configReady.then(function(cfg) {
+      this.$.restAPI.getConfig().then(function(cfg) {
         this.showAvatar = !!(cfg && cfg.plugin && cfg.plugin.has_avatars) &&
             this.message && this.message.author;
       }.bind(this));
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
index 0f09b70..dc4464b 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
index 5a562ba..4f18439 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 3cde22a..d3072ac 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
index 0d549d9..814e206 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.html
@@ -17,6 +17,7 @@
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
 <link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
 <link rel="import" href="../../shared/gr-button/gr-button.html">
+<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-account-dropdown">
   <style>
@@ -36,6 +37,11 @@
       font: inherit;
       padding: .3em 0;
     }
+    gr-avatar {
+      height: 2em;
+      width: 2em;
+      vertical-align: -.25em;
+    }
     ul {
       list-style: none;
     }
@@ -59,7 +65,11 @@
   </style>
   <template>
     <gr-button link class="dropdown-trigger" id="trigger"
-        on-tap="_showDropdownTapHandler">[[account.name]]</gr-button>
+        on-tap="_showDropdownTapHandler">
+      <span hidden$="[[_hasAvatars]]" hidden>[[account.name]]</span>
+      <gr-avatar account="[[account]]" hidden$="[[!_hasAvatars]]" hidden
+          image-size="56"></gr-avatar>
+    </gr-button>
     <iron-dropdown id="dropdown"
         vertical-align="top"
         vertical-offset="25"
@@ -77,6 +87,7 @@
         </ul>
       </div>
     </iron-dropdown>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-account-dropdown.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
index 09de6c1..62212a3 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.js
@@ -19,6 +19,13 @@
 
     properties: {
       account: Object,
+      _hasAvatars: Boolean,
+    },
+
+    attached: function() {
+      this.$.restAPI.getConfig().then(function(cfg) {
+        this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
+      }.bind(this));
     },
 
     _showDropdownTapHandler: function(e) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index 4d0c6e5..188bc5d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -21,7 +21,7 @@
 <script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <script src="../../../bower_components/page/page.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index 921d766..f3c1402 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 67ab50f..b1c084e 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -26,7 +26,6 @@
 <link rel="import" href="./change/gr-change-view/gr-change-view.html">
 <link rel="import" href="./diff/gr-diff-view/gr-diff-view.html">
 
-<link rel="import" href="./shared/gr-ajax/gr-ajax.html">
 <link rel="import" href="./shared/gr-overlay/gr-overlay.html">
 <link rel="import" href="./shared/gr-rest-api-interface/gr-rest-api-interface.html">
 
@@ -56,11 +55,6 @@
         color: #b71c1c;
       }
     </style>
-    <gr-ajax auto url="/config/server/info" last-response="{{config}}"></gr-ajax>
-    <gr-ajax auto url="/config/server/version" last-response="{{version}}"></gr-ajax>
-    <gr-ajax id="diffPreferencesXHR"
-        url="/accounts/self/preferences.diff"
-        last-response="{{_diffPreferences}}"></gr-ajax>
     <gr-main-header search-query="{{params.query}}"></gr-main-header>
     <main>
       <template is="dom-if" if="{{_showChangeListView}}" restamp="true">
@@ -68,18 +62,18 @@
             params="[[params]]"
             view-state="{{_viewState.changeListView}}"
             changes-per-page="[[_preferences.changes_per_page]]"
-            logged-in="[[_computeLoggedIn(account)]]"></gr-change-list-view>
+            logged-in="[[_computeLoggedIn(_account)]]"></gr-change-list-view>
       </template>
       <template is="dom-if" if="{{_showDashboardView}}" restamp="true">
         <gr-dashboard-view
-            account="[[account]]"
+            account="[[_account]]"
             params="[[params]]"
             view-state="{{_viewState.dashboardView}}"></gr-dashboard-view>
       </template>
       <template is="dom-if" if="{{_showChangeView}}" restamp="true">
         <gr-change-view
             params="[[params]]"
-            server-config="[[config]]"
+            server-config="[[_serverConfig]]"
             view-state="{{_viewState.changeView}}"></gr-change-view>
       </template>
       <template is="dom-if" if="{{_showDiffView}}" restamp="true">
@@ -91,14 +85,14 @@
     </main>
     <footer role="contentinfo">
       Powered by <a href="https://www.gerritcodereview.com/" target="_blank">Gerrit Code Review</a>
-      ([[version]])
-      <span hidden$="[[!config.gerrit.report_bug_url]]">
+      ([[_version]])
+      <span hidden$="[[!_serverConfig.gerrit.report_bug_url]]">
         |
-        <a href$="[[config.gerrit.report_bug_url]]" target="_blank">
-          <span hidden$="[[!config.gerrit.report_bug_text]]">
-            [[config.gerrit.report_bug_text]]
+        <a href$="[[_serverConfig.gerrit.report_bug_url]]" target="_blank">
+          <span hidden$="[[!_serverConfig.gerrit.report_bug_text]]">
+            [[_serverConfig.gerrit.report_bug_text]]
           </span>
-          <span hidden$="[[config.gerrit.report_bug_text]]">Report Bug</span>
+          <span hidden$="[[_serverConfig.gerrit.report_bug_text]]">Report Bug</span>
         </a>
       </span>
       |
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index a40e61b..31797dd 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -18,10 +18,7 @@
     is: 'gr-app',
 
     properties: {
-      account: {
-        type: Object,
-        observer: '_accountChanged',
-      },
+      params: Object,
       accountReady: {
         type: Object,
         readOnly: true,
@@ -32,29 +29,20 @@
           }.bind(this));
         },
       },
-      config: {
-        type: Object,
-        observer: '_configChanged',
-      },
-      configReady: {
-        type: Object,
-        readOnly: true,
-        notify: true,
-        value: function() {
-          return new Promise(function(resolve) {
-            this._resolveConfigReady = resolve;
-          }.bind(this));
-        },
-      },
-      version: String,
-      params: Object,
       keyEventTarget: {
         type: Object,
         value: function() { return document.body; },
       },
 
+      _account: {
+        type: Object,
+        observer: '_accountChanged',
+      },
+      _serverConfig: Object,
+      _version: String,
       _diffPreferences: Object,
       _preferences: Object,
+      _resolveAccountReady: Function,
       _showChangeListView: Boolean,
       _showDashboardView: Boolean,
       _showChangeView: Boolean,
@@ -75,12 +63,18 @@
     ],
 
     get loggedIn() {
-      return !!(this.account && Object.keys(this.account).length > 0);
+      return !!(this._account && Object.keys(this._account).length > 0);
     },
 
     attached: function() {
       this.$.restAPI.getAccount().then(function(account) {
-        this.account = account;
+        this._account = account;
+      }.bind(this));
+      this.$.restAPI.getConfig().then(function(config) {
+        this._serverConfig = config;
+      }.bind(this));
+      this.$.restAPI.getVersion().then(function(version) {
+        this._version = version;
       }.bind(this));
     },
 
@@ -105,12 +99,14 @@
 
     _accountChanged: function() {
       this._resolveAccountReady();
-      if (this.loggedIn) {
-        this.$.diffPreferencesXHR.generateRequest();
 
+      if (this.loggedIn) {
         this.$.restAPI.getPreferences().then(function(preferences) {
           this._preferences = preferences;
         }.bind(this));
+        this.$.restAPI.getDiffPreferences().then(function(prefs) {
+          this._diffPreferences = prefs;
+        }.bind(this));
       } else {
         // These defaults should match the defaults in
         // gerrit-extension-api/src/main/jcg/gerrit/extensions/client/DiffPreferencesInfo.java
@@ -137,10 +133,6 @@
       }
     },
 
-    _configChanged: function(config) {
-      this._resolveConfigReady(config);
-    },
-
     _viewChanged: function(view) {
       this.set('_showChangeListView', view == 'gr-change-list-view');
       this.set('_showDashboardView', view == 'gr-dashboard-view');
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
index c39f288..af65bfd 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="gr-account-label.html">
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
index e1ef862..869d812 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="gr-account-link.html">
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
index 3491443..55655c0 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.html
@@ -15,6 +15,7 @@
 -->
 
 <link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../gr-rest-api-interface/gr-rest-api-interface.html">
 
 <dom-module id="gr-avatar">
   <template>
@@ -26,6 +27,7 @@
         background-color: var(--background-color, #f1f2f3);
       }
     </style>
+    <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-avatar.js"></script>
 </dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
index 8f289ca..3655975 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar.js
@@ -32,8 +32,8 @@
       this.hidden = true;
     },
 
-    ready: function() {
-      app.configReady.then(function(cfg) {
+    attached: function() {
+      this.$.restAPI.getConfig().then(function(cfg) {
         var hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
         if (hasAvatars) {
           this.hidden = false;
diff --git a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
index 7e3c25c..f065290 100644
--- a/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-avatar/gr-avatar_test.html
@@ -20,7 +20,7 @@
 
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 
 <link rel="import" href="gr-avatar.html">
 
diff --git a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
index 86ee947..03b8e13 100644
--- a/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-change-star/gr-change-star_test.html
@@ -21,7 +21,7 @@
 <script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
 <script src="../../../bower_components/web-component-tester/browser.js"></script>
 <script src="../../../bower_components/page/page.js"></script>
-<script src="../../../scripts/fake-app.js"></script>
+<script src="../../../test/fake-app.js"></script>
 <script src="../../../scripts/util.js"></script>
 
 <link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 09b6d35..27cd989 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -82,6 +82,18 @@
       }.bind(this));
     },
 
+    getConfig: function() {
+      return this._fetchSharedCacheURL('/config/server/info');
+    },
+
+    getVersion: function() {
+      return this._fetchSharedCacheURL('/config/server/version');
+    },
+
+    getDiffPreferences: function() {
+      return this._fetchSharedCacheURL('/accounts/self/preferences.diff');
+    },
+
     getAccount: function() {
       return this._fetchSharedCacheURL('/accounts/self/detail');
     },
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
index b0a6649..3902707f 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface_test.html
@@ -42,7 +42,7 @@
       var testJSON = ')]}\'\n{"hello": "bonjour"}';
 
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ text: function() {
+        return Promise.resolve({text: function() {
           return Promise.resolve(testJSON);
         }});
       });
@@ -65,7 +65,7 @@
 
       Promise.all(promises).then(function(results) {
         assert.deepEqual(results, [1, 1, 1]);
-         element._fetchSharedCacheURL('/foo').then(function(foo) {
+        element._fetchSharedCacheURL('/foo').then(function(foo) {
           assert.equal(foo, 1);
           fetchJSONStub.restore();
           done();
@@ -84,7 +84,7 @@
 
     test('params are properly encoded', function() {
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ text: function() {
+        return Promise.resolve({text: function() {
           return Promise.resolve(')]}\'\n{}');
         }});
       });
@@ -101,7 +101,7 @@
     test('request callbacks can be canceled', function(done) {
       var cancelCalled = false;
       var fetchStub = sinon.stub(window, 'fetch', function() {
-        return Promise.resolve({ body: {
+        return Promise.resolve({body: {
           cancel: function() { cancelCalled = true; }
         }});
       });
@@ -140,6 +140,7 @@
           assert.deepEqual(obj.comments[0], {
             message: 'this isn’t quite right',
           });
+          fetchJSONStub.restore();
           done();
         });
     });
@@ -190,6 +191,7 @@
           assert.deepEqual(obj.comments[1], {
             message: '¯\\_(ツ)_/¯',
           });
+          fetchJSONStub.restore();
           done();
         });
     });
diff --git a/polygerrit-ui/app/scripts/fake-app.js b/polygerrit-ui/app/test/fake-app.js
similarity index 100%
rename from polygerrit-ui/app/scripts/fake-app.js
rename to polygerrit-ui/app/test/fake-app.js
diff --git a/tools/maven/mvn.py b/tools/maven/mvn.py
index 7017406..83a33e8 100755
--- a/tools/maven/mvn.py
+++ b/tools/maven/mvn.py
@@ -65,7 +65,8 @@
       print(' '.join(exe), file=stderr)
     check_output(exe)
   except Exception as e:
-    print('%s command failed: %s' % (args.a, e), file=stderr)
+    print('%s command failed: %s\n%s' % (args.a, ' '.join(exe), e),
+      file=stderr)
     exit(1)
 
 with open(args.o, 'w') as fd:
diff --git a/tools/plugin_archetype_deploy.sh b/tools/plugin_archetype_deploy.sh
index 4ad8b70..b16ce95 100755
--- a/tools/plugin_archetype_deploy.sh
+++ b/tools/plugin_archetype_deploy.sh
@@ -63,21 +63,9 @@
     -Dfile=target/$module-$ver.jar
 }
 
-function confirm
-{
-  read -n1 -p "Are you sure you want to deploy? [N/y]: " ready
-  if [[ ! $ready == [Yy] ]]; then
-    if [[ $ready == [Nn] || -z $ready ]]; then
-      echo; exit
-    else
-      echo; confirm
-    fi
-  fi
-}
-
 function run
 {
-  test ${dryRun:-'false'} == 'false'  && confirm
+  test ${dryRun:-'false'} == 'false'
   root=$(instroot)
   cd "$root"
   ver=$(getver GERRIT_VERSION)