"Submit on Push" option on Submit Perm.
Add "Submit on Push" option to the Submit Permission and remove the "refs/for/"-way of allowing this. This change introduces a "Submit on Push" option for the Submit permission, which will enable the %submit push parameter. Any "submit refs/for/*" permission will be automatially migrated when the config is loaded. Change-Id: I6106ecf289bef541fa273d3deebead7a3a9710ac
This commit is contained in:
@@ -795,8 +795,7 @@ above) must enable submit, and also must not block it. See above for
|
|||||||
details on each label.
|
details on each label.
|
||||||
|
|
||||||
To link:user-upload.html#auto_merge[immediately submit a change on push]
|
To link:user-upload.html#auto_merge[immediately submit a change on push]
|
||||||
the caller needs to have the Submit permission on `refs/for/<ref>`
|
the caller needs to enable the "Submit on Push" option.
|
||||||
(e.g. on `refs/for/refs/heads/master`).
|
|
||||||
|
|
||||||
Submitting to the `refs/meta/config` branch is only allowed to project
|
Submitting to the `refs/meta/config` branch is only allowed to project
|
||||||
owners. Any explicit submit permissions for non-project-owners on this
|
owners. Any explicit submit permissions for non-project-owners on this
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ limitations under the License.
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 36px;
|
right: 36px;
|
||||||
width: 7em;
|
width: 9em;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package com.google.gerrit.client.admin;
|
|||||||
|
|
||||||
import static com.google.gerrit.common.data.Permission.EDIT_TOPIC_NAME;
|
import static com.google.gerrit.common.data.Permission.EDIT_TOPIC_NAME;
|
||||||
import static com.google.gerrit.common.data.Permission.PUSH;
|
import static com.google.gerrit.common.data.Permission.PUSH;
|
||||||
|
import static com.google.gerrit.common.data.Permission.SUBMIT;
|
||||||
|
|
||||||
import com.google.gerrit.client.Dispatcher;
|
import com.google.gerrit.client.Dispatcher;
|
||||||
import com.google.gerrit.client.Gerrit;
|
import com.google.gerrit.client.Gerrit;
|
||||||
@@ -139,15 +140,23 @@ public class PermissionRuleEditor extends Composite
|
|||||||
initWidget(uiBinder.createAndBindUi(this));
|
initWidget(uiBinder.createAndBindUi(this));
|
||||||
|
|
||||||
String name = permission.getName();
|
String name = permission.getName();
|
||||||
boolean canForce = PUSH.equals(name);
|
boolean canForce = true;
|
||||||
if (canForce) {
|
switch (name) {
|
||||||
String ref = section.getName();
|
case SUBMIT:
|
||||||
canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
|
force.setText(PermissionRule.FORCE_SUBMIT);
|
||||||
force.setText(PermissionRule.FORCE_PUSH);
|
break;
|
||||||
} else {
|
case EDIT_TOPIC_NAME:
|
||||||
canForce = EDIT_TOPIC_NAME.equals(name);
|
force.setText(PermissionRule.FORCE_EDIT);
|
||||||
force.setText(PermissionRule.FORCE_EDIT);
|
break;
|
||||||
|
case PUSH:
|
||||||
|
force.setText(PermissionRule.FORCE_PUSH);
|
||||||
|
String ref = section.getName();
|
||||||
|
canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
canForce = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
force.setVisible(canForce);
|
force.setVisible(canForce);
|
||||||
force.setEnabled(!readOnly);
|
force.setEnabled(!readOnly);
|
||||||
action.getElement().setPropertyBoolean("disabled", readOnly);
|
action.getElement().setPropertyBoolean("disabled", readOnly);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ limitations under the License.
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 36px;
|
right: 36px;
|
||||||
width: 7em;
|
width: 9em;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.common.data;
|
package com.google.gerrit.common.data;
|
||||||
|
|
||||||
public class PermissionRule implements Comparable<PermissionRule> {
|
public class PermissionRule implements Comparable<PermissionRule> {
|
||||||
|
public static final String FORCE_SUBMIT = "Submit on Push";
|
||||||
public static final String FORCE_PUSH = "Force Push";
|
public static final String FORCE_PUSH = "Force Push";
|
||||||
public static final String FORCE_EDIT = "Force Edit";
|
public static final String FORCE_EDIT = "Force Edit";
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class ChangeControl {
|
|||||||
|
|
||||||
/** Can this user rebase this change? */
|
/** Can this user rebase this change? */
|
||||||
private boolean canRebase(ReviewDb db) throws OrmException {
|
private boolean canRebase(ReviewDb db) throws OrmException {
|
||||||
return (isOwner() || refControl.canSubmit(isOwner()) || refControl.canRebase())
|
return (isOwner() || refControl.canSubmit(isOwner(), false) || refControl.canRebase())
|
||||||
&& refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE)
|
&& refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE)
|
||||||
&& !isPatchSetLocked(db);
|
&& !isPatchSetLocked(db);
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ class ChangeControl {
|
|||||||
case RESTORE:
|
case RESTORE:
|
||||||
return canRestore(db());
|
return canRestore(db());
|
||||||
case SUBMIT:
|
case SUBMIT:
|
||||||
return refControl.canSubmit(isOwner());
|
return refControl.canSubmit(isOwner(), false);
|
||||||
|
|
||||||
case REMOVE_REVIEWER:
|
case REMOVE_REVIEWER:
|
||||||
case SUBMIT_AS:
|
case SUBMIT_AS:
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class RefControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if this user can submit patch sets to this ref */
|
/** @return true if this user can submit patch sets to this ref */
|
||||||
boolean canSubmit(boolean isChangeOwner) {
|
boolean canSubmit(boolean isChangeOwner, boolean force) {
|
||||||
if (RefNames.REFS_CONFIG.equals(refName)) {
|
if (RefNames.REFS_CONFIG.equals(refName)) {
|
||||||
// Always allow project owners to submit configuration changes.
|
// Always allow project owners to submit configuration changes.
|
||||||
// Submitting configuration changes modifies the access control
|
// Submitting configuration changes modifies the access control
|
||||||
@@ -117,7 +117,7 @@ class RefControl {
|
|||||||
// granting of powers beyond submitting to the configuration.
|
// granting of powers beyond submitting to the configuration.
|
||||||
return projectControl.isOwner();
|
return projectControl.isOwner();
|
||||||
}
|
}
|
||||||
return canPerform(Permission.SUBMIT, isChangeOwner, false);
|
return canPerform(Permission.SUBMIT, isChangeOwner, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if this user can force edit topic names. */
|
/** @return true if this user can force edit topic names. */
|
||||||
@@ -494,7 +494,7 @@ class RefControl {
|
|||||||
return canPerform(refPermissionName(perm));
|
return canPerform(refPermissionName(perm));
|
||||||
|
|
||||||
case UPDATE_BY_SUBMIT:
|
case UPDATE_BY_SUBMIT:
|
||||||
return projectControl.controlForRef(MagicBranch.NEW_CHANGE + refName).canSubmit(true);
|
return canSubmit(true, true);
|
||||||
|
|
||||||
case READ_PRIVATE_CHANGES:
|
case READ_PRIVATE_CHANGES:
|
||||||
return canPerform(Permission.VIEW_PRIVATE_CHANGES);
|
return canPerform(Permission.VIEW_PRIVATE_CHANGES);
|
||||||
|
|||||||
@@ -756,6 +756,23 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
convertedPerm.addAll(perm.getRules());
|
convertedPerm.addAll(perm.getRules());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (isRefsForExclusively(refName) && perm.getName().equals(Permission.SUBMIT)) {
|
||||||
|
// We only migrate "Submit" if is exclusively added to refs/for/.
|
||||||
|
// We do this because when the new "Submit on Push" force
|
||||||
|
// option is added, it is somewhat likely that people will start specify
|
||||||
|
// Submit on refs/* (something which previously had to be avoided if the
|
||||||
|
// user did not want to enable "Submit on push").
|
||||||
|
// Also, before this change, the documentation mentioned
|
||||||
|
// explicitly that "refs/for/*" will enable "Submit on push".
|
||||||
|
AccessSection migratedAs = getAccessSection(unRefsFor(refName), true);
|
||||||
|
Permission migratedPerm = migratedAs.getPermission(Permission.SUBMIT, true);
|
||||||
|
migratedPerm.setExclusiveGroup(perm.getExclusiveGroup());
|
||||||
|
for (PermissionRule rule : perm.getRules()) {
|
||||||
|
PermissionRule migratedRule = migratedPerm.getRule(rule.getGroup(), true);
|
||||||
|
migratedRule.setForce(true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,11 +129,11 @@ public class RefControlTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertCanSubmit(String ref, ProjectControl u) {
|
private void assertCanSubmit(String ref, ProjectControl u) {
|
||||||
assertThat(u.controlForRef(ref).canSubmit(false)).named("can submit " + ref).isTrue();
|
assertThat(u.controlForRef(ref).canSubmit(false, false)).named("can submit " + ref).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCannotSubmit(String ref, ProjectControl u) {
|
private void assertCannotSubmit(String ref, ProjectControl u) {
|
||||||
assertThat(u.controlForRef(ref).canSubmit(false)).named("can submit " + ref).isFalse();
|
assertThat(u.controlForRef(ref).canSubmit(false, false)).named("can submit " + ref).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCanUpload(ProjectControl u) {
|
private void assertCanUpload(ProjectControl u) {
|
||||||
|
|||||||
@@ -614,6 +614,64 @@ public class ProjectConfigTest extends GerritBaseTests {
|
|||||||
.isEqualTo(Lists.newArrayList(new PermissionRule(developers)));
|
.isEqualTo(Lists.newArrayList(new PermissionRule(developers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readConfigSubmitRefsForStarIsMigrated() throws Exception {
|
||||||
|
RevCommit rev =
|
||||||
|
tr.commit()
|
||||||
|
.add("groups", group(developers))
|
||||||
|
.add("project.config", "[access \"refs/for/*\"]\n" + " submit = group Developers\n")
|
||||||
|
.create();
|
||||||
|
|
||||||
|
ProjectConfig cfg = read(rev);
|
||||||
|
AccessSection as = cfg.getAccessSection("refs/for/*");
|
||||||
|
assertThat(as).isNull();
|
||||||
|
|
||||||
|
as = cfg.getAccessSection("refs/*");
|
||||||
|
assertThat(as.getPermission(Permission.SUBMIT, false)).isNotNull();
|
||||||
|
PermissionRule rule = new PermissionRule(developers);
|
||||||
|
rule.setForce(true);
|
||||||
|
assertThat(as.getPermission(Permission.SUBMIT, false).getRules())
|
||||||
|
.isEqualTo(Lists.newArrayList(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readConfigSubmitRefsStarIsNotMigrated() throws Exception {
|
||||||
|
RevCommit rev =
|
||||||
|
tr.commit()
|
||||||
|
.add("groups", group(developers))
|
||||||
|
.add("project.config", "[access \"refs/*\"]\n" + " submit = group Developers\n")
|
||||||
|
.create();
|
||||||
|
|
||||||
|
ProjectConfig cfg = read(rev);
|
||||||
|
AccessSection as = cfg.getAccessSection("refs/*");
|
||||||
|
assertThat(as).isNotNull();
|
||||||
|
PermissionRule rule = new PermissionRule(developers);
|
||||||
|
assertThat(as.getPermission(Permission.SUBMIT, false).getRules())
|
||||||
|
.isEqualTo(Lists.newArrayList(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readConfigSubmitRefsForStarIsMigratedIntoExistingPermission() throws Exception {
|
||||||
|
RevCommit rev =
|
||||||
|
tr.commit()
|
||||||
|
.add("groups", group(developers))
|
||||||
|
.add(
|
||||||
|
"project.config",
|
||||||
|
"[access \"refs/*\"]\n"
|
||||||
|
+ " submit = group Developers\n"
|
||||||
|
+ "[access \"refs/for/*\"]\n"
|
||||||
|
+ " submit = group Developers\n")
|
||||||
|
.create();
|
||||||
|
|
||||||
|
ProjectConfig cfg = read(rev);
|
||||||
|
AccessSection as = cfg.getAccessSection("refs/*");
|
||||||
|
assertThat(as).isNotNull();
|
||||||
|
PermissionRule rule = new PermissionRule(developers);
|
||||||
|
rule.setForce(true);
|
||||||
|
assertThat(as.getPermission(Permission.SUBMIT, false).getRules())
|
||||||
|
.isEqualTo(Lists.newArrayList(rule));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void readCommentLinkMatchButNoHtmlOrLink() throws Exception {
|
public void readCommentLinkMatchButNoHtmlOrLink() throws Exception {
|
||||||
RevCommit rev =
|
RevCommit rev =
|
||||||
|
|||||||
@@ -56,6 +56,17 @@
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const FORCE_SUBMIT_OPTIONS = [
|
||||||
|
{
|
||||||
|
name: 'No Submit on Push',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Submit on Push',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'gr-rule-editor',
|
is: 'gr-rule-editor',
|
||||||
|
|
||||||
@@ -114,7 +125,8 @@
|
|||||||
|
|
||||||
_computeForce(permission) {
|
_computeForce(permission) {
|
||||||
return this.permissionValues.push.id === permission ||
|
return this.permissionValues.push.id === permission ||
|
||||||
this.permissionValues.editTopicName.id === permission;
|
this.permissionValues.editTopicName.id === permission ||
|
||||||
|
this.permissionValues.submit.id === permission;
|
||||||
},
|
},
|
||||||
|
|
||||||
_computeForceClass(permission) {
|
_computeForceClass(permission) {
|
||||||
@@ -156,6 +168,8 @@
|
|||||||
return FORCE_PUSH_OPTIONS;
|
return FORCE_PUSH_OPTIONS;
|
||||||
} else if (permission === this.permissionValues.editTopicName.id) {
|
} else if (permission === this.permissionValues.editTopicName.id) {
|
||||||
return FORCE_EDIT_OPTIONS;
|
return FORCE_EDIT_OPTIONS;
|
||||||
|
} else if (permission === this.permissionValues.submit.id) {
|
||||||
|
return FORCE_SUBMIT_OPTIONS;
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -71,6 +71,16 @@ limitations under the License.
|
|||||||
value: true,
|
value: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const FORCE_SUBMIT_OPTIONS = [
|
||||||
|
{
|
||||||
|
name: 'No Submit on Push',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Submit on Push',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
let permission = 'push';
|
let permission = 'push';
|
||||||
assert.isTrue(element._computeForce(permission));
|
assert.isTrue(element._computeForce(permission));
|
||||||
assert.equal(element._computeForceClass(permission), 'force');
|
assert.equal(element._computeForceClass(permission), 'force');
|
||||||
@@ -82,6 +92,11 @@ limitations under the License.
|
|||||||
assert.deepEqual(element._computeForceOptions(permission),
|
assert.deepEqual(element._computeForceOptions(permission),
|
||||||
FORCE_EDIT_OPTIONS);
|
FORCE_EDIT_OPTIONS);
|
||||||
permission = 'submit';
|
permission = 'submit';
|
||||||
|
assert.isTrue(element._computeForce(permission));
|
||||||
|
assert.equal(element._computeForceClass(permission), 'force');
|
||||||
|
assert.deepEqual(element._computeForceOptions(permission),
|
||||||
|
FORCE_SUBMIT_OPTIONS);
|
||||||
|
permission = 'editHashtags';
|
||||||
assert.isFalse(element._computeForce(permission));
|
assert.isFalse(element._computeForce(permission));
|
||||||
assert.equal(element._computeForceClass(permission), '');
|
assert.equal(element._computeForceClass(permission), '');
|
||||||
assert.deepEqual(element._computeForceOptions(permission), []);
|
assert.deepEqual(element._computeForceOptions(permission), []);
|
||||||
@@ -124,7 +139,7 @@ limitations under the License.
|
|||||||
{action: 'ALLOW', force: false});
|
{action: 'ALLOW', force: false});
|
||||||
permission = 'submit';
|
permission = 'submit';
|
||||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||||
{action: 'ALLOW'});
|
{action: 'ALLOW', force: false});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_setDefaultRuleValues', () => {
|
test('_setDefaultRuleValues', () => {
|
||||||
@@ -210,7 +225,7 @@ limitations under the License.
|
|||||||
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
assert.equal(element.$.action.bindValue, element.rule.value.action);
|
||||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMin'));
|
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMin'));
|
||||||
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMax'));
|
assert.isNotOk(Polymer.dom(element.root).querySelector('#labelMax'));
|
||||||
assert.isFalse(element.$.force.classList.contains('force'));
|
assert.isTrue(element.$.force.classList.contains('force'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('modify and cancel restores original values', () => {
|
test('modify and cancel restores original values', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user