diff --git a/Documentation/cmd-query.txt b/Documentation/cmd-query.txt index 79723c52d0..0243b8d7c6 100644 --- a/Documentation/cmd-query.txt +++ b/Documentation/cmd-query.txt @@ -17,6 +17,7 @@ _ssh_ -p _gerrit query_ [--submit-records] [--all-reviewers] [--start | -S ] + [--no-limit] [--] [limit:] @@ -101,6 +102,9 @@ command line parser in the server). -S:: Number of changes to skip. +--no-limit:: + Return all results, overriding the default limit. + limit::: Maximum number of results to return. This is actually a query operator, and not a command line option. If more diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index b60e56d8ac..cdb464dee9 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -350,6 +350,11 @@ be recomputed often, which is slow for projects with big trees. as link:#tracking-id-info[TrackingIdInfo]. -- +[[no-limit]] +-- +* `NO-LIMIT`: Return all results +-- + .Request ---- GET /changes/?q=97&o=CURRENT_REVISION&o=CURRENT_COMMIT&o=CURRENT_FILES&o=DOWNLOAD_COMMANDS HTTP/1.0 diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java index 362803fde4..55599aad62 100644 --- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java +++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java @@ -46,6 +46,7 @@ import com.google.gerrit.common.data.LabelFunction; import com.google.gerrit.common.data.LabelType; import com.google.gerrit.common.data.LabelValue; import com.google.gerrit.common.data.Permission; +import com.google.gerrit.common.data.PermissionRange; import com.google.gerrit.common.data.PermissionRule; import com.google.gerrit.common.data.PermissionRule.Action; import com.google.gerrit.extensions.api.GerritApi; @@ -954,6 +955,17 @@ public abstract class AbstractDaemonTest { } } + protected void allowGlobalCapabilities( + AccountGroup.UUID id, int min, int max, String... capabilityNames) throws Exception { + try (ProjectConfigUpdate u = updateProject(allProjects)) { + for (String capabilityName : capabilityNames) { + Util.allow( + u.getConfig(), capabilityName, id, new PermissionRange(capabilityName, min, max)); + } + u.save(); + } + } + protected void allowGlobalCapabilities(AccountGroup.UUID id, String... capabilityNames) throws Exception { allowGlobalCapabilities(id, Arrays.asList(capabilityNames)); diff --git a/java/com/google/gerrit/extensions/api/changes/Changes.java b/java/com/google/gerrit/extensions/api/changes/Changes.java index 0708ef5dc9..b651fdd0f0 100644 --- a/java/com/google/gerrit/extensions/api/changes/Changes.java +++ b/java/com/google/gerrit/extensions/api/changes/Changes.java @@ -75,6 +75,7 @@ public interface Changes { private String query; private int limit; private int start; + private boolean isNoLimit; private EnumSet options = EnumSet.noneOf(ListChangesOption.class); public abstract List get() throws RestApiException; @@ -89,6 +90,11 @@ public interface Changes { return this; } + public QueryRequest withNoLimit() { + this.isNoLimit = true; + return this; + } + public QueryRequest withStart(int start) { this.start = start; return this; @@ -117,6 +123,10 @@ public interface Changes { return limit; } + public boolean getNoLimit() { + return isNoLimit; + } + public int getStart() { return start; } @@ -137,7 +147,11 @@ public interface Changes { if (!options.isEmpty()) { sb.append("options=").append(options); } - return sb.append('}').toString(); + sb.append('}'); + if (isNoLimit == true) { + sb.append(" --no-limit"); + } + return sb.toString(); } } diff --git a/java/com/google/gerrit/index/query/QueryProcessor.java b/java/com/google/gerrit/index/query/QueryProcessor.java index 081575b631..302cf01107 100644 --- a/java/com/google/gerrit/index/query/QueryProcessor.java +++ b/java/com/google/gerrit/index/query/QueryProcessor.java @@ -91,6 +91,7 @@ public abstract class QueryProcessor { private boolean enforceVisibility = true; private int userProvidedLimit; + private boolean isNoLimit; private Set requestedFields; protected QueryProcessor( @@ -157,6 +158,11 @@ public abstract class QueryProcessor { return this; } + public QueryProcessor setNoLimit(boolean isNoLimit) { + this.isNoLimit = isNoLimit; + return this; + } + public QueryProcessor setRequestedFields(Set fields) { requestedFields = fields; return this; @@ -354,6 +360,9 @@ public abstract class QueryProcessor { } private int getEffectiveLimit(Predicate p) { + if (isNoLimit == true) { + return Integer.MAX_VALUE; + } List possibleLimits = new ArrayList<>(4); possibleLimits.add(getBackendSupportedLimit()); possibleLimits.add(getPermittedLimit()); diff --git a/java/com/google/gerrit/server/api/changes/ChangesImpl.java b/java/com/google/gerrit/server/api/changes/ChangesImpl.java index 2f19040935..0fdaeaa20b 100644 --- a/java/com/google/gerrit/server/api/changes/ChangesImpl.java +++ b/java/com/google/gerrit/server/api/changes/ChangesImpl.java @@ -116,6 +116,7 @@ class ChangesImpl implements Changes { } qc.setLimit(q.getLimit()); qc.setStart(q.getStart()); + qc.setNoLimit(q.getNoLimit()); for (ListChangesOption option : q.getOptions()) { qc.addOption(option); } diff --git a/java/com/google/gerrit/server/project/testing/Util.java b/java/com/google/gerrit/server/project/testing/Util.java index abfd2bd624..204fa7b8f3 100644 --- a/java/com/google/gerrit/server/project/testing/Util.java +++ b/java/com/google/gerrit/server/project/testing/Util.java @@ -124,16 +124,28 @@ public class Util { public static PermissionRule allow( ProjectConfig project, String capabilityName, AccountGroup.UUID group) { + return allow(project, capabilityName, group, (PermissionRange) null); + } + + public static PermissionRule allow( + ProjectConfig project, + String capabilityName, + AccountGroup.UUID group, + PermissionRange customRange) { PermissionRule rule = newRule(project, group); project .getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true) .getPermission(capabilityName, true) .add(rule); if (GlobalCapability.hasRange(capabilityName)) { - PermissionRange.WithDefaults range = GlobalCapability.getRange(capabilityName); - if (range != null) { - rule.setRange(range.getDefaultMin(), range.getDefaultMax()); + if (customRange == null) { + PermissionRange.WithDefaults range = GlobalCapability.getRange(capabilityName); + if (range != null) { + rule.setRange(range.getDefaultMin(), range.getDefaultMax()); + } + return rule; } + rule.setRange(customRange.getMin(), customRange.getMax()); } return rule; } diff --git a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java index 17c23b6fdf..171768a974 100644 --- a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java +++ b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java @@ -120,6 +120,10 @@ public class OutputStreamQuery { queryProcessor.setUserProvidedLimit(n); } + public void setNoLimit(boolean on) { + queryProcessor.setNoLimit(on); + } + public void setStart(int n) { queryProcessor.setStart(n); } diff --git a/java/com/google/gerrit/server/restapi/change/QueryChanges.java b/java/com/google/gerrit/server/restapi/change/QueryChanges.java index d1eea44884..9fedfd640a 100644 --- a/java/com/google/gerrit/server/restapi/change/QueryChanges.java +++ b/java/com/google/gerrit/server/restapi/change/QueryChanges.java @@ -82,6 +82,11 @@ public class QueryChanges implements RestReadView, DynamicOpti imp.setStart(start); } + @Option(name = "--no-limit", usage = "Return all results, overriding the default limit") + public void setNoLimit(boolean on) { + imp.setNoLimit(on); + } + @Override public void setDynamicBean(String plugin, DynamicOptions.DynamicBean dynamicBean) { imp.setDynamicBean(plugin, dynamicBean); diff --git a/java/com/google/gerrit/sshd/commands/Query.java b/java/com/google/gerrit/sshd/commands/Query.java index 4d8351ec6f..78485d3442 100644 --- a/java/com/google/gerrit/sshd/commands/Query.java +++ b/java/com/google/gerrit/sshd/commands/Query.java @@ -91,6 +91,11 @@ public class Query extends SshCommand implements DynamicOptions.BeanReceiver { processor.setStart(start); } + @Option(name = "--no-limit", usage = "Return all results, overriding the default limit") + void setNoLimit(boolean on) { + processor.setNoLimit(on); + } + @Argument( index = 0, required = true, diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java index f2ee8e1b3b..cdc2c017da 100644 --- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java +++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java @@ -71,6 +71,7 @@ import com.google.gerrit.acceptance.testsuite.account.AccountOperations; import com.google.gerrit.acceptance.testsuite.group.GroupOperations; import com.google.gerrit.acceptance.testsuite.project.ProjectOperations; import com.google.gerrit.common.FooterConstants; +import com.google.gerrit.common.data.GlobalCapability; import com.google.gerrit.common.data.LabelFunction; import com.google.gerrit.common.data.LabelType; import com.google.gerrit.common.data.Permission; @@ -2553,6 +2554,19 @@ public class ChangeIT extends AbstractDaemonTest { assertThat(Iterables.getOnlyElement(results).changeId).isEqualTo(r2.getChangeId()); } + @Test + public void queryChangesNoLimit() throws Exception { + allowGlobalCapabilities( + SystemGroupBackend.REGISTERED_USERS, 0, 2, GlobalCapability.QUERY_LIMIT); + for (int i = 0; i < 3; i++) { + createChange(); + } + List resultsWithDefaultLimit = gApi.changes().query().get(); + List resultsWithNoLimit = gApi.changes().query().withNoLimit().get(); + assertThat(resultsWithDefaultLimit).hasSize(2); + assertThat(resultsWithNoLimit.size()).isAtLeast(3); + } + @Test public void queryChangesStart() throws Exception { PushOneCommit.Result r1 = createChange();