Merge "Clearer wording for force option in push permissions"
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
index febd446..5d45811 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.html
@@ -111,13 +111,13 @@
         </a>
         <gr-select
             id="force"
-            class$="[[_computeForceClass(permission)]]"
+            class$="[[_computeForceClass(permission, rule.value.action)]]"
             bind-value="{{rule.value.force}}"
             on-change="_handleValueChange">
           <select disabled$="[[!editing]]">
             <template
                 is="dom-repeat"
-                items="[[_computeForceOptions(permission)]]">
+                items="[[_computeForceOptions(permission, rule.value.action)]]">
               <option value="[[item.value]]">[[item.name]]</option>
             </template>
           </select>
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
index 4af4952..1893536 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.js
@@ -33,22 +33,24 @@
     'INTERACTIVE',
   ];
 
-  const DROPDOWN_OPTIONS = [
-    'ALLOW',
-    'DENY',
-    'BLOCK',
-  ];
+  const Action = {
+    ALLOW: 'ALLOW',
+    DENY: 'DENY',
+    BLOCK: 'BLOCK',
+  };
 
-  const FORCE_PUSH_OPTIONS = [
-    {
-      name: 'Block all pushes, block force push only',
-      value: false,
-    },
-    {
-      name: 'Allow fast-forward only push, allow all pushes',
-      value: true,
-    },
-  ];
+  const DROPDOWN_OPTIONS = [Action.ALLOW, Action.DENY, Action.BLOCK];
+
+  const ForcePushOptions = {
+    ALLOW: [
+      {name: 'Allow pushing but not force pushing', value: false},
+      {name: 'Allow pushing with or without force', value: true},
+    ],
+    BLOCK: [
+      {name: 'Block pushing with or without force', value: false},
+      {name: 'Block force pushing', value: true},
+    ],
+  };
 
   const FORCE_EDIT_OPTIONS = [
     {
@@ -117,13 +119,17 @@
       this._setOriginalRuleValues(rule.value);
     },
 
-    _computeForce(permission) {
-      return this.permissionValues.push.id === permission ||
-          this.permissionValues.editTopicName.id === permission;
+    _computeForce(permission, action) {
+      if (this.permissionValues.push.id === permission &&
+          action !== Action.DENY) {
+        return true;
+      }
+
+      return this.permissionValues.editTopicName.id === permission;
     },
 
-    _computeForceClass(permission) {
-      return this._computeForce(permission) ? 'force' : '';
+    _computeForceClass(permission, action) {
+      return this._computeForce(permission, action) ? 'force' : '';
     },
 
     _computeGroupPath(group) {
@@ -156,9 +162,15 @@
       return classList.join(' ');
     },
 
-    _computeForceOptions(permission) {
+    _computeForceOptions(permission, action) {
       if (permission === this.permissionValues.push.id) {
-        return FORCE_PUSH_OPTIONS;
+        if (action === Action.ALLOW) {
+          return ForcePushOptions.ALLOW;
+        } else if (action === Action.BLOCK) {
+          return ForcePushOptions.BLOCK;
+        } else {
+          return [];
+        }
       } else if (permission === this.permissionValues.editTopicName.id) {
         return FORCE_EDIT_OPTIONS;
       }
@@ -166,6 +178,7 @@
     },
 
     _getDefaultRuleValues(permission, label) {
+      const ruleAction = Action.ALLOW;
       const value = {};
       if (permission === 'priority') {
         value.action = PRIORITY_OPTIONS[0];
@@ -173,16 +186,17 @@
       } else if (label) {
         value.min = label.values[0].value;
         value.max = label.values[label.values.length - 1].value;
-      } else if (this._computeForce(permission)) {
-        value.force = this._computeForceOptions(permission)[0].value;
+      } else if (this._computeForce(permission, ruleAction)) {
+        value.force =
+            this._computeForceOptions(permission, ruleAction)[0].value;
       }
       value.action = DROPDOWN_OPTIONS[0];
       return value;
     },
 
     _setDefaultRuleValues() {
-      this.set('rule.value',
-          this._getDefaultRuleValues(this.permission, this.label));
+      this.set('rule.value', this._getDefaultRuleValues(this.permission,
+          this.label));
     },
 
     _computeOptions(permission) {
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
index 5b6f947..556568b 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor_test.html
@@ -50,16 +50,16 @@
     suite('unit tests', () => {
       test('_computeForce, _computeForceClass, and _computeForceOptions',
           () => {
-            const FORCE_PUSH_OPTIONS = [
-              {
-                name: 'Block all pushes, block force push only',
-                value: false,
-              },
-              {
-                name: 'Allow fast-forward only push, allow all pushes',
-                value: true,
-              },
-            ];
+            const ForcePushOptions = {
+              ALLOW: [
+                {name: 'Allow pushing but not force pushing', value: false},
+                {name: 'Allow pushing with or without force', value: true},
+              ],
+              BLOCK: [
+                {name: 'Block pushing with or without force', value: false},
+                {name: 'Block force pushing', value: true},
+              ],
+            };
 
             const FORCE_EDIT_OPTIONS = [
               {
@@ -72,10 +72,26 @@
               },
             ];
             let permission = 'push';
-            assert.isTrue(element._computeForce(permission));
-            assert.equal(element._computeForceClass(permission), 'force');
-            assert.deepEqual(element._computeForceOptions(permission),
-                FORCE_PUSH_OPTIONS);
+            let action = 'ALLOW';
+            assert.isTrue(element._computeForce(permission, action));
+            assert.equal(element._computeForceClass(permission, action),
+                'force');
+            assert.deepEqual(element._computeForceOptions(permission, action),
+                ForcePushOptions.ALLOW);
+
+            action = 'BLOCK';
+            assert.isTrue(element._computeForce(permission, action));
+            assert.equal(element._computeForceClass(permission, action),
+                'force');
+            assert.deepEqual(element._computeForceOptions(permission, action),
+                ForcePushOptions.BLOCK);
+
+            action = 'DENY';
+            assert.isFalse(element._computeForce(permission, action));
+            assert.equal(element._computeForceClass(permission, action), '');
+            assert.equal(
+                element._computeForceOptions(permission, action).length, 0);
+
             permission = 'editTopicName';
             assert.isTrue(element._computeForce(permission));
             assert.equal(element._computeForceClass(permission), 'force');