Replace document when reusing existing documents during offline reindex

The offline reindexing tool would bind IsFirstInsertForEntry.YES. This
caused the ChangeIndexer to insert a document in the index. However, if
we reuse existing documents the old index was not deleted. This led to
duplicate entries in the index, if a change was stale.

Now, if the reuseExistingDocuments option is being used, the index
documents will be replaced instead with a fallback to creating them
in case they are not yet existing.

Release-Notes: Fix duplicate index entries after offline reindex with --reuse
Change-Id: Iae0ce7f9ecc50f0237a689346566d2ee287effd2
diff --git a/java/com/google/gerrit/pgm/Reindex.java b/java/com/google/gerrit/pgm/Reindex.java
index e800d17..d393a89 100644
--- a/java/com/google/gerrit/pgm/Reindex.java
+++ b/java/com/google/gerrit/pgm/Reindex.java
@@ -104,6 +104,7 @@
   private Injector sysInjector;
   private Injector cfgInjector;
   private Config globalConfig;
+  private boolean reuseExistingDocuments;
 
   @Inject private Collection<IndexDefinition<?, ?, ?>> indexDefs;
   @Inject private DynamicMap<Cache<?, ?>> cacheMap;
@@ -120,6 +121,10 @@
     cfgInjector = dbInjector.createChildInjector();
     globalConfig = dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
     overrideConfig();
+    reuseExistingDocuments =
+        reuseExistingDocumentsOption != null
+            ? reuseExistingDocumentsOption
+            : globalConfig.getBoolean("index", null, "reuseExistingDocuments", false);
     LifecycleManager dbManager = new LifecycleManager();
     dbManager.add(dbInjector);
     dbManager.start();
@@ -221,7 +226,8 @@
             super.configure();
             OptionalBinder.newOptionalBinder(binder(), IsFirstInsertForEntry.class)
                 .setBinding()
-                .toInstance(IsFirstInsertForEntry.YES);
+                .toInstance(
+                    reuseExistingDocuments ? IsFirstInsertForEntry.NO : IsFirstInsertForEntry.YES);
             OptionalBinder.newOptionalBinder(binder(), BuildBloomFilter.class)
                 .setBinding()
                 .toInstance(buildBloomFilter ? BuildBloomFilter.TRUE : BuildBloomFilter.FALSE);
@@ -265,10 +271,6 @@
     requireNonNull(
         index, () -> String.format("no active search index configured for %s", def.getName()));
     index.markReady(false);
-    boolean reuseExistingDocuments =
-        reuseExistingDocumentsOption != null
-            ? reuseExistingDocumentsOption
-            : globalConfig.getBoolean("index", null, "reuseExistingDocuments", false);
 
     if (!reuseExistingDocuments) {
       index.deleteAll();