Create a label config for copying all scores if list of files is the same

This change allows creating new labels or setting to an old label a new
label config: copyAllScoresIfListOfFilesDidNotChange.

Labels that have this config set to true will copy all scores if the
list of files did not change. Renames count as the same file (= no file
change); as long as there are no explicit additions or deletions to the
list of files, the scores will be copied to the next patch-set.

Change-Id: I0051ea1236e6bd50a69455d799ce27081091d21a
This commit is contained in:
Gal Paikin
2021-01-19 11:55:19 +01:00
parent d60c956621
commit bef260ec30
20 changed files with 316 additions and 3 deletions

View File

@@ -283,6 +283,22 @@ forward when a new patch set is uploaded. This can be used to enable
sticky approvals, reducing turn-around for trivial cleanups prior to
submitting a change. Defaults to false.
[[label_copyAllScoresIfListOfFilesDidNotChange]]
=== `label.Label-Name.copyAllScoresIfListOfFilesDidNotChange`
This policy is useful if you don't want to trigger CI or human
verification again if the list of files didn't change.
If true, all scores for the label are copied forward when a new
patch-set is uploaded that has the same list of files as the previous
patch-set.
Renames are considered the same file when computing whether new files
were added or old files were deleted. Hence, if there are only renames,
scores will still be copied over.
Defaults to false.
[[label_copyAllScoresOnMergeFirstParentUpdate]]
=== `label.Label-Name.copyAllScoresOnMergeFirstParentUpdate`

View File

@@ -3971,6 +3971,9 @@ copyAllScoresIfNoCodeChange] is set on the label.
|`copy_all_scores_on_trivial_rebase`|`false` if not set|
Whether link:config-labels.html#label_copyAllScoresOnTrivialRebase[
copyAllScoresOnTrivialRebase] is set on the label.
|`copy_all_scores_if_list_of_files_did_not_change`|`false` if not set|
Whether link:config-labels.html#label_copyAllScoresIfListOfFilesDidNotChange[
copyAllScoresIfListOfFilesDidNotChange] is set on the label.
|`copy_all_scores_on_merge_first_parent_update`|`false` if not set|
Whether link:config-labels.html#label_copyAllScoresOnMergeFirstParentUpdate[
copyAllScoresOnMergeFirstParentUpdate] is set on the label.
@@ -4038,6 +4041,9 @@ copyAllScoresIfNoCodeChange] is set on the label.
|`copy_all_scores_on_trivial_rebase`|optional|
Whether link:config-labels.html#label_copyAllScoresOnTrivialRebase[
copyAllScoresOnTrivialRebase] is set on the label.
|`copy_all_scores_if_list_of_files_did_not_change`|optional|
Whether link:config-labels.html#label_copyAllScoresIfListOfFilesDidNotChange[
copyAllScoresIfListOfFilesDidNotChange] is set on the label.
|`copy_all_scores_on_merge_first_parent_update`|optional|
Whether link:config-labels.html#label_copyAllScoresOnMergeFirstParentUpdate[
copyAllScoresOnMergeFirstParentUpdate] is set on the label.

View File

@@ -29,6 +29,7 @@ import java.util.List;
public abstract class LabelType {
public static final boolean DEF_ALLOW_POST_SUBMIT = true;
public static final boolean DEF_CAN_OVERRIDE = true;
public static final boolean DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE = false;
public static final boolean DEF_COPY_ALL_SCORES_IF_NO_CHANGE = true;
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;
@@ -101,6 +102,8 @@ public abstract class LabelType {
public abstract boolean isCopyMaxScore();
public abstract boolean isCopyAllScoresIfListOfFilesDidNotChange();
public abstract boolean isCopyAllScoresOnMergeFirstParentUpdate();
public abstract boolean isCopyAllScoresOnTrivialRebase();
@@ -143,6 +146,8 @@ public abstract class LabelType {
.setMaxNegative(Short.MIN_VALUE)
.setMaxPositive(Short.MAX_VALUE)
.setCanOverride(DEF_CAN_OVERRIDE)
.setCopyAllScoresIfListOfFilesDidNotChange(
DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE)
.setCopyAllScoresIfNoChange(DEF_COPY_ALL_SCORES_IF_NO_CHANGE)
.setCopyAllScoresIfNoCodeChange(DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE)
.setCopyAllScoresOnTrivialRebase(DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE)
@@ -238,6 +243,9 @@ public abstract class LabelType {
public abstract Builder setCopyMaxScore(boolean copyMaxScore);
public abstract Builder setCopyAllScoresIfListOfFilesDidNotChange(
boolean copyAllScoresIfListOfFilesDidNotChange);
public abstract Builder setCopyAllScoresOnMergeFirstParentUpdate(
boolean copyAllScoresOnMergeFirstParentUpdate);

View File

@@ -28,6 +28,7 @@ public class LabelDefinitionInfo {
public Boolean copyAnyScore;
public Boolean copyMinScore;
public Boolean copyMaxScore;
public Boolean copyAllScoresIfListOfFilesDidNotChange;
public Boolean copyAllScoresIfNoChange;
public Boolean copyAllScoresIfNoCodeChange;
public Boolean copyAllScoresOnTrivialRebase;

View File

@@ -27,6 +27,7 @@ public class LabelDefinitionInput extends InputWithCommitMessage {
public Boolean copyAnyScore;
public Boolean copyMinScore;
public Boolean copyMaxScore;
public Boolean copyAllScoresIfListOfFilesDidNotChange;
public Boolean copyAllScoresIfNoChange;
public Boolean copyAllScoresIfNoCodeChange;
public Boolean copyAllScoresOnTrivialRebase;

View File

@@ -25,15 +25,22 @@ import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.Patch.ChangeType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.server.change.ChangeKindCache;
import com.google.gerrit.server.change.LabelNormalizer;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListKey;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
@@ -59,13 +66,18 @@ public class ApprovalInference {
private final ProjectCache projectCache;
private final ChangeKindCache changeKindCache;
private final LabelNormalizer labelNormalizer;
private final PatchListCache patchListCache;
@Inject
ApprovalInference(
ProjectCache projectCache, ChangeKindCache changeKindCache, LabelNormalizer labelNormalizer) {
ProjectCache projectCache,
ChangeKindCache changeKindCache,
LabelNormalizer labelNormalizer,
PatchListCache patchListCache) {
this.projectCache = projectCache;
this.changeKindCache = changeKindCache;
this.labelNormalizer = labelNormalizer;
this.patchListCache = patchListCache;
}
/**
@@ -93,10 +105,15 @@ public class ApprovalInference {
}
private static boolean canCopy(
ProjectState project, PatchSetApproval psa, PatchSet.Id psId, ChangeKind kind) {
ProjectState project,
PatchSetApproval psa,
PatchSet.Id psId,
ChangeKind kind,
PatchList patchList) {
int n = psa.key().patchSetId().get();
checkArgument(n != psId.get());
LabelType type = project.getLabelTypes().byLabel(psa.labelId());
if (type == null) {
logger.atFine().log(
"approval %d on label %s of patch set %d of change %d cannot be copied"
@@ -153,6 +170,25 @@ public class ApprovalInference {
psa.value(),
project.getName());
return true;
} else if (type.isCopyAllScoresIfListOfFilesDidNotChange()
&& patchList.getPatches().stream()
.noneMatch(
p ->
p.getChangeType() == ChangeType.ADDED
|| p.getChangeType() == ChangeType.DELETED)) {
logger.atFine().log(
"approval %d on label %s of patch set %d of change %d can be copied"
+ " to patch set %d because the label has set "
+ "copyAllScoresIfListOfFilesDidNotChange = true on "
+ "project %s and list of files did not change (maybe except a rename, which is "
+ "still the same file).",
psa.value(),
psa.label(),
n,
psa.key().patchSetId().changeId().get(),
psId.get(),
project.getName());
return true;
}
switch (kind) {
case MERGE_FIRST_PARENT_UPDATE:
@@ -331,15 +367,38 @@ public class ApprovalInference {
logger.atFine().log(
"change kind for patch set %d of change %d against prior patch set %s is %s",
ps.id().get(), ps.id().changeId().get(), priorPatchSet.getValue().id().changeId(), kind);
PatchList patchList = getPatchList(project, ps, priorPatchSet);
for (PatchSetApproval psa : priorApprovals) {
if (resultByUser.contains(psa.label(), psa.accountId())) {
continue;
}
if (!canCopy(project, psa, ps.id(), kind)) {
if (!canCopy(project, psa, ps.id(), kind, patchList)) {
continue;
}
resultByUser.put(psa.label(), psa.accountId(), psa.copyWithPatchSet(ps.id()));
}
return resultByUser.values();
}
/**
* Gets the {@link PatchList} between the two latest patch-sets. Can be used to compute difference
* in files between those two patch-sets .
*/
private PatchList getPatchList(
ProjectState project, PatchSet ps, Map.Entry<PatchSet.Id, PatchSet> priorPatchSet) {
PatchListKey key =
PatchListKey.againstCommit(
priorPatchSet.getValue().commitId(),
ps.commitId(),
DiffPreferencesInfo.Whitespace.IGNORE_NONE);
try {
return patchListCache.get(key, project.getNameKey());
} catch (PatchListNotAvailableException ex) {
throw new StorageException(
"failed to compute difference in files, so won't copy"
+ " votes on labels even if list of files is the same and "
+ "copyAllIfListOfFilesDidNotChange",
ex);
}
}
}

View File

@@ -42,6 +42,8 @@ public class LabelTypeSerializer {
.setCopyAnyScore(proto.getCopyAnyScore())
.setCopyMinScore(proto.getCopyMinScore())
.setCopyMaxScore(proto.getCopyMaxScore())
.setCopyAllScoresIfListOfFilesDidNotChange(
proto.getCopyAllScoresIfListOfFilesDidNotChange())
.setCopyAllScoresOnMergeFirstParentUpdate(proto.getCopyAllScoresOnMergeFirstParentUpdate())
.setCopyAllScoresOnTrivialRebase(proto.getCopyAllScoresOnTrivialRebase())
.setCopyAllScoresIfNoCodeChange(proto.getCopyAllScoresIfNoCodeChange())
@@ -68,6 +70,8 @@ public class LabelTypeSerializer {
.setCopyAnyScore(autoValue.isCopyAnyScore())
.setCopyMinScore(autoValue.isCopyMinScore())
.setCopyMaxScore(autoValue.isCopyMaxScore())
.setCopyAllScoresIfListOfFilesDidNotChange(
autoValue.isCopyAllScoresIfListOfFilesDidNotChange())
.setCopyAllScoresOnMergeFirstParentUpdate(
autoValue.isCopyAllScoresOnMergeFirstParentUpdate())
.setCopyAllScoresOnTrivialRebase(autoValue.isCopyAllScoresOnTrivialRebase())

View File

@@ -35,6 +35,8 @@ public class LabelDefinitionJson {
label.copyAnyScore = toBoolean(labelType.isCopyAnyScore());
label.copyMinScore = toBoolean(labelType.isCopyMinScore());
label.copyMaxScore = toBoolean(labelType.isCopyMaxScore());
label.copyAllScoresIfListOfFilesDidNotChange =
toBoolean(labelType.isCopyAllScoresIfListOfFilesDidNotChange());
label.copyAllScoresIfNoChange = toBoolean(labelType.isCopyAllScoresIfNoChange());
label.copyAllScoresIfNoCodeChange = toBoolean(labelType.isCopyAllScoresIfNoCodeChange());
label.copyAllScoresOnTrivialRebase = toBoolean(labelType.isCopyAllScoresOnTrivialRebase());

View File

@@ -111,6 +111,8 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
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_IF_LIST_OF_FILES_DID_NOT_CHANGE =
"copyAllScoresIfListOfFilesDidNotChange";
public static final String KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE =
"copyAllScoresOnMergeFirstParentUpdate";
public static final String KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = "copyAllScoresOnTrivialRebase";
@@ -1029,6 +1031,12 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, LabelType.DEF_COPY_MIN_SCORE));
label.setCopyMaxScore(
rc.getBoolean(LABEL, name, KEY_COPY_MAX_SCORE, LabelType.DEF_COPY_MAX_SCORE));
label.setCopyAllScoresIfListOfFilesDidNotChange(
rc.getBoolean(
LABEL,
name,
KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE,
LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE));
label.setCopyAllScoresOnMergeFirstParentUpdate(
rc.getBoolean(
LABEL,
@@ -1562,6 +1570,13 @@ public class ProjectConfig extends VersionedMetaData implements ValidationError.
KEY_COPY_ALL_SCORES_IF_NO_CHANGE,
label.isCopyAllScoresIfNoChange(),
LabelType.DEF_COPY_ALL_SCORES_IF_NO_CHANGE);
setBooleanConfigKey(
rc,
LABEL,
name,
KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE,
label.isCopyAllScoresIfListOfFilesDidNotChange(),
LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE);
setBooleanConfigKey(
rc,
LABEL,

View File

@@ -174,6 +174,11 @@ public class CreateLabel
labelType.setCopyMaxScore(input.copyMaxScore);
}
if (input.copyAllScoresIfListOfFilesDidNotChange != null) {
labelType.setCopyAllScoresIfListOfFilesDidNotChange(
input.copyAllScoresIfListOfFilesDidNotChange);
}
if (input.copyAllScoresIfNoChange != null) {
labelType.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
}

View File

@@ -189,6 +189,12 @@ public class SetLabel implements RestModifyView<LabelResource, LabelDefinitionIn
dirty = true;
}
if (input.copyAllScoresIfListOfFilesDidNotChange != null) {
labelTypeBuilder.setCopyAllScoresIfListOfFilesDidNotChange(
input.copyAllScoresIfListOfFilesDidNotChange);
dirty = true;
}
if (input.copyAllScoresIfNoChange != null) {
labelTypeBuilder.setCopyAllScoresIfNoChange(input.copyAllScoresIfNoChange);
dirty = true;

View File

@@ -37,8 +37,10 @@ import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.CherryPickInput;
@@ -68,6 +70,7 @@ import org.junit.Test;
public class StickyApprovalsIT extends AbstractDaemonTest {
@Inject private ProjectOperations projectOperations;
@Inject private RequestScopeOperations requestScopeOperations;
@Inject private ChangeOperations changeOperations;
@Inject
@Named("change_kind")
@@ -324,6 +327,96 @@ public class StickyApprovalsIT extends AbstractDaemonTest {
assertVotes(c, user, 0, 0, null);
}
@Test
public void notStickyWithCopyAllScoresIfListOfFilesDidNotChangeWhenFileIsAdded()
throws Exception {
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig()
.updateLabelType("Code-Review", b -> b.setCopyAllScoresIfListOfFilesDidNotChange(true));
u.save();
}
Change.Id changeId =
changeOperations.newChange().project(project).file("file").content("content").create();
vote(admin, changeId.toString(), 2, 1);
vote(user, changeId.toString(), -2, -1);
changeOperations
.change(changeId)
.newPatchset()
.file("new file")
.content("new content")
.create();
ChangeInfo c = detailedChange(changeId.toString());
// no votes are copied since the list of files changed.
assertVotes(c, admin, 0, 0);
assertVotes(c, user, 0, 0);
}
@Test
public void notStickyWithCopyAllScoresIfListOfFilesDidNotChangeWhenFileIsDeleted()
throws Exception {
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig()
.updateLabelType("Code-Review", b -> b.setCopyAllScoresIfListOfFilesDidNotChange(true));
u.save();
}
Change.Id changeId =
changeOperations.newChange().project(project).file("file").content("content").create();
vote(admin, changeId.toString(), 2, 1);
vote(user, changeId.toString(), -2, -1);
changeOperations.change(changeId).newPatchset().file("file").delete().create();
ChangeInfo c = detailedChange(changeId.toString());
// no votes are copied since the list of files changed.
assertVotes(c, admin, 0, 0);
assertVotes(c, user, 0, 0);
}
@Test
public void stickyWithCopyAllScoresIfListOfFilesDidNotChangeWhenFileIsModified()
throws Exception {
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig()
.updateLabelType("Code-Review", b -> b.setCopyAllScoresIfListOfFilesDidNotChange(true));
u.save();
}
Change.Id changeId =
changeOperations.newChange().project(project).file("file").content("content").create();
vote(admin, changeId.toString(), 2, 1);
vote(user, changeId.toString(), -2, -1);
changeOperations.change(changeId).newPatchset().file("file").content("new content").create();
ChangeInfo c = detailedChange(changeId.toString());
// only code review votes are copied since copyAllScoresIfListOfFilesDidNotChange is
// configured for that label, and list of files didn't change.
assertVotes(c, admin, 2, 0);
assertVotes(c, user, -2, 0);
}
@Test
public void stickyWithCopyAllScoresIfListOfFilesDidNotChangeWhenFileIsRenamed() throws Exception {
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig()
.updateLabelType("Code-Review", b -> b.setCopyAllScoresIfListOfFilesDidNotChange(true));
u.save();
}
Change.Id changeId =
changeOperations.newChange().project(project).file("file").content("content").create();
vote(admin, changeId.toString(), 2, 1);
vote(user, changeId.toString(), -2, -1);
changeOperations.change(changeId).newPatchset().file("file").renameTo("new_file").create();
ChangeInfo c = detailedChange(changeId.toString());
// only code review votes are copied since copyAllScoresIfListOfFilesDidNotChange is
// configured for that label, and list of files didn't change (rename is still the same file).
assertVotes(c, admin, 2, 0);
assertVotes(c, user, -2, 0);
}
@Test
public void removedVotesNotSticky() throws Exception {
try (ProjectConfigUpdate u = updateProject(project)) {

View File

@@ -240,6 +240,7 @@ public class CreateLabelIT extends AbstractDaemonTest {
assertThat(createdLabel.copyAnyScore).isNull();
assertThat(createdLabel.copyMinScore).isNull();
assertThat(createdLabel.copyMaxScore).isNull();
assertThat(createdLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
assertThat(createdLabel.copyAllScoresIfNoChange).isTrue();
assertThat(createdLabel.copyAllScoresIfNoCodeChange).isNull();
assertThat(createdLabel.copyAllScoresOnTrivialRebase).isNull();
@@ -449,6 +450,28 @@ public class CreateLabelIT extends AbstractDaemonTest {
assertThat(createdLabel.copyMaxScore).isNull();
}
@Test
public void createWithCopyAllScoresIfListOfFilesDidNotChange() throws Exception {
LabelDefinitionInput input = new LabelDefinitionInput();
input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
input.copyAllScoresIfListOfFilesDidNotChange = true;
LabelDefinitionInfo createdLabel =
gApi.projects().name(project.get()).label("foo").create(input).get();
assertThat(createdLabel.copyAllScoresIfListOfFilesDidNotChange).isTrue();
}
@Test
public void createWithoutCopyAllScoresIfListOfFilesDidNotChange() throws Exception {
LabelDefinitionInput input = new LabelDefinitionInput();
input.values = ImmutableMap.of("+1", "Looks Good", " 0", "Don't Know", "-1", "Looks Bad");
input.copyAllScoresIfListOfFilesDidNotChange = false;
LabelDefinitionInfo createdLabel =
gApi.projects().name(project.get()).label("foo").create(input).get();
assertThat(createdLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
}
@Test
public void createWithCopyAllScoresIfNoChange() throws Exception {
LabelDefinitionInput input = new LabelDefinitionInput();

View File

@@ -113,6 +113,7 @@ public class GetLabelIT extends AbstractDaemonTest {
assertThat(fooLabel.copyAnyScore).isNull();
assertThat(fooLabel.copyMinScore).isNull();
assertThat(fooLabel.copyMaxScore).isNull();
assertThat(fooLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
assertThat(fooLabel.copyAllScoresIfNoChange).isNull();
assertThat(fooLabel.copyAllScoresIfNoCodeChange).isNull();
assertThat(fooLabel.copyAllScoresOnTrivialRebase).isNull();
@@ -135,6 +136,7 @@ public class GetLabelIT extends AbstractDaemonTest {
labelType.setCopyAnyScore(true);
labelType.setCopyMinScore(true);
labelType.setCopyMaxScore(true);
labelType.setCopyAllScoresIfListOfFilesDidNotChange(true);
labelType.setCopyAllScoresIfNoCodeChange(true);
labelType.setCopyAllScoresOnTrivialRebase(true);
labelType.setCopyAllScoresOnMergeFirstParentUpdate(true);
@@ -149,6 +151,7 @@ public class GetLabelIT extends AbstractDaemonTest {
assertThat(fooLabel.copyAnyScore).isTrue();
assertThat(fooLabel.copyMinScore).isTrue();
assertThat(fooLabel.copyMaxScore).isTrue();
assertThat(fooLabel.copyAllScoresIfListOfFilesDidNotChange).isTrue();
assertThat(fooLabel.copyAllScoresIfNoChange).isTrue();
assertThat(fooLabel.copyAllScoresIfNoCodeChange).isTrue();
assertThat(fooLabel.copyAllScoresOnTrivialRebase).isTrue();

View File

@@ -43,6 +43,7 @@ public class LabelAssert {
assertThat(codeReviewLabel.copyAnyScore).isNull();
assertThat(codeReviewLabel.copyMinScore).isTrue();
assertThat(codeReviewLabel.copyMaxScore).isNull();
assertThat(codeReviewLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
assertThat(codeReviewLabel.copyAllScoresIfNoChange).isTrue();
assertThat(codeReviewLabel.copyAllScoresIfNoCodeChange).isNull();
assertThat(codeReviewLabel.copyAllScoresOnTrivialRebase).isTrue();

View File

@@ -135,6 +135,7 @@ public class ListLabelsIT extends AbstractDaemonTest {
assertThat(fooLabel.copyAnyScore).isNull();
assertThat(fooLabel.copyMinScore).isNull();
assertThat(fooLabel.copyMaxScore).isNull();
assertThat(fooLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
assertThat(fooLabel.copyAllScoresIfNoChange).isNull();
assertThat(fooLabel.copyAllScoresIfNoCodeChange).isNull();
assertThat(fooLabel.copyAllScoresOnTrivialRebase).isNull();
@@ -157,6 +158,7 @@ public class ListLabelsIT extends AbstractDaemonTest {
labelType.setCopyAnyScore(true);
labelType.setCopyMinScore(true);
labelType.setCopyMaxScore(true);
labelType.setCopyAllScoresIfListOfFilesDidNotChange(true);
labelType.setCopyAllScoresIfNoCodeChange(true);
labelType.setCopyAllScoresOnTrivialRebase(true);
labelType.setCopyAllScoresOnMergeFirstParentUpdate(true);
@@ -174,6 +176,7 @@ public class ListLabelsIT extends AbstractDaemonTest {
assertThat(fooLabel.copyAnyScore).isTrue();
assertThat(fooLabel.copyMinScore).isTrue();
assertThat(fooLabel.copyMaxScore).isTrue();
assertThat(fooLabel.copyAllScoresIfListOfFilesDidNotChange).isTrue();
assertThat(fooLabel.copyAllScoresIfNoChange).isTrue();
assertThat(fooLabel.copyAllScoresIfNoCodeChange).isTrue();
assertThat(fooLabel.copyAllScoresOnTrivialRebase).isTrue();

View File

@@ -581,6 +581,65 @@ public class SetLabelIT extends AbstractDaemonTest {
assertThat(gApi.projects().name(project.get()).label("foo").get().copyMaxScore).isNull();
}
@Test
public void setCopyAllScoresIfListOfFilesDidNotChange() throws Exception {
configLabel("foo", LabelFunction.NO_OP);
assertThat(
gApi.projects()
.name(project.get())
.label("foo")
.get()
.copyAllScoresIfListOfFilesDidNotChange)
.isNull();
LabelDefinitionInput input = new LabelDefinitionInput();
input.copyAllScoresIfListOfFilesDidNotChange = true;
LabelDefinitionInfo updatedLabel =
gApi.projects().name(project.get()).label("foo").update(input);
assertThat(updatedLabel.copyAllScoresIfListOfFilesDidNotChange).isTrue();
assertThat(
gApi.projects()
.name(project.get())
.label("foo")
.get()
.copyAllScoresIfListOfFilesDidNotChange)
.isTrue();
}
@Test
public void unsetCopyAllScoresIfListOfFilesDidNotChange() throws Exception {
configLabel("foo", LabelFunction.NO_OP);
try (ProjectConfigUpdate u = updateProject(project)) {
u.getConfig()
.updateLabelType("foo", lt -> lt.setCopyAllScoresIfListOfFilesDidNotChange(true));
u.save();
}
assertThat(
gApi.projects()
.name(project.get())
.label("foo")
.get()
.copyAllScoresIfListOfFilesDidNotChange)
.isTrue();
LabelDefinitionInput input = new LabelDefinitionInput();
input.copyAllScoresIfListOfFilesDidNotChange = false;
LabelDefinitionInfo updatedLabel =
gApi.projects().name(project.get()).label("foo").update(input);
assertThat(updatedLabel.copyAllScoresIfListOfFilesDidNotChange).isNull();
assertThat(
gApi.projects()
.name(project.get())
.label("foo")
.get()
.copyAllScoresIfListOfFilesDidNotChange)
.isNull();
}
@Test
public void setCopyAllScoresIfNoChange() throws Exception {
configLabel("foo", LabelFunction.NO_OP);

View File

@@ -38,6 +38,8 @@ public class LabelTypeSerializerTest {
.setCopyAnyScore(!LabelType.DEF_COPY_ANY_SCORE)
.setCopyMaxScore(!LabelType.DEF_COPY_MAX_SCORE)
.setCopyMinScore(!LabelType.DEF_COPY_MIN_SCORE)
.setCopyAllScoresIfListOfFilesDidNotChange(
!LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE)
.setCopyAllScoresOnMergeFirstParentUpdate(
!LabelType.DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE)
.setCopyAllScoresOnTrivialRebase(!LabelType.DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE)

View File

@@ -77,6 +77,9 @@ public class ProjectConfigTest {
+ " copyMaxScore = "
+ !LabelType.DEF_COPY_MAX_SCORE
+ "\n"
+ " copyAllScoresIfListOfFilesDidNotChange = "
+ !LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE
+ "\n"
+ " copyAllScoresOnMergeFirstParentUpdate = "
+ !LabelType.DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE
+ "\n"
@@ -270,6 +273,8 @@ public class ProjectConfigTest {
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.isCopyAllScoresIfListOfFilesDidNotChange())
.isNotEqualTo(LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE);
assertThat(type.isCopyAllScoresOnMergeFirstParentUpdate())
.isNotEqualTo(LabelType.DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE);
assertThat(type.isCopyAllScoresOnTrivialRebase())

View File

@@ -443,6 +443,7 @@ message LabelTypeProto {
int32 max_positive = 16;
bool can_override = 17;
repeated string ref_patterns = 18;
bool copy_all_scores_if_list_of_files_did_not_change = 19;
}
// Serialized form of com.google.gerrit.server.project.ConfiguredMimeTypes.