Add a "is:pure-revert" predicate This predicate can be used in search queries and submit requirement expressions. Bug: Google b/203640165 Change-Id: Ic2142daede83e886e001f5e10432d490f631c02c
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt index cc8d813..1543720 100644 --- a/Documentation/user-search.txt +++ b/Documentation/user-search.txt
@@ -565,6 +565,11 @@ cherry-picked locally using the git cherry-pick command and then pushed to Gerrit. +[[pure-revert]] +is:pure-revert:: ++ +True if the change is a pure revert. + [[status]] status:open, status:pending, status:new:: +
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java index b9569e4..1990cc0 100644 --- a/java/com/google/gerrit/server/index/change/ChangeField.java +++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -412,6 +412,10 @@ integer(ChangeQueryBuilder.FIELD_REVERTOF) .build(cd -> cd.change().getRevertOf() != null ? cd.change().getRevertOf().get() : null); + public static final FieldDef<ChangeData, String> IS_PURE_REVERT = + fullText(ChangeQueryBuilder.FIELD_PURE_REVERT) + .build(cd -> Boolean.TRUE.equals(cd.isPureRevert()) ? "1" : "0"); + @VisibleForTesting static List<String> getReviewerFieldValues(ReviewerSet reviewers) { List<String> r = new ArrayList<>(reviewers.asTable().size() * 2);
diff --git a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java index 9339d62..5dfce84 100644 --- a/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java +++ b/java/com/google/gerrit/server/index/change/ChangeSchemaDefinitions.java
@@ -183,9 +183,14 @@ new Schema.Builder<ChangeData>().add(V69).add(ChangeField.ATTENTION_SET_USERS_COUNT).build(); /** Added new field {@link ChangeField#UPLOADER}. */ + @Deprecated static final Schema<ChangeData> V71 = new Schema.Builder<ChangeData>().add(V70).add(ChangeField.UPLOADER).build(); + /** Added new field {@link ChangeField#IS_PURE_REVERT}. */ + static final Schema<ChangeData> V72 = + new Schema.Builder<ChangeData>().add(V71).add(ChangeField.IS_PURE_REVERT).build(); + /** * Name of the change index to be used when contacting index backends or loading configurations. */
diff --git a/java/com/google/gerrit/server/query/change/ChangePredicates.java b/java/com/google/gerrit/server/query/change/ChangePredicates.java index 3afdcdd..7e50c6f 100644 --- a/java/com/google/gerrit/server/query/change/ChangePredicates.java +++ b/java/com/google/gerrit/server/query/change/ChangePredicates.java
@@ -342,4 +342,12 @@ public static Predicate<ChangeData> submitRuleStatus(String value) { return new ChangeIndexPredicate(ChangeField.SUBMIT_RULE_RESULT, value); } + + /** + * Returns a predicate that matches with changes that are pure reverts if {@code value} is equal + * to "1", or non-pure reverts if {@code value} is "0". + */ + public static Predicate<ChangeData> pureRevert(String value) { + return new ChangeIndexPredicate(ChangeField.IS_PURE_REVERT, value); + } }
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java index 8006c61..e1cf454 100644 --- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java +++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -204,6 +204,7 @@ public static final String FIELD_WATCHEDBY = "watchedby"; public static final String FIELD_WIP = "wip"; public static final String FIELD_REVERTOF = "revertof"; + public static final String FIELD_PURE_REVERT = "ispurerevert"; public static final String FIELD_CHERRYPICK = "cherrypick"; public static final String FIELD_CHERRY_PICK_OF_CHANGE = "cherrypickofchange"; public static final String FIELD_CHERRY_PICK_OF_PATCHSET = "cherrypickofpatchset"; @@ -704,6 +705,11 @@ return ChangePredicates.assignee(Account.id(ChangeField.NO_ASSIGNEE)); } + if ("pure-revert".equalsIgnoreCase(value)) { + checkFieldAvailable(ChangeField.IS_PURE_REVERT, "is:pure-revert"); + return ChangePredicates.pureRevert("1"); + } + if ("submittable".equalsIgnoreCase(value)) { // SubmittablePredicate will match if *any* of the submit records are OK, // but we need to check that they're *all* OK, so check that none of the
diff --git a/javatests/com/google/gerrit/acceptance/server/project/SubmitRequirementsEvaluatorIT.java b/javatests/com/google/gerrit/acceptance/server/project/SubmitRequirementsEvaluatorIT.java index f511683..b76d5cb 100644 --- a/javatests/com/google/gerrit/acceptance/server/project/SubmitRequirementsEvaluatorIT.java +++ b/javatests/com/google/gerrit/acceptance/server/project/SubmitRequirementsEvaluatorIT.java
@@ -25,6 +25,7 @@ import com.google.gerrit.acceptance.PushOneCommit; import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; import com.google.gerrit.common.Nullable; +import com.google.gerrit.entities.Change; import com.google.gerrit.entities.LabelFunction; import com.google.gerrit.entities.SubmitRequirement; import com.google.gerrit.entities.SubmitRequirementExpression; @@ -32,6 +33,7 @@ import com.google.gerrit.entities.SubmitRequirementExpressionResult.Status; import com.google.gerrit.entities.SubmitRequirementResult; import com.google.gerrit.extensions.api.changes.ReviewInput; +import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.server.project.SubmitRequirementsEvaluator; import com.google.gerrit.server.query.change.ChangeData; @@ -215,6 +217,33 @@ .isEqualTo("Unsupported operator invalid_field:invalid_value"); } + @Test + public void byPureRevert() throws Exception { + testRepo.reset("HEAD~1"); + PushOneCommit.Result pushResult = + createChange(testRepo, "refs/heads/master", "Fix a bug", "file.txt", "content", "topic"); + changeData = pushResult.getChange(); + changeId = pushResult.getChangeId(); + + SubmitRequirement sr = + createSubmitRequirement( + /* applicabilityExpr= */ "project:" + project.get(), + /* submittabilityExpr= */ "is:pure-revert", + /* overrideExpr= */ ""); + + SubmitRequirementResult result = evaluator.evaluateRequirement(sr, changeData); + assertThat(result.status()).isEqualTo(SubmitRequirementResult.Status.UNSATISFIED); + approve(changeId); + gApi.changes().id(changeId).current().submit(); + + ChangeInfo changeInfo = gApi.changes().id(changeId).revert().get(); + String revertId = Integer.toString(changeInfo._number); + ChangeData revertChangeData = + changeQueryProvider.get().byLegacyChangeId(Change.Id.parse(revertId)).get(0); + result = evaluator.evaluateRequirement(sr, revertChangeData); + assertThat(result.status()).isEqualTo(SubmitRequirementResult.Status.SATISFIED); + } + private void voteLabel(String changeId, String labelName, int score) throws RestApiException { gApi.changes().id(changeId).current().review(new ReviewInput().label(labelName, score)); }
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java index 3b671aa..26bb7a0 100644 --- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java +++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -26,6 +26,7 @@ import static com.google.gerrit.server.project.testing.TestLabels.label; import static com.google.gerrit.server.project.testing.TestLabels.value; import static com.google.gerrit.testing.GerritJUnit.assertThrows; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; @@ -48,6 +49,7 @@ import com.google.gerrit.acceptance.config.GerritConfig; import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; import com.google.gerrit.common.Nullable; +import com.google.gerrit.common.RawInputUtil; import com.google.gerrit.entities.Account; import com.google.gerrit.entities.AccountGroup; import com.google.gerrit.entities.BranchNameKey; @@ -3891,6 +3893,33 @@ } @Test + public void isPureRevert() throws Exception { + assume().that(getSchema().hasField(ChangeField.IS_PURE_REVERT)).isTrue(); + TestRepository<Repo> repo = createProject("repo"); + // Create two commits and revert second commit (initial commit can't be reverted) + Change initial = insert(repo, newChange(repo)); + gApi.changes().id(initial.getChangeId()).current().review(ReviewInput.approve()); + gApi.changes().id(initial.getChangeId()).current().submit(); + + ChangeInfo changeToRevert = + gApi.changes().create(new ChangeInput("repo", "master", "commit to revert")).get(); + gApi.changes().id(changeToRevert.id).current().review(ReviewInput.approve()); + gApi.changes().id(changeToRevert.id).current().submit(); + + ChangeInfo changeThatReverts = gApi.changes().id(changeToRevert.id).revert().get(); + Change.Id changeThatRevertsId = Change.id(changeThatReverts._number); + assertQueryByIds("is:pure-revert", changeThatRevertsId); + + // Update the change that reverts such that it's not a pure revert + gApi.changes() + .id(changeThatReverts.id) + .edit() + .modifyFile("some-file.txt", RawInputUtil.create("newcontent".getBytes(UTF_8))); + gApi.changes().id(changeThatReverts.id).edit().publish(); + assertQueryByIds("is:pure-revert"); + } + + @Test public void selfFailsForAnonymousUser() throws Exception { for (String query : ImmutableList.of("assignee:self", "has:star", "is:starred", "star:star")) { assertQuery(query);