MetaDataUpdate: Do not close repository that was passed in

The repository to be updated by MetaDataUpdate can either be passed
in, or created based on other passed parameters.

If the repository is passed in, it should not be closed by the
MetaDataUpdate's close() method. This is because it is possible that
the repository was created in a try-with-resource block and will get
automatically closed. Closing it in MetaDataUpdate will then cause
the repository to be closed too many times, resulting in a corrupt use
count.

Update the static factory methods to prevent closing of the repository
that was passed in. Also update the Javadoc to explicitly mention that
the passed in repository must be closed by the caller.

Also rename 'db' member variable and parameters to 'repository' which
is more meaningful.

Bug: Issue 5404
Change-Id: I7ef68ecba31f1ca2528cf96c698c908c7303bdca
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
index a31d1fc..7e47d1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
@@ -79,7 +79,10 @@
    */
     public MetaDataUpdate create(Project.NameKey name, IdentifiedUser user,
         BatchRefUpdate batch) throws RepositoryNotFoundException, IOException {
-      return create(name, mgr.openRepository(name), user, batch);
+      Repository repo = mgr.openRepository(name);
+      MetaDataUpdate md = create(name, repo, user, batch);
+      md.setCloseRepository(true);
+      return md;
     }
 
     /**
@@ -117,7 +120,8 @@
      * </pre>
      *
      * @param name project name.
-     * @param repository GIT respository
+     * @param repository the repository to update; the caller is responsible for
+     *     closing the repository.
      * @param user user for the update.
      * @param batch batch update to use; the caller is responsible for committing
      *     the update.
@@ -157,7 +161,9 @@
     /** @see User#create(Project.NameKey, IdentifiedUser, BatchRefUpdate) */
     public MetaDataUpdate create(Project.NameKey name, BatchRefUpdate batch)
         throws RepositoryNotFoundException, IOException {
-      MetaDataUpdate md = factory.create(name, mgr.openRepository(name), batch);
+      Repository repo = mgr.openRepository(name);
+      MetaDataUpdate md = factory.create(name, repo, batch);
+      md.setCloseRepository(true);
       md.getCommitBuilder().setAuthor(serverIdent);
       md.getCommitBuilder().setCommitter(serverIdent);
       return md;
@@ -166,32 +172,34 @@
 
   interface InternalFactory {
     MetaDataUpdate create(@Assisted Project.NameKey projectName,
-        @Assisted Repository db, @Assisted @Nullable BatchRefUpdate batch);
+        @Assisted Repository repository,
+        @Assisted @Nullable BatchRefUpdate batch);
   }
 
   private final GitReferenceUpdated gitRefUpdated;
   private final Project.NameKey projectName;
-  private final Repository db;
+  private final Repository repository;
   private final BatchRefUpdate batch;
   private final CommitBuilder commit;
   private boolean allowEmpty;
   private boolean insertChangeId;
+  private boolean closeRepository;
   private IdentifiedUser author;
 
   @AssistedInject
   public MetaDataUpdate(GitReferenceUpdated gitRefUpdated,
-      @Assisted Project.NameKey projectName, @Assisted Repository db,
+      @Assisted Project.NameKey projectName, @Assisted Repository repository,
       @Assisted @Nullable BatchRefUpdate batch) {
     this.gitRefUpdated = gitRefUpdated;
     this.projectName = projectName;
-    this.db = db;
+    this.repository = repository;
     this.batch = batch;
     this.commit = new CommitBuilder();
   }
 
   public MetaDataUpdate(GitReferenceUpdated gitRefUpdated,
-      Project.NameKey projectName, Repository db) {
-    this(gitRefUpdated, projectName, db, null);
+      Project.NameKey projectName, Repository repository) {
+    this(gitRefUpdated, projectName, repository, null);
   }
 
   /** Set the commit message used when committing the update. */
@@ -214,6 +222,10 @@
     this.insertChangeId = insertChangeId;
   }
 
+  public void setCloseRepository(boolean closeRepository) {
+    this.closeRepository = closeRepository;
+  }
+
   /** @return batch in which to run the update, or {@code null} for no batch. */
   BatchRefUpdate getBatch() {
     return batch;
@@ -222,7 +234,9 @@
   /** Close the cached Repository handle. */
   @Override
   public void close() {
-    getRepository().close();
+    if (closeRepository) {
+      getRepository().close();
+    }
   }
 
   Project.NameKey getProjectName() {
@@ -230,7 +244,7 @@
   }
 
   public Repository getRepository() {
-    return db;
+    return repository;
   }
 
   boolean allowEmpty() {