diff --git a/Documentation/config-labels.txt b/Documentation/config-labels.txt index 9c90ba7482..193a96f6b7 100644 --- a/Documentation/config-labels.txt +++ b/Documentation/config-labels.txt @@ -262,6 +262,12 @@ the past and affect submission somehow. 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.Label-Name.copyMinScore` diff --git a/java/com/google/gerrit/common/data/LabelType.java b/java/com/google/gerrit/common/data/LabelType.java index 25b8d197e0..c6cabe2a42 100644 --- a/java/com/google/gerrit/common/data/LabelType.java +++ b/java/com/google/gerrit/common/data/LabelType.java @@ -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_ON_TRIVIAL_REBASE = 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_MIN_SCORE = false; public static final boolean DEF_IGNORE_SELF_APPROVAL = false; @@ -96,6 +97,7 @@ public class LabelType { protected LabelFunction function; + protected boolean copyAnyScore; protected boolean copyMinScore; protected boolean copyMaxScore; protected boolean copyAllScoresOnMergeFirstParentUpdate; @@ -139,6 +141,7 @@ public class LabelType { setCopyAllScoresIfNoCodeChange(DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE); setCopyAllScoresOnTrivialRebase(DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE); setCopyAllScoresOnMergeFirstParentUpdate(DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE); + setCopyAnyScore(DEF_COPY_ANY_SCORE); setCopyMaxScore(DEF_COPY_MAX_SCORE); setCopyMinScore(DEF_COPY_MIN_SCORE); setAllowPostSubmit(DEF_ALLOW_POST_SUBMIT); @@ -229,6 +232,14 @@ public class LabelType { this.defaultValue = defaultValue; } + public boolean isCopyAnyScore() { + return copyAnyScore; + } + + public void setCopyAnyScore(boolean copyAnyScore) { + this.copyAnyScore = copyAnyScore; + } + public boolean isCopyMinScore() { return copyMinScore; } diff --git a/java/com/google/gerrit/server/ApprovalInference.java b/java/com/google/gerrit/server/ApprovalInference.java index f5cc9563b2..8d132cd473 100644 --- a/java/com/google/gerrit/server/ApprovalInference.java +++ b/java/com/google/gerrit/server/ApprovalInference.java @@ -99,6 +99,8 @@ public class ApprovalInference { } else if ((type.isCopyMinScore() && type.isMaxNegative(psa)) || (type.isCopyMaxScore() && type.isMaxPositive(psa))) { return true; + } else if (type.isCopyAnyScore()) { + return true; } switch (kind) { case MERGE_FIRST_PARENT_UPDATE: diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java index 7eb5f5746c..65513abb75 100644 --- a/java/com/google/gerrit/server/project/ProjectConfig.java +++ b/java/com/google/gerrit/server/project/ProjectConfig.java @@ -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_ALLOW_POST_SUBMIT = "allowPostSubmit"; 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_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE = "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)); label.setIgnoreSelfApproval( 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( rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, LabelType.DEF_COPY_MIN_SCORE)); label.setCopyMaxScore( @@ -1417,6 +1420,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError. KEY_IGNORE_SELF_APPROVAL, label.ignoreSelfApproval(), LabelType.DEF_IGNORE_SELF_APPROVAL); + setBooleanConfigKey( + rc, + LABEL, + name, + KEY_COPY_ANY_SCORE, + label.isCopyAnyScore(), + LabelType.DEF_COPY_ANY_SCORE); setBooleanConfigKey( rc, LABEL, diff --git a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java index 894e980895..6e9ccdfd25 100644 --- a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java +++ b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java @@ -118,6 +118,28 @@ public class StickyApprovalsIT extends AbstractDaemonTest { 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 public void stickyOnMinScore() throws Exception { try (ProjectConfigUpdate u = updateProject(project)) { diff --git a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java index 0b401df460..b53f35579f 100644 --- a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java +++ b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java @@ -63,7 +63,10 @@ import org.junit.rules.TemporaryFolder; public class ProjectConfigTest { private static final String LABEL_SCORES_CONFIG = - " copyMinScore = " + " copyAnyScore = " + + !LabelType.DEF_COPY_ANY_SCORE + + "\n" + + " copyMinScore = " + !LabelType.DEF_COPY_MIN_SCORE + "\n" + " copyMaxScore = " @@ -259,6 +262,7 @@ public class ProjectConfigTest { ProjectConfig cfg = read(rev); Map labels = cfg.getLabelSections(); 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.isCopyMaxScore()).isNotEqualTo(LabelType.DEF_COPY_MAX_SCORE); assertThat(type.isCopyAllScoresOnMergeFirstParentUpdate())