Add 'is:merge' operator to find changes which are merge commits
This change introduces a new index schema version and reindexing the changes is required. Change-Id: If800fce63f6d45419b46e5e624f6872ca3feaba3
This commit is contained in:
		@@ -487,6 +487,11 @@ is:wip::
 | 
				
			|||||||
+
 | 
					+
 | 
				
			||||||
True if the change is Work In Progress.
 | 
					True if the change is Work In Progress.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[merge]]
 | 
				
			||||||
 | 
					is:merge::
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					True if the change is a merge commit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[status]]
 | 
					[[status]]
 | 
				
			||||||
status:open, status:pending, status:new::
 | 
					status:open, status:pending, status:new::
 | 
				
			||||||
+
 | 
					+
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -696,6 +696,19 @@ public class ChangeField {
 | 
				
			|||||||
                return m ? "1" : "0";
 | 
					                return m ? "1" : "0";
 | 
				
			||||||
              });
 | 
					              });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Whether the change is a merge commit. */
 | 
				
			||||||
 | 
					  public static final FieldDef<ChangeData, String> MERGE =
 | 
				
			||||||
 | 
					      exact(ChangeQueryBuilder.FIELD_MERGE)
 | 
				
			||||||
 | 
					          .stored()
 | 
				
			||||||
 | 
					          .build(
 | 
				
			||||||
 | 
					              cd -> {
 | 
				
			||||||
 | 
					                Boolean m = cd.isMerge();
 | 
				
			||||||
 | 
					                if (m == null) {
 | 
				
			||||||
 | 
					                  return null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return m ? "1" : "0";
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** The number of inserted lines in this change. */
 | 
					  /** The number of inserted lines in this change. */
 | 
				
			||||||
  public static final FieldDef<ChangeData, Integer> ADDED =
 | 
					  public static final FieldDef<ChangeData, Integer> ADDED =
 | 
				
			||||||
      intRange(ChangeQueryBuilder.FIELD_ADDED)
 | 
					      intRange(ChangeQueryBuilder.FIELD_ADDED)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -121,6 +121,7 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> {
 | 
				
			|||||||
   * Added new fields {@link ChangeField#ATTENTION_SET_USERS} and {@link
 | 
					   * Added new fields {@link ChangeField#ATTENTION_SET_USERS} and {@link
 | 
				
			||||||
   * ChangeField#ATTENTION_SET_FULL}.
 | 
					   * ChangeField#ATTENTION_SET_FULL}.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 | 
					  @Deprecated
 | 
				
			||||||
  static final Schema<ChangeData> V59 =
 | 
					  static final Schema<ChangeData> V59 =
 | 
				
			||||||
      new Schema.Builder<ChangeData>()
 | 
					      new Schema.Builder<ChangeData>()
 | 
				
			||||||
          .add(V58)
 | 
					          .add(V58)
 | 
				
			||||||
@@ -128,6 +129,10 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> {
 | 
				
			|||||||
          .add(ChangeField.ATTENTION_SET_FULL)
 | 
					          .add(ChangeField.ATTENTION_SET_FULL)
 | 
				
			||||||
          .build();
 | 
					          .build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** Added new fields {@link ChangeField#MERGE} */
 | 
				
			||||||
 | 
					  static final Schema<ChangeData> V60 =
 | 
				
			||||||
 | 
					      new Schema.Builder<ChangeData>().add(V59).add(ChangeField.MERGE).build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Name of the change index to be used when contacting index backends or loading configurations.
 | 
					   * Name of the change index to be used when contacting index backends or loading configurations.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -284,6 +284,7 @@ public class ChangeData {
 | 
				
			|||||||
  private Optional<ChangedLines> changedLines;
 | 
					  private Optional<ChangedLines> changedLines;
 | 
				
			||||||
  private SubmitTypeRecord submitTypeRecord;
 | 
					  private SubmitTypeRecord submitTypeRecord;
 | 
				
			||||||
  private Boolean mergeable;
 | 
					  private Boolean mergeable;
 | 
				
			||||||
 | 
					  private Boolean merge;
 | 
				
			||||||
  private Set<String> hashtags;
 | 
					  private Set<String> hashtags;
 | 
				
			||||||
  private Map<Account.Id, Ref> editsByUser;
 | 
					  private Map<Account.Id, Ref> editsByUser;
 | 
				
			||||||
  private Set<Account.Id> reviewedBy;
 | 
					  private Set<Account.Id> reviewedBy;
 | 
				
			||||||
@@ -953,6 +954,16 @@ public class ChangeData {
 | 
				
			|||||||
    return mergeable;
 | 
					    return mergeable;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Nullable
 | 
				
			||||||
 | 
					  public Boolean isMerge() {
 | 
				
			||||||
 | 
					    if (merge == null) {
 | 
				
			||||||
 | 
					      if (!loadCommitData()) {
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return parentCount > 1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public Set<Account.Id> editsByUser() {
 | 
					  public Set<Account.Id> editsByUser() {
 | 
				
			||||||
    return editRefs().keySet();
 | 
					    return editRefs().keySet();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -597,6 +597,13 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
 | 
				
			|||||||
      return new BooleanPredicate(ChangeField.MERGEABLE);
 | 
					      return new BooleanPredicate(ChangeField.MERGEABLE);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ("merge".equalsIgnoreCase(value)) {
 | 
				
			||||||
 | 
					      if (args.getSchema().hasField(ChangeField.MERGE)) {
 | 
				
			||||||
 | 
					        return new BooleanPredicate(ChangeField.MERGE);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      throw new QueryParseException("'is:merge' operator is not supported by change index version");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ("private".equalsIgnoreCase(value)) {
 | 
					    if ("private".equalsIgnoreCase(value)) {
 | 
				
			||||||
      if (args.getSchema().hasField(ChangeField.PRIVATE)) {
 | 
					      if (args.getSchema().hasField(ChangeField.PRIVATE)) {
 | 
				
			||||||
        return new BooleanPredicate(ChangeField.PRIVATE);
 | 
					        return new BooleanPredicate(ChangeField.PRIVATE);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2124,6 +2124,29 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
 | 
				
			|||||||
    assertQuery("status:open -is:mergeable", change2);
 | 
					    assertQuery("status:open -is:mergeable", change2);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void merge() throws Exception {
 | 
				
			||||||
 | 
					    assume().that(getSchema().hasField(ChangeField.MERGE)).isTrue();
 | 
				
			||||||
 | 
					    TestRepository<Repo> repo = createProject("repo");
 | 
				
			||||||
 | 
					    RevCommit commit1 = repo.parseBody(repo.commit().add("file1", "contents1").create());
 | 
				
			||||||
 | 
					    RevCommit commit2 = repo.parseBody(repo.commit().add("file1", "contents2").create());
 | 
				
			||||||
 | 
					    Change change1 = insert(repo, newChangeForCommit(repo, commit1));
 | 
				
			||||||
 | 
					    Change change2 = insert(repo, newChangeForCommit(repo, commit2));
 | 
				
			||||||
 | 
					    RevCommit mergeCommit =
 | 
				
			||||||
 | 
					        repo.branch("master")
 | 
				
			||||||
 | 
					            .commit()
 | 
				
			||||||
 | 
					            .message("Merge commit")
 | 
				
			||||||
 | 
					            .parent(commit1)
 | 
				
			||||||
 | 
					            .parent(commit2)
 | 
				
			||||||
 | 
					            .insertChangeId()
 | 
				
			||||||
 | 
					            .create();
 | 
				
			||||||
 | 
					    Change mergeChange = insert(repo, newChangeForCommit(repo, mergeCommit));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assertQuery("status:open is:merge", mergeChange);
 | 
				
			||||||
 | 
					    assertQuery("status:open -is:merge", change2, change1);
 | 
				
			||||||
 | 
					    assertQuery("status:open", mergeChange, change2, change1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Test
 | 
					  @Test
 | 
				
			||||||
  public void reviewedBy() throws Exception {
 | 
					  public void reviewedBy() throws Exception {
 | 
				
			||||||
    resetTimeWithClockStep(2, MINUTES);
 | 
					    resetTimeWithClockStep(2, MINUTES);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user