Merge "Make project state check in DELETE explicit"
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 74bf116..5ee9017 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -1120,7 +1120,7 @@
   private boolean canDelete(ReceiveCommand cmd) throws PermissionBackendException {
     try {
       permissions.ref(cmd.getRefName()).check(RefPermission.DELETE);
-      return true;
+      return projectState.statePermitsWrite();
     } catch (AuthException e) {
       return false;
     }
diff --git a/java/com/google/gerrit/server/project/RefControl.java b/java/com/google/gerrit/server/project/RefControl.java
index 329b3a9..552336a 100644
--- a/java/com/google/gerrit/server/project/RefControl.java
+++ b/java/com/google/gerrit/server/project/RefControl.java
@@ -272,7 +272,7 @@
    * @return {@code true} if the user specified can delete a Git ref.
    */
   private boolean canDelete() {
-    if (!isProjectStatePermittingWrite() || (RefNames.REFS_CONFIG.equals(refName))) {
+    if (RefNames.REFS_CONFIG.equals(refName)) {
       // Never allow removal of the refs/meta/config branch.
       // Deleting the branch would destroy all Gerrit specific
       // metadata about the project, including its access rules.
diff --git a/java/com/google/gerrit/server/restapi/project/CreateBranch.java b/java/com/google/gerrit/server/restapi/project/CreateBranch.java
index 0b62c15..38bc982 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateBranch.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateBranch.java
@@ -183,6 +183,7 @@
         info.revision = revid.getName();
         info.canDelete =
             permissionBackend.user(identifiedUser).ref(name).testOrFalse(RefPermission.DELETE)
+                    && rsrc.getProjectState().statePermitsWrite()
                 ? true
                 : null;
         return info;
diff --git a/java/com/google/gerrit/server/restapi/project/CreateTag.java b/java/com/google/gerrit/server/restapi/project/CreateTag.java
index ca51b44..f501faf 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateTag.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateTag.java
@@ -147,7 +147,7 @@
             result.getObjectId(),
             identifiedUser.get().getAccount());
         try (RevWalk w = new RevWalk(repo)) {
-          return ListTags.createTagInfo(perm, result, w, resource.getNameKey(), links);
+          return ListTags.createTagInfo(perm, result, w, resource.getProjectState(), links);
         }
       }
     } catch (InvalidRevisionException e) {
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteBranch.java b/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
index 09bbca9..3114f8a 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteBranch.java
@@ -57,6 +57,7 @@
   public Response<?> apply(BranchResource rsrc, Input input)
       throws RestApiException, OrmException, IOException, PermissionBackendException {
     permissionBackend.user(user).ref(rsrc.getBranchKey()).check(RefPermission.DELETE);
+    rsrc.getProjectState().checkStatePermitsWrite();
 
     if (!queryProvider.get().setLimit(1).byBranchOpen(rsrc.getBranchKey()).isEmpty()) {
       throw new ResourceConflictException("branch " + rsrc.getBranchKey() + " has open changes");
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteRef.java b/java/com/google/gerrit/server/restapi/project/DeleteRef.java
index b1b575b..7bd1c4a 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteRef.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteRef.java
@@ -235,6 +235,10 @@
           "it doesn't exist or you do not have permission to delete it");
     }
 
+    if (!project.getProjectState().statePermitsWrite()) {
+      command.setResult(Result.REJECTED_OTHER_REASON, "project state does not permit write");
+    }
+
     if (!refName.startsWith(R_TAGS)) {
       Branch.NameKey branchKey = new Branch.NameKey(project.getNameKey(), ref.getName());
       if (!queryProvider.get().setLimit(1).byBranchOpen(branchKey).isEmpty()) {
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteTag.java b/java/com/google/gerrit/server/restapi/project/DeleteTag.java
index cce7103..f432129 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteTag.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteTag.java
@@ -56,6 +56,7 @@
         .project(resource.getNameKey())
         .ref(tag)
         .check(RefPermission.DELETE);
+    resource.getProjectState().checkStatePermitsWrite();
     deleteRefFactory.create(resource).ref(tag).delete();
     return Response.none();
   }
diff --git a/java/com/google/gerrit/server/restapi/project/ListBranches.java b/java/com/google/gerrit/server/restapi/project/ListBranches.java
index 5675be1..416a5c2 100644
--- a/java/com/google/gerrit/server/restapi/project/ListBranches.java
+++ b/java/com/google/gerrit/server/restapi/project/ListBranches.java
@@ -204,7 +204,11 @@
         branches.add(b);
 
         if (!Constants.HEAD.equals(ref.getName())) {
-          b.canDelete = perm.ref(ref.getName()).testOrFalse(RefPermission.DELETE) ? true : null;
+          b.canDelete =
+              perm.ref(ref.getName()).testOrFalse(RefPermission.DELETE)
+                      && rsrc.getProjectState().statePermitsWrite()
+                  ? true
+                  : null;
         }
         continue;
       }
@@ -248,7 +252,11 @@
     info.ref = ref.getName();
     info.revision = ref.getObjectId() != null ? ref.getObjectId().name() : null;
     info.canDelete =
-        !targets.contains(ref.getName()) && perm.testOrFalse(RefPermission.DELETE) ? true : null;
+        !targets.contains(ref.getName())
+                && perm.testOrFalse(RefPermission.DELETE)
+                && projectState.statePermitsWrite()
+            ? true
+            : null;
 
     BranchResource rsrc = new BranchResource(projectState, user, ref);
     for (UiAction.Description d : uiActions.from(branchViews, rsrc)) {
diff --git a/java/com/google/gerrit/server/restapi/project/ListTags.java b/java/com/google/gerrit/server/restapi/project/ListTags.java
index a2b7082..af4586c 100644
--- a/java/com/google/gerrit/server/restapi/project/ListTags.java
+++ b/java/com/google/gerrit/server/restapi/project/ListTags.java
@@ -140,7 +140,8 @@
           visibleTags(
               resource.getProjectState(), repo, repo.getRefDatabase().getRefs(Constants.R_TAGS));
       for (Ref ref : all.values()) {
-        tags.add(createTagInfo(perm.ref(ref.getName()), ref, rw, resource.getNameKey(), links));
+        tags.add(
+            createTagInfo(perm.ref(ref.getName()), ref, rw, resource.getProjectState(), links));
       }
     }
 
@@ -180,7 +181,7 @@
                 .ref(ref.getName()),
             ref,
             rw,
-            resource.getNameKey(),
+            resource.getProjectState(),
             links);
       }
     }
@@ -188,15 +189,12 @@
   }
 
   public static TagInfo createTagInfo(
-      PermissionBackend.ForRef perm,
-      Ref ref,
-      RevWalk rw,
-      Project.NameKey projectName,
-      WebLinks links)
+      PermissionBackend.ForRef perm, Ref ref, RevWalk rw, ProjectState projectState, WebLinks links)
       throws MissingObjectException, IOException {
     RevObject object = rw.parseAny(ref.getObjectId());
-    Boolean canDelete = perm.testOrFalse(RefPermission.DELETE) ? true : null;
-    List<WebLinkInfo> webLinks = links.getTagLinks(projectName.get(), ref.getName());
+    Boolean canDelete =
+        perm.testOrFalse(RefPermission.DELETE) && projectState.statePermitsWrite() ? true : null;
+    List<WebLinkInfo> webLinks = links.getTagLinks(projectState.getName(), ref.getName());
     if (object instanceof RevTag) {
       // Annotated or signed tag
       RevTag tag = (RevTag) object;