Merge branch 'stable-2.11'

* stable-2.11:
  Update version to 2.10.6
  Release notes for Gerrit 2.10.6
  Correct file list when comparing patchsets
  AbstractSubmit, ActionsIT: Disable tests for submitWholeTopic
  Buck: Fix api build
  Remove org.json:json and fix gwt-dev deps
  Fix license generation
  Submit: Disable the 'submitWholeTopic' feature
  Pack prettify.min.{js,css} into documentation.
  Print proper name for project indexer tasks in show-queue command
  Print proper name for reindex after update tasks in show-queue command
  Set version to 2.11.2
  Update JGit to 4.0.1.201506240215-r
  Revert "Use changeRefsById to track existing revisions"
  ChangeUtil: Delete draft change inside database transaction
  Revert "Treat the search box oracle as a remote oracle"

The commit:
  Revert "Use changeRefsById to track existing revisions"

is reverted by this merge. The original change was reverted on the
stable-2.11 branch due to a regression and causes a merge conflict
against the current head of master.

Rather than try to resolve the conflic in this merge, my intention
is to either re-do the revert as a separate commit on master, or
try to find a solution to the regression that required the revert.

Change-Id: I563fac10e3ed6f572a78305876a2c37a5b5b04ea
diff --git a/ReleaseNotes/ReleaseNotes-2.10.6.txt b/ReleaseNotes/ReleaseNotes-2.10.6.txt
new file mode 100644
index 0000000..94a95bd
--- /dev/null
+++ b/ReleaseNotes/ReleaseNotes-2.10.6.txt
@@ -0,0 +1,14 @@
+Release notes for Gerrit 2.10.6
+===============================
+
+There are no schema changes from link:ReleaseNotes-2.10.5.html[2.10.5].
+
+Download:
+link:https://gerrit-releases.storage.googleapis.com/gerrit-2.10.6.war[
+https://gerrit-releases.storage.googleapis.com/gerrit-2.10.6.war]
+
+Bug Fixes
+---------
+
+* Fix generation of licenses in documentation.
+
diff --git a/ReleaseNotes/index.txt b/ReleaseNotes/index.txt
index 57d311e..773fdd2 100644
--- a/ReleaseNotes/index.txt
+++ b/ReleaseNotes/index.txt
@@ -10,6 +10,7 @@
 [[2_10]]
 Version 2.10.x
 --------------
+* link:ReleaseNotes-2.10.6.html[2.10.6]
 * link:ReleaseNotes-2.10.5.html[2.10.5]
 * link:ReleaseNotes-2.10.4.html[2.10.4]
 * link:ReleaseNotes-2.10.3.1.html[2.10.3.1]
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 6db9362..7731415 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -51,7 +51,6 @@
 import com.google.gerrit.server.events.ChangeMergedEvent;
 import com.google.gerrit.server.events.Event;
 import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.testutil.ConfigSuite;
 import com.google.gson.reflect.TypeToken;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
@@ -59,7 +58,6 @@
 import org.apache.http.HttpStatus;
 import org.eclipse.jgit.diff.DiffFormatter;
 import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -77,11 +75,6 @@
 import java.util.Map;
 
 public abstract class AbstractSubmit extends AbstractDaemonTest {
-  @ConfigSuite.Config
-  public static Config submitWholeTopicEnabled() {
-    return submitWholeTopicEnabledConfig();
-  }
-
   private Map<String, String> mergeResults;
 
   @Inject
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
index 66c99f1..a9d5ad3 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
@@ -20,21 +20,14 @@
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.common.ActionInfo;
-import com.google.gerrit.testutil.ConfigSuite;
 
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
 import org.junit.Test;
 
 import java.util.Map;
 
 public class ActionsIT extends AbstractDaemonTest {
-  @ConfigSuite.Config
-  public static Config submitWholeTopicEnabled() {
-    return submitWholeTopicEnabledConfig();
-  }
-
   @Test
   public void revisionActionsOneChangePerTopicUnapproved() throws Exception {
     String changeId = createChangeWithTopic().getChangeId();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
index 94198cb..45b1d52 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
@@ -16,7 +16,6 @@
 
 import com.google.gerrit.client.changes.QueryScreen;
 import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.client.ui.RemoteSuggestOracle;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -55,9 +54,8 @@
       }
     });
 
-    final SuggestBox suggestBox = new SuggestBox(
-        new RemoteSuggestOracle(new SearchSuggestOracle()),
-        searchBox, suggestionDisplay);
+    final SuggestBox suggestBox =
+        new SuggestBox(new SearchSuggestOracle(), searchBox, suggestionDisplay);
     searchBox.setStyleName("searchTextBox");
     searchBox.setVisibleLength(70);
     searchBox.setHintText(Gerrit.C.searchHint());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index a25d9b3..1384ac9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -56,7 +56,9 @@
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.BatchRefUpdate;
 import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -75,6 +77,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -364,15 +367,39 @@
     }
 
     ReviewDb db = this.db.get();
-    for (PatchSet ps : db.patchSets().byChange(changeId)) {
-      // These should all be draft patch sets.
-      deleteOnlyDraftPatchSet(ps, change);
-    }
+    db.changes().beginTransaction(change.getId());
+    try {
+      Map<RevId, String> refsToDelete = new HashMap<>();
+      for (PatchSet ps : db.patchSets().byChange(changeId)) {
+        // These should all be draft patch sets.
+        deleteOnlyDraftPatchSetPreserveRef(db, ps);
+        refsToDelete.put(ps.getRevision(), ps.getRefName());
+      }
+      db.changeMessages().delete(db.changeMessages().byChange(changeId));
+      db.starredChanges().delete(db.starredChanges().byChange(changeId));
+      db.changes().delete(Collections.singleton(change));
 
-    db.changeMessages().delete(db.changeMessages().byChange(changeId));
-    db.starredChanges().delete(db.starredChanges().byChange(changeId));
-    db.changes().delete(Collections.singleton(change));
-    indexer.delete(change.getId());
+      // Delete all refs at once
+      try (Repository repo = gitManager.openRepository(change.getProject());
+          RevWalk rw = new RevWalk(repo)) {
+        BatchRefUpdate ru = repo.getRefDatabase().newBatchUpdate();
+        for (Map.Entry<RevId, String> e : refsToDelete.entrySet()) {
+          ru.addCommand(new ReceiveCommand(ObjectId.fromString(e.getKey().get()),
+              ObjectId.zeroId(), e.getValue()));
+        }
+        ru.execute(rw, NullProgressMonitor.INSTANCE);
+        for (ReceiveCommand cmd : ru.getCommands()) {
+          if (cmd.getResult() != ReceiveCommand.Result.OK) {
+            throw new IOException("failed: " + cmd);
+          }
+        }
+      }
+
+      db.commit();
+      indexer.delete(change.getId());
+    } finally {
+      db.rollback();
+    }
   }
 
   public void deleteOnlyDraftPatchSet(PatchSet patch, Change change)
@@ -400,15 +427,7 @@
       gitRefUpdated.fire(change.getProject(), update, ReceiveCommand.Type.DELETE);
     }
 
-    ReviewDb db = this.db.get();
-    db.accountPatchReviews().delete(db.accountPatchReviews().byPatchSet(patchSetId));
-    db.changeMessages().delete(db.changeMessages().byPatchSet(patchSetId));
-    // No need to delete from notedb; draft patch sets will be filtered out.
-    db.patchComments().delete(db.patchComments().byPatchSet(patchSetId));
-    db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(patchSetId));
-    db.patchSetAncestors().delete(db.patchSetAncestors().byPatchSet(patchSetId));
-
-    db.patchSets().delete(Collections.singleton(patch));
+    deleteOnlyDraftPatchSetPreserveRef(this.db.get(), patch);
   }
 
   /**
@@ -450,6 +469,23 @@
     return (IdentifiedUser) userProvider.get();
   }
 
+  private static void deleteOnlyDraftPatchSetPreserveRef(ReviewDb db,
+      PatchSet patch) throws NoSuchChangeException, OrmException {
+    PatchSet.Id patchSetId = patch.getId();
+    if (!patch.isDraft()) {
+      throw new NoSuchChangeException(patchSetId.getParentKey());
+    }
+
+    db.accountPatchReviews().delete(db.accountPatchReviews().byPatchSet(patchSetId));
+    db.changeMessages().delete(db.changeMessages().byPatchSet(patchSetId));
+    // No need to delete from notedb; draft patch sets will be filtered out.
+    db.patchComments().delete(db.patchComments().byPatchSet(patchSetId));
+    db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(patchSetId));
+    db.patchSetAncestors().delete(db.patchSetAncestors().byPatchSet(patchSetId));
+
+    db.patchSets().delete(Collections.singleton(patch));
+  }
+
   public static PatchSet.Id nextPatchSetId(PatchSet.Id id) {
     return new PatchSet.Id(id.getParentKey(), id.get() + 1);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
index 982f897..45b7c4d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ReindexAfterUpdate.java
@@ -120,6 +120,12 @@
             new Branch.NameKey(project, ref)));
       }
     }
+
+    @Override
+    public String toString() {
+      return "Get changes to reindex caused by " + event.getRefName()
+          + " update of project " + event.getProjectName();
+    }
   }
 
   private class Index extends Task<Void> {
@@ -138,5 +144,11 @@
       indexerFactory.create(executor, indexes).index(db, c);
       return null;
     }
+
+    @Override
+    public String toString() {
+      return "Index change " + id.get() + " of project "
+          + event.getProjectName();
+    }
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
index 909cb53..775e967 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/SiteIndexer.java
@@ -259,6 +259,11 @@
         }
         return null;
       }
+
+      @Override
+      public String toString() {
+        return "Index all changes of project " + project.get();
+      }
     };
   }