Merge "Add a "is:pure-revert" predicate"
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 6ebc293..2581d89 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);