Merge "Make project state check in SUBMIT explicit"
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 5ee9017..6ca2266 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -1556,6 +1556,10 @@
         reject(cmd, e.getMessage());
         return;
       }
+      if (!projectState.statePermitsWrite()) {
+        reject(cmd, "project state does not permit write");
+        return;
+      }
     }
 
     RevWalk walk = rp.getRevWalk();
diff --git a/java/com/google/gerrit/server/project/RefControl.java b/java/com/google/gerrit/server/project/RefControl.java
index 552336a..c65eb10 100644
--- a/java/com/google/gerrit/server/project/RefControl.java
+++ b/java/com/google/gerrit/server/project/RefControl.java
@@ -129,7 +129,7 @@
       // granting of powers beyond submitting to the configuration.
       return projectControl.isOwner();
     }
-    return canPerform(Permission.SUBMIT, isChangeOwner) && isProjectStatePermittingWrite();
+    return canPerform(Permission.SUBMIT, isChangeOwner);
   }
 
   /** @return true if this user can abandon a change for this ref */
diff --git a/java/com/google/gerrit/server/restapi/change/Submit.java b/java/com/google/gerrit/server/restapi/change/Submit.java
index 04aafff..264a0fb 100644
--- a/java/com/google/gerrit/server/restapi/change/Submit.java
+++ b/java/com/google/gerrit/server/restapi/change/Submit.java
@@ -57,6 +57,7 @@
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gerrit.server.query.change.InternalChangeQuery;
 import com.google.gerrit.server.restapi.account.AccountsCollection;
@@ -132,6 +133,7 @@
   private final boolean submitWholeTopic;
   private final Provider<InternalChangeQuery> queryProvider;
   private final PatchSetUtil psUtil;
+  private final ProjectCache projectCache;
 
   @Inject
   Submit(
@@ -146,7 +148,8 @@
       AccountsCollection accounts,
       @GerritServerConfig Config cfg,
       Provider<InternalChangeQuery> queryProvider,
-      PatchSetUtil psUtil) {
+      PatchSetUtil psUtil,
+      ProjectCache projectCache) {
     this.dbProvider = dbProvider;
     this.repoManager = repoManager;
     this.permissionBackend = permissionBackend;
@@ -183,6 +186,7 @@
                 cfg.getString("change", null, "submitTopicTooltip"), DEFAULT_TOPIC_TOOLTIP));
     this.queryProvider = queryProvider;
     this.psUtil = psUtil;
+    this.projectCache = projectCache;
   }
 
   @Override
@@ -197,6 +201,7 @@
       rsrc.permissions().check(ChangePermission.SUBMIT);
       submitter = rsrc.getUser().asIdentifiedUser();
     }
+    projectCache.checkedGet(rsrc.getProject()).checkStatePermitsWrite();
 
     return new Output(mergeChange(rsrc, submitter, input));
   }
@@ -303,6 +308,15 @@
       return null; // submit not visible
     }
 
+    try {
+      if (!projectCache.checkedGet(resource.getProject()).statePermitsWrite()) {
+        return null; // submit not visible
+      }
+    } catch (IOException e) {
+      log.error("Error checking if change is submittable", e);
+      throw new OrmRuntimeException("Could not determine problems for the change", e);
+    }
+
     ReviewDb db = dbProvider.get();
     ChangeData cd = changeDataFactory.create(db, resource.getNotes());
     try {