Add copyAnyScore configuration option to label.
This option, when enabled, copies all votes from previous patch sets to new patch sets. This is useful for *very* sticky approvals. Without this there is no way to allow for Code-Review +1 and +2 votes and to have Code-Review +1 votes be sticky. Change-Id: Id9c3916c60063b96d1812e6ced6ac4c52db64d2b
This commit is contained in:
@@ -262,6 +262,12 @@ the past and affect submission somehow.
|
|||||||
|
|
||||||
Defaults to true.
|
Defaults to true.
|
||||||
|
|
||||||
|
[[label_copyAnyScore]]
|
||||||
|
=== `label.Label-Name.copyAnyScore`
|
||||||
|
|
||||||
|
If true, any score for the label is copied forward when a new patch
|
||||||
|
set is uploaded. Defaults to false.
|
||||||
|
|
||||||
[[label_copyMinScore]]
|
[[label_copyMinScore]]
|
||||||
=== `label.Label-Name.copyMinScore`
|
=== `label.Label-Name.copyMinScore`
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@ public class LabelType {
|
|||||||
public static final boolean DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE = false;
|
public static final boolean DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE = false;
|
||||||
public static final boolean DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = false;
|
public static final boolean DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = false;
|
||||||
public static final boolean DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE = false;
|
public static final boolean DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE = false;
|
||||||
|
public static final boolean DEF_COPY_ANY_SCORE = false;
|
||||||
public static final boolean DEF_COPY_MAX_SCORE = false;
|
public static final boolean DEF_COPY_MAX_SCORE = false;
|
||||||
public static final boolean DEF_COPY_MIN_SCORE = false;
|
public static final boolean DEF_COPY_MIN_SCORE = false;
|
||||||
public static final boolean DEF_IGNORE_SELF_APPROVAL = false;
|
public static final boolean DEF_IGNORE_SELF_APPROVAL = false;
|
||||||
@@ -96,6 +97,7 @@ public class LabelType {
|
|||||||
|
|
||||||
protected LabelFunction function;
|
protected LabelFunction function;
|
||||||
|
|
||||||
|
protected boolean copyAnyScore;
|
||||||
protected boolean copyMinScore;
|
protected boolean copyMinScore;
|
||||||
protected boolean copyMaxScore;
|
protected boolean copyMaxScore;
|
||||||
protected boolean copyAllScoresOnMergeFirstParentUpdate;
|
protected boolean copyAllScoresOnMergeFirstParentUpdate;
|
||||||
@@ -139,6 +141,7 @@ public class LabelType {
|
|||||||
setCopyAllScoresIfNoCodeChange(DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE);
|
setCopyAllScoresIfNoCodeChange(DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE);
|
||||||
setCopyAllScoresOnTrivialRebase(DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE);
|
setCopyAllScoresOnTrivialRebase(DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE);
|
||||||
setCopyAllScoresOnMergeFirstParentUpdate(DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE);
|
setCopyAllScoresOnMergeFirstParentUpdate(DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE);
|
||||||
|
setCopyAnyScore(DEF_COPY_ANY_SCORE);
|
||||||
setCopyMaxScore(DEF_COPY_MAX_SCORE);
|
setCopyMaxScore(DEF_COPY_MAX_SCORE);
|
||||||
setCopyMinScore(DEF_COPY_MIN_SCORE);
|
setCopyMinScore(DEF_COPY_MIN_SCORE);
|
||||||
setAllowPostSubmit(DEF_ALLOW_POST_SUBMIT);
|
setAllowPostSubmit(DEF_ALLOW_POST_SUBMIT);
|
||||||
@@ -229,6 +232,14 @@ public class LabelType {
|
|||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCopyAnyScore() {
|
||||||
|
return copyAnyScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCopyAnyScore(boolean copyAnyScore) {
|
||||||
|
this.copyAnyScore = copyAnyScore;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCopyMinScore() {
|
public boolean isCopyMinScore() {
|
||||||
return copyMinScore;
|
return copyMinScore;
|
||||||
}
|
}
|
||||||
|
@@ -99,6 +99,8 @@ public class ApprovalInference {
|
|||||||
} else if ((type.isCopyMinScore() && type.isMaxNegative(psa))
|
} else if ((type.isCopyMinScore() && type.isMaxNegative(psa))
|
||||||
|| (type.isCopyMaxScore() && type.isMaxPositive(psa))) {
|
|| (type.isCopyMaxScore() && type.isMaxPositive(psa))) {
|
||||||
return true;
|
return true;
|
||||||
|
} else if (type.isCopyAnyScore()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case MERGE_FIRST_PARENT_UPDATE:
|
case MERGE_FIRST_PARENT_UPDATE:
|
||||||
|
@@ -101,6 +101,7 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
public static final String KEY_COPY_MIN_SCORE = "copyMinScore";
|
public static final String KEY_COPY_MIN_SCORE = "copyMinScore";
|
||||||
public static final String KEY_ALLOW_POST_SUBMIT = "allowPostSubmit";
|
public static final String KEY_ALLOW_POST_SUBMIT = "allowPostSubmit";
|
||||||
public static final String KEY_IGNORE_SELF_APPROVAL = "ignoreSelfApproval";
|
public static final String KEY_IGNORE_SELF_APPROVAL = "ignoreSelfApproval";
|
||||||
|
public static final String KEY_COPY_ANY_SCORE = "copyAnyScore";
|
||||||
public static final String KEY_COPY_MAX_SCORE = "copyMaxScore";
|
public static final String KEY_COPY_MAX_SCORE = "copyMaxScore";
|
||||||
public static final String KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE =
|
public static final String KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE =
|
||||||
"copyAllScoresOnMergeFirstParentUpdate";
|
"copyAllScoresOnMergeFirstParentUpdate";
|
||||||
@@ -960,6 +961,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
rc.getBoolean(LABEL, name, KEY_ALLOW_POST_SUBMIT, LabelType.DEF_ALLOW_POST_SUBMIT));
|
rc.getBoolean(LABEL, name, KEY_ALLOW_POST_SUBMIT, LabelType.DEF_ALLOW_POST_SUBMIT));
|
||||||
label.setIgnoreSelfApproval(
|
label.setIgnoreSelfApproval(
|
||||||
rc.getBoolean(LABEL, name, KEY_IGNORE_SELF_APPROVAL, LabelType.DEF_IGNORE_SELF_APPROVAL));
|
rc.getBoolean(LABEL, name, KEY_IGNORE_SELF_APPROVAL, LabelType.DEF_IGNORE_SELF_APPROVAL));
|
||||||
|
label.setCopyAnyScore(
|
||||||
|
rc.getBoolean(LABEL, name, KEY_COPY_ANY_SCORE, LabelType.DEF_COPY_ANY_SCORE));
|
||||||
label.setCopyMinScore(
|
label.setCopyMinScore(
|
||||||
rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, LabelType.DEF_COPY_MIN_SCORE));
|
rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, LabelType.DEF_COPY_MIN_SCORE));
|
||||||
label.setCopyMaxScore(
|
label.setCopyMaxScore(
|
||||||
@@ -1417,6 +1420,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
|
|||||||
KEY_IGNORE_SELF_APPROVAL,
|
KEY_IGNORE_SELF_APPROVAL,
|
||||||
label.ignoreSelfApproval(),
|
label.ignoreSelfApproval(),
|
||||||
LabelType.DEF_IGNORE_SELF_APPROVAL);
|
LabelType.DEF_IGNORE_SELF_APPROVAL);
|
||||||
|
setBooleanConfigKey(
|
||||||
|
rc,
|
||||||
|
LABEL,
|
||||||
|
name,
|
||||||
|
KEY_COPY_ANY_SCORE,
|
||||||
|
label.isCopyAnyScore(),
|
||||||
|
LabelType.DEF_COPY_ANY_SCORE);
|
||||||
setBooleanConfigKey(
|
setBooleanConfigKey(
|
||||||
rc,
|
rc,
|
||||||
LABEL,
|
LABEL,
|
||||||
|
@@ -118,6 +118,28 @@ public class StickyApprovalsIT extends AbstractDaemonTest {
|
|||||||
EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE));
|
EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void stickyOnAnyScore() throws Exception {
|
||||||
|
try (ProjectConfigUpdate u = updateProject(project)) {
|
||||||
|
u.getConfig().getLabelSections().get("Code-Review").setCopyAnyScore(true);
|
||||||
|
u.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChangeKind changeKind :
|
||||||
|
EnumSet.of(REWORK, TRIVIAL_REBASE, NO_CODE_CHANGE, MERGE_FIRST_PARENT_UPDATE, NO_CHANGE)) {
|
||||||
|
testRepo.reset(projectOperations.project(project).getHead("master"));
|
||||||
|
|
||||||
|
String changeId = createChange(changeKind);
|
||||||
|
vote(admin, changeId, 2, 1);
|
||||||
|
vote(user, changeId, 1, -1);
|
||||||
|
|
||||||
|
updateChange(changeId, changeKind);
|
||||||
|
ChangeInfo c = detailedChange(changeId);
|
||||||
|
assertVotes(c, admin, 2, 0, changeKind);
|
||||||
|
assertVotes(c, user, 1, 0, changeKind);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void stickyOnMinScore() throws Exception {
|
public void stickyOnMinScore() throws Exception {
|
||||||
try (ProjectConfigUpdate u = updateProject(project)) {
|
try (ProjectConfigUpdate u = updateProject(project)) {
|
||||||
|
@@ -63,7 +63,10 @@ import org.junit.rules.TemporaryFolder;
|
|||||||
|
|
||||||
public class ProjectConfigTest {
|
public class ProjectConfigTest {
|
||||||
private static final String LABEL_SCORES_CONFIG =
|
private static final String LABEL_SCORES_CONFIG =
|
||||||
" copyMinScore = "
|
" copyAnyScore = "
|
||||||
|
+ !LabelType.DEF_COPY_ANY_SCORE
|
||||||
|
+ "\n"
|
||||||
|
+ " copyMinScore = "
|
||||||
+ !LabelType.DEF_COPY_MIN_SCORE
|
+ !LabelType.DEF_COPY_MIN_SCORE
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ " copyMaxScore = "
|
+ " copyMaxScore = "
|
||||||
@@ -259,6 +262,7 @@ public class ProjectConfigTest {
|
|||||||
ProjectConfig cfg = read(rev);
|
ProjectConfig cfg = read(rev);
|
||||||
Map<String, LabelType> labels = cfg.getLabelSections();
|
Map<String, LabelType> labels = cfg.getLabelSections();
|
||||||
LabelType type = labels.entrySet().iterator().next().getValue();
|
LabelType type = labels.entrySet().iterator().next().getValue();
|
||||||
|
assertThat(type.isCopyAnyScore()).isNotEqualTo(LabelType.DEF_COPY_ANY_SCORE);
|
||||||
assertThat(type.isCopyMinScore()).isNotEqualTo(LabelType.DEF_COPY_MIN_SCORE);
|
assertThat(type.isCopyMinScore()).isNotEqualTo(LabelType.DEF_COPY_MIN_SCORE);
|
||||||
assertThat(type.isCopyMaxScore()).isNotEqualTo(LabelType.DEF_COPY_MAX_SCORE);
|
assertThat(type.isCopyMaxScore()).isNotEqualTo(LabelType.DEF_COPY_MAX_SCORE);
|
||||||
assertThat(type.isCopyAllScoresOnMergeFirstParentUpdate())
|
assertThat(type.isCopyAllScoresOnMergeFirstParentUpdate())
|
||||||
|
Reference in New Issue
Block a user