Make MetaDataUpdate auto-closeable

And convert users to instantiate it in try-with-resource blocks.

Change-Id: Ief1a42ccbf4b3d943a7987b2c9b8077175695515
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 3cea4a2..4414593 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -552,11 +552,8 @@
 
   protected void saveProjectConfig(Project.NameKey p, ProjectConfig cfg)
       throws Exception {
-    MetaDataUpdate md = metaDataUpdateFactory.create(p);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(p)) {
       cfg.commit(md);
-    } finally {
-      md.close();
     }
     projectCache.evict(cfg.getProject());
   }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index 73a02a5..d104a41 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -83,11 +83,8 @@
   }
 
   private void saveProjectConfig(ProjectConfig cfg) throws Exception {
-    MetaDataUpdate md = metaDataUpdateFactory.create(project);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
       cfg.commit(md);
-    } finally {
-      md.close();
     }
   }
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
index f7e11fb..534afcb 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
@@ -321,11 +321,8 @@
   }
 
   private void saveProjectConfig(ProjectConfig cfg) throws Exception {
-    MetaDataUpdate md = metaDataUpdateFactory.create(project);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
       cfg.commit(md);
-    } finally {
-      md.close();
     }
   }
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
index aee238d..ed2a4f9 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
@@ -100,8 +100,7 @@
     // state, force a cache flush now.
     //
     ProjectConfig config;
-    MetaDataUpdate md = metaDataUpdateFactory.create(projectName);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
       config = ProjectConfig.read(md);
 
       if (config.updateGroupNames(groupBackend)) {
@@ -115,8 +114,6 @@
         projectCache.evict(config.getProject());
         pc = open();
       }
-    } finally {
-      md.close();
     }
 
     final RefControl metaConfigControl = pc.controlForRef(RefNames.REFS_CONFIG);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
index ba4f012..f8d3e70 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessHandler.java
@@ -92,13 +92,7 @@
     final ProjectControl projectControl =
         projectControlFactory.controlFor(projectName);
 
-    final MetaDataUpdate md;
-    try {
-      md = metaDataUpdateFactory.create(projectName);
-    } catch (RepositoryNotFoundException notFound) {
-      throw new NoSuchProjectException(projectName);
-    }
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
       ProjectConfig config = ProjectConfig.read(md, base);
       Set<String> toDelete = scanSectionNames(config);
 
@@ -163,8 +157,8 @@
 
       return updateProjectConfig(projectControl, config, md,
           parentProjectUpdate);
-    } finally {
-      md.close();
+    } catch (RepositoryNotFoundException notFound) {
+      throw new NoSuchProjectException(projectName);
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/access/ListAccess.java b/gerrit-server/src/main/java/com/google/gerrit/server/access/ListAccess.java
index 93a3814..04546aa 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/access/ListAccess.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/access/ListAccess.java
@@ -93,40 +93,32 @@
       throws ResourceNotFoundException, ResourceConflictException, IOException {
     Map<String, ProjectAccessInfo> access = Maps.newTreeMap();
     for (String p: projects) {
+      // Load the current configuration from the repository, ensuring it's the most
+      // recent version available. If it differs from what was in the project
+      // state, force a cache flush now.
+      //
       Project.NameKey projectName = new Project.NameKey(p);
-      ProjectControl pc = open(projectName);
-      ProjectConfig config;
+      try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
+        ProjectControl pc = open(projectName);
+        ProjectConfig config = ProjectConfig.read(md);
 
-      try {
-        // Load the current configuration from the repository, ensuring it's the most
-        // recent version available. If it differs from what was in the project
-        // state, force a cache flush now.
-        //
-        MetaDataUpdate md = metaDataUpdateFactory.create(projectName);
-        try {
-          config = ProjectConfig.read(md);
-
-          if (config.updateGroupNames(groupBackend)) {
-            md.setMessage("Update group names\n");
-            config.commit(md);
-            projectCache.evict(config.getProject());
-            pc = open(projectName);
-          } else if (config.getRevision() != null
-              && !config.getRevision().equals(
-                  pc.getProjectState().getConfig().getRevision())) {
-            projectCache.evict(config.getProject());
-            pc = open(projectName);
-          }
-        } catch (ConfigInvalidException e) {
-          throw new ResourceConflictException(e.getMessage());
-        } finally {
-          md.close();
+        if (config.updateGroupNames(groupBackend)) {
+          md.setMessage("Update group names\n");
+          config.commit(md);
+          projectCache.evict(config.getProject());
+          pc = open(projectName);
+        } else if (config.getRevision() != null
+            && !config.getRevision().equals(
+                pc.getProjectState().getConfig().getRevision())) {
+          projectCache.evict(config.getProject());
+          pc = open(projectName);
         }
+        access.put(p, new ProjectAccessInfo(pc, config));
+      } catch (ConfigInvalidException e) {
+        throw new ResourceConflictException(e.getMessage());
       } catch (RepositoryNotFoundException e) {
         throw new ResourceNotFoundException(p);
       }
-
-      access.put(p, new ProjectAccessInfo(pc, config));
     }
     return access;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetDiffPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetDiffPreferences.java
index e14791c..9617d94 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetDiffPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetDiffPreferences.java
@@ -77,10 +77,8 @@
   private DiffPreferencesInfo writeToGit(DiffPreferencesInfo in,
       Account.Id userId) throws RepositoryNotFoundException, IOException,
           ConfigInvalidException {
-    MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName);
-
     DiffPreferencesInfo out = new DiffPreferencesInfo();
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName)) {
       VersionedAccountPreferences prefs = VersionedAccountPreferences.forUser(
           userId);
       prefs.load(md);
@@ -90,8 +88,6 @@
       prefs.commit(md);
       loadSection(prefs.getConfig(), UserConfigSections.DIFF, null, out,
           DiffPreferencesInfo.defaults(), null);
-    } finally {
-      md.close();
     }
     return out;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetEditPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetEditPreferences.java
index eabe31d..d51e24a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetEditPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetEditPreferences.java
@@ -71,18 +71,15 @@
     }
 
     Account.Id accountId = rsrc.getUser().getAccountId();
-    MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName);
 
     VersionedAccountPreferences prefs;
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName)) {
       prefs = VersionedAccountPreferences.forUser(accountId);
       prefs.load(md);
       storeSection(prefs.getConfig(), UserConfigSections.EDIT, null,
           readFromGit(accountId, gitMgr, allUsersName, in),
           EditPreferencesInfo.defaults());
       prefs.commit(md);
-    } finally {
-      md.close();
     }
 
     return Response.none();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
index 7042076..51c54ac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/SetPreferences.java
@@ -115,9 +115,8 @@
     Account.Id accountId = rsrc.getUser().getAccountId();
     AccountGeneralPreferences p;
     VersionedAccountPreferences versionedPrefs;
-    MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName);
     db.get().accounts().beginTransaction(accountId);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName)) {
       Account a = db.get().accounts().get(accountId);
       if (a == null) {
         throw new ResourceNotFoundException();
@@ -184,7 +183,6 @@
       return new GetPreferences.PreferenceInfo(
           p, versionedPrefs, md.getRepository());
     } finally {
-      md.close();
       db.get().rollback();
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java
index d6693ae..07d22b3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SetPreferences.java
@@ -60,15 +60,12 @@
     }
 
     VersionedAccountPreferences p;
-    MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName);
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsersName)) {
       p = VersionedAccountPreferences.forDefault();
       p.load(md);
       com.google.gerrit.server.account.SetPreferences.storeMyMenus(p, i.my);
       p.commit(md);
       return new PreferenceInfo(null, p, md.getRepository());
-    } finally {
-      md.close();
     }
   }
 }
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 840b167..9562945 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
@@ -34,7 +34,7 @@
 import java.io.IOException;
 
 /** Helps with the updating of a {@link VersionedMetaData}. */
-public class MetaDataUpdate {
+public class MetaDataUpdate implements AutoCloseable {
   public static class User {
     private final InternalFactory factory;
     private final GitRepositoryManager mgr;
@@ -191,6 +191,7 @@
   }
 
   /** Close the cached Repository handle. */
+  @Override
   public void close() {
     getRepository().close();
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
index 06314db..00c9a7c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/RenameGroupOp.java
@@ -83,13 +83,8 @@
         continue;
       }
 
-      try {
-        MetaDataUpdate md = metaDataUpdateFactory.create(projectName);
-        try {
-          rename(md);
-        } finally {
-          md.close();
-        }
+      try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
+        rename(md);
       } catch (RepositoryNotFoundException noProject) {
         continue;
       } catch (ConfigInvalidException | IOException err) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
index c4b686c..c460fd0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
@@ -284,9 +284,7 @@
   }
 
   private void createProjectConfig(CreateProjectArgs args) throws IOException, ConfigInvalidException {
-    MetaDataUpdate md =
-        metaDataUpdateFactory.create(args.getProject());
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(args.getProject())) {
       ProjectConfig config = ProjectConfig.read(md);
       config.load(md);
 
@@ -321,8 +319,6 @@
 
       md.setMessage("Created project\n");
       config.commit(md);
-    } finally {
-      md.close();
     }
     projectCache.onCreateProject(args.getProject());
     repoManager.setProjectDescription(args.getProject(),
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
index 5f921b1..fd7539f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
@@ -139,15 +139,7 @@
       throw new BadRequestException("config is required");
     }
 
-    final MetaDataUpdate md;
-    try {
-      md = metaDataUpdateFactory.get().create(projectName);
-    } catch (RepositoryNotFoundException notFound) {
-      throw new ResourceNotFoundException(projectName.get());
-    } catch (IOException e) {
-      throw new ResourceNotFoundException(projectName.get(), e);
-    }
-    try {
+    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(projectName)) {
       ProjectConfig projectConfig = ProjectConfig.read(md);
       Project p = projectConfig.getProject();
 
@@ -226,12 +218,12 @@
       return new ConfigInfo(serverEnableSignedPush,
           state.controlFor(user.get()), config, pluginConfigEntries,
           cfgFactory, allProjects, views);
+    } catch (RepositoryNotFoundException notFound) {
+      throw new ResourceNotFoundException(projectName.get());
     } catch (ConfigInvalidException err) {
       throw new ResourceConflictException("Cannot read project " + projectName, err);
     } catch (IOException err) {
       throw new ResourceConflictException("Cannot update project " + projectName, err);
-    } finally {
-      md.close();
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
index 2d407bd..7cf426d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
@@ -76,42 +76,37 @@
       throw new AuthException("not project owner");
     }
 
-    try {
-      MetaDataUpdate md = updateFactory.create(resource.getNameKey());
-      try {
-        ProjectConfig config = ProjectConfig.read(md);
-        Project project = config.getProject();
-        project.setDescription(Strings.emptyToNull(input.description));
+    try (MetaDataUpdate md = updateFactory.create(resource.getNameKey())) {
+      ProjectConfig config = ProjectConfig.read(md);
+      Project project = config.getProject();
+      project.setDescription(Strings.emptyToNull(input.description));
 
-        String msg = MoreObjects.firstNonNull(
-          Strings.emptyToNull(input.commitMessage),
-          "Updated description.\n");
-        if (!msg.endsWith("\n")) {
-          msg += "\n";
-        }
-        md.setAuthor(user);
-        md.setMessage(msg);
-        ObjectId baseRev = config.getRevision();
-        ObjectId commitRev = config.commit(md);
-        // Only fire hook if project was actually changed.
-        if (!Objects.equals(baseRev, commitRev)) {
-          gitRefUpdated.fire(resource.getNameKey(), RefNames.REFS_CONFIG,
-              baseRev, commitRev);
-          hooks.doRefUpdatedHook(
-            new Branch.NameKey(resource.getNameKey(), RefNames.REFS_CONFIG),
-            baseRev, commitRev, user.getAccount());
-        }
-        cache.evict(ctl.getProject());
-        gitMgr.setProjectDescription(
-            resource.getNameKey(),
-            project.getDescription());
-
-        return Strings.isNullOrEmpty(project.getDescription())
-            ? Response.<String>none()
-            : Response.ok(project.getDescription());
-      } finally {
-        md.close();
+      String msg = MoreObjects.firstNonNull(
+        Strings.emptyToNull(input.commitMessage),
+        "Updated description.\n");
+      if (!msg.endsWith("\n")) {
+        msg += "\n";
       }
+      md.setAuthor(user);
+      md.setMessage(msg);
+      ObjectId baseRev = config.getRevision();
+      ObjectId commitRev = config.commit(md);
+      // Only fire hook if project was actually changed.
+      if (!Objects.equals(baseRev, commitRev)) {
+        gitRefUpdated.fire(resource.getNameKey(), RefNames.REFS_CONFIG,
+            baseRev, commitRev);
+        hooks.doRefUpdatedHook(
+          new Branch.NameKey(resource.getNameKey(), RefNames.REFS_CONFIG),
+          baseRev, commitRev, user.getAccount());
+      }
+      cache.evict(ctl.getProject());
+      gitMgr.setProjectDescription(
+          resource.getNameKey(),
+          project.getDescription());
+
+      return Strings.isNullOrEmpty(project.getDescription())
+          ? Response.<String>none()
+          : Response.ok(project.getDescription());
     } catch (RepositoryNotFoundException notFound) {
       throw new ResourceNotFoundException(resource.getName());
     } catch (ConfigInvalidException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
index ac01de5..641c3a7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
@@ -84,39 +84,34 @@
       }
     }
 
-    try {
-      MetaDataUpdate md = updateFactory.create(ctl.getProject().getNameKey());
-      try {
-        ProjectConfig config = ProjectConfig.read(md);
-        Project project = config.getProject();
-        if (inherited) {
-          project.setDefaultDashboard(input.id);
-        } else {
-          project.setLocalDefaultDashboard(input.id);
-        }
-
-        String msg = MoreObjects.firstNonNull(
-          Strings.emptyToNull(input.commitMessage),
-          input.id == null
-            ? "Removed default dashboard.\n"
-            : String.format("Changed default dashboard to %s.\n", input.id));
-        if (!msg.endsWith("\n")) {
-          msg += "\n";
-        }
-        md.setAuthor(ctl.getUser().asIdentifiedUser());
-        md.setMessage(msg);
-        config.commit(md);
-        cache.evict(ctl.getProject());
-
-        if (target != null) {
-          DashboardInfo info = get.get().apply(target);
-          info.isDefault = true;
-          return Response.ok(info);
-        }
-        return Response.none();
-      } finally {
-        md.close();
+    try (MetaDataUpdate md = updateFactory.create(ctl.getProject().getNameKey())) {
+      ProjectConfig config = ProjectConfig.read(md);
+      Project project = config.getProject();
+      if (inherited) {
+        project.setDefaultDashboard(input.id);
+      } else {
+        project.setLocalDefaultDashboard(input.id);
       }
+
+      String msg = MoreObjects.firstNonNull(
+        Strings.emptyToNull(input.commitMessage),
+        input.id == null
+          ? "Removed default dashboard.\n"
+          : String.format("Changed default dashboard to %s.\n", input.id));
+      if (!msg.endsWith("\n")) {
+        msg += "\n";
+      }
+      md.setAuthor(ctl.getUser().asIdentifiedUser());
+      md.setMessage(msg);
+      config.commit(md);
+      cache.evict(ctl.getProject());
+
+      if (target != null) {
+        DashboardInfo info = get.get().apply(target);
+        info.isDefault = true;
+        return Response.ok(info);
+      }
+      return Response.none();
     } catch (RepositoryNotFoundException notFound) {
       throw new ResourceNotFoundException(ctl.getProject().getName());
     } catch (ConfigInvalidException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
index 15c977f..8113c01 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
@@ -71,32 +71,27 @@
       ResourceNotFoundException, UnprocessableEntityException, IOException {
     ProjectControl ctl = rsrc.getControl();
     validateParentUpdate(ctl, input.parent, checkIfAdmin);
-    try {
-      MetaDataUpdate md = updateFactory.create(rsrc.getNameKey());
-      try {
-        ProjectConfig config = ProjectConfig.read(md);
-        Project project = config.getProject();
-        project.setParentName(Strings.emptyToNull(input.parent));
+    try (MetaDataUpdate md = updateFactory.create(rsrc.getNameKey())) {
+      ProjectConfig config = ProjectConfig.read(md);
+      Project project = config.getProject();
+      project.setParentName(Strings.emptyToNull(input.parent));
 
-        String msg = Strings.emptyToNull(input.commitMessage);
-        if (msg == null) {
-          msg = String.format(
-              "Changed parent to %s.\n",
-              MoreObjects.firstNonNull(project.getParentName(),
-                  allProjects.get()));
-        } else if (!msg.endsWith("\n")) {
-          msg += "\n";
-        }
-        md.setAuthor(ctl.getUser().asIdentifiedUser());
-        md.setMessage(msg);
-        config.commit(md);
-        cache.evict(ctl.getProject());
-
-        Project.NameKey parentName = project.getParent(allProjects);
-        return parentName != null ? parentName.get() : "";
-      } finally {
-        md.close();
+      String msg = Strings.emptyToNull(input.commitMessage);
+      if (msg == null) {
+        msg = String.format(
+            "Changed parent to %s.\n",
+            MoreObjects.firstNonNull(project.getParentName(),
+                allProjects.get()));
+      } else if (!msg.endsWith("\n")) {
+        msg += "\n";
       }
+      md.setAuthor(ctl.getUser().asIdentifiedUser());
+      md.setMessage(msg);
+      config.commit(md);
+      cache.evict(ctl.getProject());
+
+      Project.NameKey parentName = project.getParent(allProjects);
+      return parentName != null ? parentName.get() : "";
     } catch (RepositoryNotFoundException notFound) {
       throw new ResourceNotFoundException(rsrc.getName());
     } catch (ConfigInvalidException e) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
index 6ed70a2..2fb91f6 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminSetParent.java
@@ -145,17 +145,12 @@
         continue;
       }
 
-      try {
-        MetaDataUpdate md = metaDataUpdateFactory.create(nameKey);
-        try {
-          ProjectConfig config = ProjectConfig.read(md);
-          config.getProject().setParentName(newParentKey);
-          md.setMessage("Inherit access from "
-              + (newParentKey != null ? newParentKey.get() : allProjectsName.get()) + "\n");
-          config.commit(md);
-        } finally {
-          md.close();
-        }
+      try (MetaDataUpdate md = metaDataUpdateFactory.create(nameKey)) {
+        ProjectConfig config = ProjectConfig.read(md);
+        config.getProject().setParentName(newParentKey);
+        md.setMessage("Inherit access from "
+            + (newParentKey != null ? newParentKey.get() : allProjectsName.get()) + "\n");
+        config.commit(md);
       } catch (RepositoryNotFoundException notFound) {
         err.append("error: Project ").append(name).append(" not found\n");
       } catch (IOException | ConfigInvalidException e) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetProjectCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
index ab1353b..589fbf0 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
@@ -124,41 +124,36 @@
     String name = ctlProject.getName();
     final StringBuilder err = new StringBuilder();
 
-    try {
-      MetaDataUpdate md = metaDataUpdateFactory.create(nameKey);
-      try {
-        ProjectConfig config = ProjectConfig.read(md);
-        Project project = config.getProject();
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(nameKey)) {
+      ProjectConfig config = ProjectConfig.read(md);
+      Project project = config.getProject();
 
-        if (requireChangeID != null) {
-          project.setRequireChangeID(requireChangeID);
-        }
-        if (submitType != null) {
-          project.setSubmitType(submitType);
-        }
-        if (contentMerge != null) {
-          project.setUseContentMerge(contentMerge);
-        }
-        if (contributorAgreements != null) {
-          project.setUseContributorAgreements(contributorAgreements);
-        }
-        if (signedOffBy != null) {
-          project.setUseSignedOffBy(signedOffBy);
-        }
-        if (projectDescription != null) {
-          project.setDescription(projectDescription);
-        }
-        if (state != null) {
-          project.setState(state);
-        }
-        if (maxObjectSizeLimit != null) {
-          project.setMaxObjectSizeLimit(maxObjectSizeLimit);
-        }
-        md.setMessage("Project settings updated");
-        config.commit(md);
-      } finally {
-        md.close();
+      if (requireChangeID != null) {
+        project.setRequireChangeID(requireChangeID);
       }
+      if (submitType != null) {
+        project.setSubmitType(submitType);
+      }
+      if (contentMerge != null) {
+        project.setUseContentMerge(contentMerge);
+      }
+      if (contributorAgreements != null) {
+        project.setUseContributorAgreements(contributorAgreements);
+      }
+      if (signedOffBy != null) {
+        project.setUseSignedOffBy(signedOffBy);
+      }
+      if (projectDescription != null) {
+        project.setDescription(projectDescription);
+      }
+      if (state != null) {
+        project.setState(state);
+      }
+      if (maxObjectSizeLimit != null) {
+        project.setMaxObjectSizeLimit(maxObjectSizeLimit);
+      }
+      md.setMessage("Project settings updated");
+      config.commit(md);
     } catch (RepositoryNotFoundException notFound) {
       err.append("error: Project ").append(name).append(" not found\n");
     } catch (IOException | ConfigInvalidException e) {