Merge branch 'stable-2.15' into stable-2.16

* stable-2.15:
  Migrate `tools/bazel.rc` to `.bazelrc`
  Upgrade bazlets to latest stable-2.15 to build with 2.15.7 API
  Upgrade bazlets to latest stable-2.15 to build with 2.15.6 API
  Align Eclipse compiler settings with core Gerrit's
  WORKSPACE: Make commented out lines spaces indent consistent
  bazlets: Replace native.git_repository with skylark rule
  Upgrade bazlets to latest stable-2.15 to build with 2.15.5 API
  Update bazlets to latest stable-2.15 to build with 2.15.4 API
  Replace Guava functional constructs with Java native ones
  Remove final qualifiers
  Fix broken build status badge link
  Allow to protect specific projects against deletion
  Add tests for protected projects

Change-Id: I2aa88b659c17cf643e2914989e1331f67718f595
diff --git a/BUILD b/BUILD
index 46ddcfe..ef23579 100644
--- a/BUILD
+++ b/BUILD
@@ -5,6 +5,9 @@
     "PLUGIN_TEST_DEPS",
     "gerrit_plugin",
 )
+load("//tools/bzl:genrule2.bzl", "genrule2")
+load("//tools/bzl:js.bzl", "polygerrit_plugin")
+
 
 gerrit_plugin(
     name = "delete-project",
@@ -16,6 +19,28 @@
         "Gerrit-SshModule: com.googlesource.gerrit.plugins.deleteproject.SshModule",
     ],
     resources = glob(["src/main/resources/**/*"]),
+    resource_jars = [":gr-delete-repo-static"],
+)
+
+genrule2(
+    name = "gr-delete-repo-static",
+    srcs = [":gr-delete-repo"],
+    outs = ["gr-delete-repo-static.jar"],
+    cmd = " && ".join([
+        "mkdir $$TMP/static",
+        "cp -r $(locations :gr-delete-repo) $$TMP/static",
+        "cd $$TMP",
+        "zip -Drq $$ROOT/$@ -g .",
+    ]),
+)
+
+polygerrit_plugin(
+    name = "gr-delete-repo",
+    srcs = glob([
+        "gr-delete-repo/*.html",
+        "gr-delete-repo/*.js",
+    ]),
+    app = "plugin.html",
 )
 
 junit_tests(
diff --git a/WORKSPACE b/WORKSPACE
index a9f0710..4cdbf86 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,10 +3,36 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "b54eaed487d37188120da6933b97c571519954ca",
+    commit = "e4662688b3f482cf5789b27a1ea726e8d0aabfc8",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
+# Polymer dependencies
+load(
+    "@com_googlesource_gerrit_bazlets//:gerrit_polymer.bzl",
+    "gerrit_polymer",
+)
+
+gerrit_polymer()
+
+# Load closure compiler with transitive dependencies
+load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories")
+
+closure_repositories()
+
+# Load Gerrit npm_binary toolchain
+load("@com_googlesource_gerrit_bazlets//tools:js.bzl", "GERRIT", "npm_binary")
+
+npm_binary(
+    name = "polymer-bundler",
+    repository = GERRIT,
+)
+
+npm_binary(
+    name = "crisper",
+    repository = GERRIT,
+)
+
 # Snapshot Plugin API
 #load(
 #    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
diff --git a/gr-delete-repo/gr-delete-repo.html b/gr-delete-repo/gr-delete-repo.html
new file mode 100644
index 0000000..c2a4a1b
--- /dev/null
+++ b/gr-delete-repo/gr-delete-repo.html
@@ -0,0 +1,57 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<dom-module id="gr-delete-repo">
+  <template>
+    <style include="gr-form-styles"></style>
+    <gr-repo-command
+        title="[[action.label]]"
+        tooltip="[[action.title]]"
+        disabled="[[!action.enabled]]"
+        on-command-tap="_handleCommandTap">
+    </gr-repo-command>
+    <gr-overlay id="deleteRepoOverlay" with-backdrop>
+      <gr-dialog
+          id="deleteRepoDialog"
+          confirm-label="Delete"
+          on-confirm="_handleDeleteRepo"
+          on-cancel="_handleCloseDeleteRepo">
+        <div class="header" slot="header">
+          Are you really sure you want to delete the repo: "[[repoName]]"?
+        </div>
+        <div class="main" slot="main">
+          <div class="gr-form-styles">
+            <div id="form">
+                <section>
+                  <input
+                      type="checkbox"
+                      id="forceDeleteOpenChangesCheckBox">
+                  <label for="forceDeleteOpenChangesCheckBox">Delete repo even if open changes exist?</label>
+                </section>
+                <section>
+                  <input
+                      type="checkbox"
+                      id="preserveGitRepoCheckBox">
+                  <label for="preserveGitRepoCheckBox">Preserve GIT Repository?</label>
+                </section>
+            </div>
+          </div>
+        </div>
+      </gr-dialog>
+    </gr-overlay>
+  </template>
+  <script src="gr-delete-repo.js"></script>
+</dom-module>
diff --git a/gr-delete-repo/gr-delete-repo.js b/gr-delete-repo/gr-delete-repo.js
new file mode 100644
index 0000000..0ce69c4
--- /dev/null
+++ b/gr-delete-repo/gr-delete-repo.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+(function() {
+  'use strict';
+
+  Polymer({
+    is: 'gr-delete-repo',
+
+    properties: {
+      repoName: String,
+      config: Object,
+      action: Object,
+      actionId: String,
+    },
+
+    attached() {
+      this.actionId = this.plugin.getPluginName() + '~delete';
+      this.action = this.config.actions[this.actionId];
+      this.hidden = !this.action;
+    },
+
+    _handleCommandTap() {
+      this.$.deleteRepoOverlay.open();
+    },
+
+    _handleCloseDeleteRepo() {
+      this.$.deleteRepoOverlay.close();
+    },
+
+    _handleDeleteRepo() {
+      const endpoint = '/projects/' +
+          encodeURIComponent(this.repoName) + '/' +
+          this.actionId;
+
+      const json = {
+        force: this.$.forceDeleteOpenChangesCheckBox.checked,
+        preserve: this.$.preserveGitRepoCheckBox.checked
+      };
+
+      const errFn = response => {
+        this.fire('page-error', {response});
+      };
+
+      return this.plugin.restApi().send(
+          this.action.method, endpoint, json, errFn)
+            .then(r => {
+              Gerrit.Nav.navigateToRelativeUrl('/admin/repos');
+      });
+    },
+  });
+})();
diff --git a/plugin.html b/plugin.html
new file mode 100644
index 0000000..138397d
--- /dev/null
+++ b/plugin.html
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<link rel="import" href="./gr-delete-repo/gr-delete-repo.html">
+
+<dom-module id="delete-repo">
+  <script>
+    if (window.Polymer) {
+      Gerrit.install(function(plugin) {
+          plugin.registerCustomComponent(
+              'repo-command', 'gr-delete-repo');
+      });
+    }
+  </script>
+</dom-module>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
index f7124e4..a804b3f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteCommand.java
@@ -14,11 +14,9 @@
 
 package com.googlesource.gerrit.plugins.deleteproject;
 
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.sshd.CommandMetaData;
 import com.google.gerrit.sshd.SshCommand;
 import com.google.gwtorm.server.OrmException;
@@ -31,7 +29,7 @@
 @CommandMetaData(name = "delete", description = "Delete specific project")
 public final class DeleteCommand extends SshCommand {
   @Argument(index = 0, required = true, metaVar = "NAME", usage = "project to delete")
-  private ProjectControl projectControl;
+  private ProjectState projectState;
 
   @Option(name = "--yes-really-delete", usage = "confirmation to delete the project")
   private boolean yesReallyDelete;
@@ -56,7 +54,7 @@
       input.force = force;
       input.preserve = preserveGitRepository;
 
-      ProjectResource rsrc = new ProjectResource(projectControl);
+      ProjectResource rsrc = new ProjectResource(projectState, user);
       deleteProject.assertDeletePermission(rsrc);
       deleteProject.assertCanDelete(rsrc, input);
 
@@ -93,11 +91,7 @@
       }
 
       deleteProject.doDelete(rsrc, input);
-    } catch (AuthException
-        | ResourceNotFoundException
-        | ResourceConflictException
-        | OrmException
-        | IOException e) {
+    } catch (RestApiException | OrmException | IOException e) {
       throw die(e);
     }
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
index 292d8bd..960dc0a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteLog.java
@@ -16,15 +16,15 @@
 
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.MultimapBuilder;
-import com.google.gerrit.audit.AuditEvent;
-import com.google.gerrit.audit.AuditService;
-import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.extensions.systemstatus.ServerInformation;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.OutputFormat;
+import com.google.gerrit.server.audit.AuditEvent;
+import com.google.gerrit.server.audit.AuditService;
 import com.google.gerrit.server.util.PluginLogFile;
 import com.google.gerrit.server.util.SystemLog;
+import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import org.apache.log4j.Level;
@@ -73,7 +73,9 @@
             );
 
     event.setProperty(ACCOUNT_ID, user.getAccountId().toString());
-    event.setProperty(USER_NAME, user.getUserName());
+    if (user.getUserName().isPresent()) {
+      event.setProperty(USER_NAME, user.getUserName().get());
+    }
     event.setProperty(PROJECT_NAME, project.get());
 
     if (options != null) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
index 472198e..79f57ec 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProject.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
@@ -30,6 +31,7 @@
 import com.google.gerrit.server.notedb.NotesMigration;
 import com.google.gerrit.server.permissions.GlobalPermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.ProjectPermission;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
@@ -91,8 +93,7 @@
 
   @Override
   public Object apply(ProjectResource rsrc, Input input)
-      throws ResourceNotFoundException, ResourceConflictException, OrmException, IOException,
-          AuthException {
+      throws OrmException, IOException, RestApiException {
     assertDeletePermission(rsrc);
     assertCanDelete(rsrc, input);
 
@@ -115,17 +116,18 @@
   }
 
   protected boolean canDelete(ProjectResource rsrc) {
-    PermissionBackend.WithUser userPermission = permissionBackend.user(userProvider);
+    PermissionBackend.WithUser userPermission = permissionBackend.currentUser();
+    PermissionBackend.ForProject projectPermission = userPermission.project(rsrc.getNameKey());
     return userPermission.testOrFalse(GlobalPermission.ADMINISTRATE_SERVER)
         || userPermission.testOrFalse(new PluginPermission(pluginName, DELETE_PROJECT))
         || (userPermission.testOrFalse(new PluginPermission(pluginName, DELETE_OWN_PROJECT))
-            && rsrc.getControl().isOwner());
+            && projectPermission.testOrFalse(ProjectPermission.WRITE_CONFIG));
   }
 
   public void assertCanDelete(ProjectResource rsrc, Input input) throws ResourceConflictException {
     try {
       pcHandler.assertCanDelete(rsrc);
-      dbHandler.assertCanDelete(rsrc.getControl().getProject());
+      dbHandler.assertCanDelete(rsrc.getProjectState().getProject());
       fsHandler.assertCanDelete(rsrc, input == null ? false : input.preserve);
     } catch (CannotDeleteProjectException e) {
       throw new ResourceConflictException(e.getMessage());
@@ -133,12 +135,12 @@
   }
 
   public Collection<String> getWarnings(ProjectResource rsrc) throws OrmException {
-    return dbHandler.getWarnings(rsrc.getControl().getProject());
+    return dbHandler.getWarnings(rsrc.getProjectState().getProject());
   }
 
   public void doDelete(ProjectResource rsrc, Input input)
-      throws OrmException, IOException, ResourceNotFoundException, ResourceConflictException {
-    Project project = rsrc.getControl().getProject();
+      throws OrmException, IOException, RestApiException {
+    Project project = rsrc.getProjectState().getProject();
     boolean preserve = input != null && input.preserve;
     Exception ex = null;
     try {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
index 8b60ae3..f529c54 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HideProject.java
@@ -16,18 +16,18 @@
 
 import com.google.gerrit.common.data.AccessSection;
 import com.google.gerrit.extensions.client.ProjectState;
-import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
 import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.CreateProject;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.restapi.project.CreateProject;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
@@ -39,23 +39,22 @@
 
   private final MetaDataUpdate.Server metaDataUpdateFactory;
   private final ProjectCache projectCache;
-  private final CreateProject.Factory createProjectFactory;
+  private final CreateProject createProject;
   private final Configuration cfg;
 
   @Inject
   HideProject(
       MetaDataUpdate.Server metaDataUpdateFactory,
       ProjectCache projectCache,
-      CreateProject.Factory createProjectFactory,
+      CreateProject createProject,
       Configuration cfg) {
     this.metaDataUpdateFactory = metaDataUpdateFactory;
     this.projectCache = projectCache;
-    this.createProjectFactory = createProjectFactory;
+    this.createProject = createProject;
     this.cfg = cfg;
   }
 
-  public void apply(ProjectResource rsrc)
-      throws ResourceNotFoundException, ResourceConflictException, IOException {
+  public void apply(ProjectResource rsrc) throws IOException, RestApiException {
     try {
       MetaDataUpdate md = metaDataUpdateFactory.create(rsrc.getNameKey());
 
@@ -81,16 +80,11 @@
     }
   }
 
-  private void createProjectIfMissing(String projectName)
-      throws ResourceConflictException, IOException {
+  private void createProjectIfMissing(String projectName) throws IOException, RestApiException {
     if (projectCache.get(new Project.NameKey(projectName)) == null) {
       try {
-        createProjectFactory.create(projectName).apply(TopLevelResource.INSTANCE, null);
-      } catch (BadRequestException
-          | UnprocessableEntityException
-          | ResourceNotFoundException
-          | ConfigInvalidException
-          | PermissionBackendException e) {
+        createProject.apply(TopLevelResource.INSTANCE, IdString.fromDecoded(projectName), null);
+      } catch (RestApiException | ConfigInvalidException | PermissionBackendException e) {
         throw new ResourceConflictException(
             String.format("Failed to create project %s", projectName));
       }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HttpModule.java
index a5470c9..f07ef52 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HttpModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/HttpModule.java
@@ -24,5 +24,7 @@
   protected void configureServlets() {
     DynamicSet.bind(binder(), WebUiPlugin.class)
         .toInstance(new JavaScriptPlugin("delete-project.js"));
+    DynamicSet.bind(binder(), WebUiPlugin.class)
+        .toInstance(new JavaScriptPlugin("gr-delete-repo.html"));
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
index bdf3ff5..c453478 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/cache/CacheDeleteHandler.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.inject.Inject;
+import java.io.IOException;
 
 public class CacheDeleteHandler {
 
@@ -27,7 +28,7 @@
     this.projectCache = projectCache;
   }
 
-  public void delete(Project project) {
+  public void delete(Project project) throws IOException {
     projectCache.remove(project);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
index e6d79b6..5db7fe5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/database/DatabaseDeleteHandler.java
@@ -27,20 +27,20 @@
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.reviewdb.server.ReviewDbUtil;
 import com.google.gerrit.server.StarredChangesUtil;
+import com.google.gerrit.server.UserInitiated;
 import com.google.gerrit.server.account.AccountState;
-import com.google.gerrit.server.account.WatchConfig;
-import com.google.gerrit.server.account.WatchConfig.Accessor;
-import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
+import com.google.gerrit.server.account.AccountsUpdate;
+import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
 import com.google.gerrit.server.change.AccountPatchReviewStore;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.MergeOpRepoManager;
-import com.google.gerrit.server.git.SubmoduleException;
-import com.google.gerrit.server.git.SubmoduleOp;
 import com.google.gerrit.server.index.change.ChangeIndexer;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
+import com.google.gerrit.server.submit.MergeOpRepoManager;
+import com.google.gerrit.server.submit.SubmoduleException;
+import com.google.gerrit.server.submit.SubmoduleOp;
 import com.google.gwtorm.jdbc.JdbcSchema;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.ResultSet;
@@ -76,7 +76,7 @@
   private final DynamicItem<AccountPatchReviewStore> accountPatchReviewStore;
   private final ChangeIndexer indexer;
   private final Provider<InternalAccountQuery> accountQueryProvider;
-  private final Provider<Accessor> watchConfig;
+  private final Provider<AccountsUpdate> accountsUpdateProvider;
 
   @Inject
   public DatabaseDeleteHandler(
@@ -89,9 +89,7 @@
       DynamicItem<AccountPatchReviewStore> accountPatchReviewStore,
       ChangeIndexer indexer,
       Provider<InternalAccountQuery> accountQueryProvider,
-      Provider<WatchConfig.Accessor> watchConfig) {
-    this.accountQueryProvider = accountQueryProvider;
-    this.watchConfig = watchConfig;
+      @UserInitiated Provider<AccountsUpdate> accountsUpdateProvider) {
     this.dbProvider = dbProvider;
     this.queryProvider = queryProvider;
     this.repoManager = repoManager;
@@ -100,6 +98,8 @@
     this.starredChangesUtil = starredChangesUtil;
     this.accountPatchReviewStore = accountPatchReviewStore;
     this.indexer = indexer;
+    this.accountQueryProvider = accountQueryProvider;
+    this.accountsUpdateProvider = accountsUpdateProvider;
   }
 
   public Collection<String> getWarnings(Project project) throws OrmException {
@@ -194,7 +194,7 @@
     try (Repository repo = repoManager.openRepository(proj);
         MergeOpRepoManager orm = ormProvider.get()) {
       Set<Branch.NameKey> branches = new HashSet<>();
-      for (Ref ref : repo.getRefDatabase().getRefs(RefNames.REFS_HEADS).values()) {
+      for (Ref ref : repo.getRefDatabase().getRefsByPrefix(RefNames.REFS_HEADS)) {
         branches.add(new Branch.NameKey(proj, ref.getName()));
       }
       SubmoduleOp sub = subOpFactory.create(branches, orm);
@@ -223,7 +223,12 @@
       for (ProjectWatchKey watchKey : a.getProjectWatches().keySet()) {
         if (project.getNameKey().equals(watchKey.project())) {
           try {
-            watchConfig.get().deleteProjectWatches(accountId, singleton(watchKey));
+            accountsUpdateProvider
+                .get()
+                .update(
+                    "Delete Project Watches via API",
+                    accountId,
+                    u -> u.deleteProjectWatches(singleton(watchKey)));
           } catch (IOException | ConfigInvalidException e) {
             log.error(
                 "Removing watch entry for user {} in project {} failed.",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java
index 31fafea..abba619 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/fs/FilesystemDeleteHandler.java
@@ -77,7 +77,7 @@
 
   private void assertHasNoTags(ProjectResource rsrc) throws CannotDeleteProjectException {
     try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) {
-      if (!repo.getRefDatabase().getRefs(Constants.R_TAGS).isEmpty()) {
+      if (!repo.getRefDatabase().getRefsByPrefix(Constants.R_TAGS).isEmpty()) {
         throw new CannotDeleteProjectException(
             String.format("Project %s has tags", rsrc.getName()));
       }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
index 9906c6c..31ee0e8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/projectconfig/ProjectConfigDeleteHandler.java
@@ -17,9 +17,10 @@
 import static java.util.stream.Collectors.joining;
 
 import com.google.gerrit.extensions.common.ProjectInfo;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.server.project.ListChildProjects;
 import com.google.gerrit.server.project.ProjectResource;
+import com.google.gerrit.server.restapi.project.ListChildProjects;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.googlesource.gerrit.plugins.deleteproject.CannotDeleteProjectException;
@@ -38,12 +39,14 @@
     this.listChildProjectsProvider = listChildProjectsProvider;
   }
 
-  public void assertCanDelete(ProjectResource rsrc) throws CannotDeleteProjectException {
+  public void assertCanDelete(ProjectResource rsrc)
+      throws CannotDeleteProjectException, ResourceConflictException {
     protectedProjects.assertIsNotProtected(rsrc);
     assertHasNoChildProjects(rsrc);
   }
 
-  private void assertHasNoChildProjects(ProjectResource rsrc) throws CannotDeleteProjectException {
+  private void assertHasNoChildProjects(ProjectResource rsrc)
+      throws CannotDeleteProjectException, ResourceConflictException {
     try {
       List<ProjectInfo> children = listChildProjectsProvider.get().apply(rsrc);
       if (!children.isEmpty()) {
diff --git a/src/main/resources/static/delete-project.js b/src/main/resources/static/delete-project.js
index 2200973..2291279 100644
--- a/src/main/resources/static/delete-project.js
+++ b/src/main/resources/static/delete-project.js
@@ -12,32 +12,34 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-Gerrit.install(function(self) {
-    function onDeleteProject(c) {
-      var f = c.checkbox();
-      var p = c.checkbox();
-      var b = c.button('Delete',
-        {onclick: function(){
-          c.call(
-            {force: f.checked, preserve: p.checked},
-            function(r) {
-              c.hide();
-              window.alert('The project: "'
-                + c.project
-                + '" was deleted.'),
-              Gerrit.go('/admin/projects/');
-            });
-        }});
-      c.popup(c.div(
-        c.msg('Are you really sure you want to delete the project: "'
-          + c.project
-          + '"?'),
-        c.br(),
-        c.label(f, 'Delete project even if open changes exist?'),
-        c.br(),
-        c.label(p, 'Preserve GIT Repository?'),
-        c.br(),
-        b));
-    }
-    self.onAction('project', 'delete', onDeleteProject);
-  });
+if (!window.Polymer) {
+  Gerrit.install(function(self) {
+      function onDeleteProject(c) {
+        var f = c.checkbox();
+        var p = c.checkbox();
+        var b = c.button('Delete',
+          {onclick: function(){
+            c.call(
+              {force: f.checked, preserve: p.checked},
+              function(r) {
+                c.hide();
+                window.alert('The project: "'
+                  + c.project
+                  + '" was deleted.'),
+                Gerrit.go('/admin/projects/');
+              });
+          }});
+        c.popup(c.div(
+          c.msg('Are you really sure you want to delete the project: "'
+            + c.project
+            + '"?'),
+          c.br(),
+          c.label(f, 'Delete project even if open changes exist?'),
+          c.br(),
+          c.label(p, 'Preserve GIT Repository?'),
+          c.br(),
+          b));
+      }
+      self.onAction('project', 'delete', onDeleteProject);
+    });
+}
diff --git a/tools/bzl/genrule2.bzl b/tools/bzl/genrule2.bzl
new file mode 100644
index 0000000..de66f32
--- /dev/null
+++ b/tools/bzl/genrule2.bzl
@@ -0,0 +1 @@
+load("@com_googlesource_gerrit_bazlets//tools:genrule2.bzl", "genrule2")
diff --git a/tools/bzl/js.bzl b/tools/bzl/js.bzl
new file mode 100644
index 0000000..0eba184
--- /dev/null
+++ b/tools/bzl/js.bzl
@@ -0,0 +1 @@
+load("@com_googlesource_gerrit_bazlets//tools:js.bzl", "polygerrit_plugin")