summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuca Milanesio <luca.milanesio@gmail.com>2023-04-22 17:20:53 -0700
committerLuca Milanesio <luca.milanesio@gmail.com>2023-04-22 17:32:53 -0700
commit9978b91a581d5f91c8b57cf708144f60ccd5ed36 (patch)
tree2b93673a03e8e6716c7074e588eff238b5f60801
parent1626b4358e2de41e7b267088da0845d1b6f01161 (diff)
parent686fb694cd7ff696e40e3e3b37b5c378ce6fdcc2 (diff)
Merge branch 'stable-3.7' into stable-3.8
* stable-3.7: PaginatingSource: Stop matching changes after desired limit is reached Fix typo in test method name Don't retry new change creation on lock failure pgm-init.txt: remove reference to Review DB from --batch option gr-change-view: Call reload event with clear patchset set when editing commit msg Don't fail metric computation due to duplicated metric names gr-file-list-header: Use change-model for fetching latest patchNum gr-reply-dialog: Use change-model for patchNum gr-change-actions: Use change-model for setting editBasedOnCurrentPatchSet and editPatchsetLoaded DefaultMemoryCacheFactoryTest: Fix flaky test Set uninteresting branches based on project configuration Split RebaseSorter.isAlreadyMerged() to avoid unnecessary work Fix creating changes in SubmoduleSubscriptionsWholeTopicMergeIT Update JGit to 5166ded098 Update JGit to 0687c73a12 Fix LDAP "Remember me" default value in login form Allow to hide download schemes from the REST API and UI Update JGit to 176f17d05 Update JGit to 596c445af Update JGit to 66b871b AndSource: Run isVisibleToPredicate based on its cost Release-Notes: skip Change-Id: I9048fb57672c41abc62c06e07bdc7e86225e3daa
-rw-r--r--Documentation/pgm-init.txt5
-rw-r--r--java/com/google/gerrit/index/project/IndexedProjectQuery.java21
-rw-r--r--java/com/google/gerrit/index/query/AndSource.java33
-rw-r--r--java/com/google/gerrit/index/query/PaginatingSource.java3
-rw-r--r--java/com/google/gerrit/metrics/dropwizard/BUILD1
-rw-r--r--java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java2
-rw-r--r--java/com/google/gerrit/metrics/dropwizard/CallbackMetricImpl1.java15
-rw-r--r--java/com/google/gerrit/server/git/receive/ReceiveCommits.java200
-rw-r--r--java/com/google/gerrit/server/index/group/IndexedGroupQuery.java21
-rw-r--r--java/com/google/gerrit/server/query/account/AccountQueryProcessor.java5
-rw-r--r--java/com/google/gerrit/server/query/change/AndChangeSource.java8
-rw-r--r--java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java5
-rw-r--r--java/com/google/gerrit/server/query/group/GroupQueryProcessor.java5
-rw-r--r--java/com/google/gerrit/server/query/project/ProjectQueryProcessor.java5
-rw-r--r--java/com/google/gerrit/server/submit/RebaseSorter.java37
-rw-r--r--java/com/google/gerrit/server/submit/SubmitStrategy.java10
-rw-r--r--javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java57
-rw-r--r--javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java6
-rw-r--r--resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html1
19 files changed, 241 insertions, 199 deletions
diff --git a/Documentation/pgm-init.txt b/Documentation/pgm-init.txt
index 3c9e3fce37..4b346fecad 100644
--- a/Documentation/pgm-init.txt
+++ b/Documentation/pgm-init.txt
@@ -38,11 +38,6 @@ If run in an existing `$site_path`, init upgrades existing resources
install, reasonable configuration defaults are chosen based
on the whims of the Gerrit developers. On upgrades, the existing
settings in `gerrit.config` are respected.
-+
-If during a schema migration unused objects (e.g. tables, columns)
-are detected, they are *not* automatically dropped; a list of SQL
-statements to drop these objects is provided. To drop the unused
-objects these SQL statements must be executed manually.
--delete-caches::
Force deletion of all persistent cache files. Note that
diff --git a/java/com/google/gerrit/index/project/IndexedProjectQuery.java b/java/com/google/gerrit/index/project/IndexedProjectQuery.java
index 5fc74ca153..52d08d6e6d 100644
--- a/java/com/google/gerrit/index/project/IndexedProjectQuery.java
+++ b/java/com/google/gerrit/index/project/IndexedProjectQuery.java
@@ -14,11 +14,14 @@
package com.google.gerrit.index.project;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.gerrit.entities.Project;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.IndexedQuery;
+import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
@@ -27,11 +30,27 @@ import com.google.gerrit.index.query.QueryParseException;
* com.google.gerrit.index.IndexRewriter}. See {@link IndexedQuery}.
*/
public class IndexedProjectQuery extends IndexedQuery<Project.NameKey, ProjectData>
- implements DataSource<ProjectData> {
+ implements DataSource<ProjectData>, Matchable<ProjectData> {
public IndexedProjectQuery(
Index<Project.NameKey, ProjectData> index, Predicate<ProjectData> pred, QueryOptions opts)
throws QueryParseException {
super(index, pred, opts.convertForBackend());
}
+
+ @Override
+ public boolean match(ProjectData object) {
+ Predicate<ProjectData> pred = getChild(0);
+ checkState(
+ pred.isMatchable(),
+ "match invoked, but child predicate %s doesn't implement %s",
+ pred,
+ Matchable.class.getName());
+ return pred.asMatchable().match(object);
+ }
+
+ @Override
+ public int getCost() {
+ return 1;
+ }
}
diff --git a/java/com/google/gerrit/index/query/AndSource.java b/java/com/google/gerrit/index/query/AndSource.java
index f5f30bd097..3adf881310 100644
--- a/java/com/google/gerrit/index/query/AndSource.java
+++ b/java/com/google/gerrit/index/query/AndSource.java
@@ -16,7 +16,6 @@ package com.google.gerrit.index.query;
import static com.google.common.base.Preconditions.checkArgument;
-import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.IndexConfig;
import java.util.Collection;
import java.util.List;
@@ -24,36 +23,17 @@ import java.util.List;
public class AndSource<T> extends AndPredicate<T> implements DataSource<T> {
protected final DataSource<T> source;
- private final IsVisibleToPredicate<T> isVisibleToPredicate;
private final int start;
private final int cardinality;
private final IndexConfig indexConfig;
public AndSource(Collection<? extends Predicate<T>> that, IndexConfig indexConfig) {
- this(that, null, 0, indexConfig);
+ this(that, 0, indexConfig);
}
- public AndSource(
- Predicate<T> that, IsVisibleToPredicate<T> isVisibleToPredicate, IndexConfig indexConfig) {
- this(that, isVisibleToPredicate, 0, indexConfig);
- }
-
- public AndSource(
- Predicate<T> that,
- IsVisibleToPredicate<T> isVisibleToPredicate,
- int start,
- IndexConfig indexConfig) {
- this(ImmutableList.of(that), isVisibleToPredicate, start, indexConfig);
- }
-
- public AndSource(
- Collection<? extends Predicate<T>> that,
- IsVisibleToPredicate<T> isVisibleToPredicate,
- int start,
- IndexConfig indexConfig) {
+ public AndSource(Collection<? extends Predicate<T>> that, int start, IndexConfig indexConfig) {
super(that);
checkArgument(start >= 0, "negative start: %s", start);
- this.isVisibleToPredicate = isVisibleToPredicate;
this.start = start;
this.indexConfig = indexConfig;
@@ -93,16 +73,7 @@ public class AndSource<T> extends AndPredicate<T> implements DataSource<T> {
}
@Override
- public boolean isMatchable() {
- return isVisibleToPredicate != null || super.isMatchable();
- }
-
- @Override
public boolean match(T object) {
- if (isVisibleToPredicate != null && !isVisibleToPredicate.match(object)) {
- return false;
- }
-
if (super.isMatchable() && !super.match(object)) {
return false;
}
diff --git a/java/com/google/gerrit/index/query/PaginatingSource.java b/java/com/google/gerrit/index/query/PaginatingSource.java
index 337332f347..8431ccc6fc 100644
--- a/java/com/google/gerrit/index/query/PaginatingSource.java
+++ b/java/com/google/gerrit/index/query/PaginatingSource.java
@@ -87,6 +87,9 @@ public class PaginatingSource<T> implements DataSource<T> {
r.add(data);
}
pageResultSize++;
+ if (r.size() > limit) {
+ break;
+ }
}
nextStart += pageResultSize;
searchAfter = next.searchAfter();
diff --git a/java/com/google/gerrit/metrics/dropwizard/BUILD b/java/com/google/gerrit/metrics/dropwizard/BUILD
index 4b3859f7a8..dbb8f5ec5f 100644
--- a/java/com/google/gerrit/metrics/dropwizard/BUILD
+++ b/java/com/google/gerrit/metrics/dropwizard/BUILD
@@ -12,6 +12,7 @@ java_library(
"//lib:args4j",
"//lib:guava",
"//lib/dropwizard:dropwizard-core",
+ "//lib/flogger:api",
"//lib/guice",
],
)
diff --git a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
index b3860f72ab..da9ec70e53 100644
--- a/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
+++ b/java/com/google/gerrit/metrics/dropwizard/BucketedCallback.java
@@ -110,7 +110,7 @@ abstract class BucketedCallback<V> implements BucketedMetric {
}
}
- private String submetric(Object key) {
+ String submetric(Object key) {
return DropWizardMetricMaker.name(ordering, name, name(key));
}
diff --git a/java/com/google/gerrit/metrics/dropwizard/CallbackMetricImpl1.java b/java/com/google/gerrit/metrics/dropwizard/CallbackMetricImpl1.java
index d718035f40..bd3caf92ca 100644
--- a/java/com/google/gerrit/metrics/dropwizard/CallbackMetricImpl1.java
+++ b/java/com/google/gerrit/metrics/dropwizard/CallbackMetricImpl1.java
@@ -15,13 +15,17 @@
package com.google.gerrit.metrics.dropwizard;
import com.codahale.metrics.MetricRegistry;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.metrics.CallbackMetric1;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Field;
+import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/** Optimized version of {@link BucketedCallback} for single dimension. */
class CallbackMetricImpl1<F1, V> extends BucketedCallback<V> {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
CallbackMetricImpl1(
DropWizardMetricMaker metrics,
MetricRegistry registry,
@@ -44,9 +48,14 @@ class CallbackMetricImpl1<F1, V> extends BucketedCallback<V> {
@Override
public void set(F1 field1, V value) {
- BucketedCallback<V>.ValueGauge cell = getOrCreate(field1);
- cell.value = value;
- cell.set = true;
+ try {
+ BucketedCallback<V>.ValueGauge cell = getOrCreate(field1);
+ cell.value = value;
+ cell.set = true;
+ } catch (IllegalArgumentException e) {
+ logger.atWarning().withCause(e).atMostEvery(1, TimeUnit.HOURS).log(
+ "Unable to register duplicate metric: %s", submetric(field1));
+ }
}
@Override
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 0e9f7ca2fe..2baca53b1c 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -1038,111 +1038,29 @@ class ReceiveCommits {
return;
}
try {
- retryHelper
- .changeUpdate(
- "insertChangesAndPatchSets",
- updateFactory -> {
- try (BatchUpdate bu =
- batchUpdateFactory.create(
- project.getNameKey(), user.materializedCopy(), TimeUtil.now());
- ObjectInserter ins = repo.newObjectInserter();
- ObjectReader reader = ins.newReader();
- RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo, rw, ins);
- bu.setRefLogMessage("push");
- if (magicBranch != null) {
- bu.setNotify(magicBranch.getNotifyForNewChange());
- }
-
- logger.atFine().log("Adding %d replace requests", newChanges.size());
- for (ReplaceRequest replace : replaceByChange.values()) {
- replace.addOps(bu, replaceProgress);
- if (magicBranch != null) {
- bu.setNotifyHandling(
- replace.ontoChange, magicBranch.getNotifyHandling(replace.notes));
- if (magicBranch.shouldPublishComments()) {
- bu.addOp(
- replace.notes.getChangeId(),
- publishCommentsOp.create(replace.psId, project.getNameKey()));
- Optional<ChangeNotes> changeNotes =
- getChangeNotes(replace.notes.getChangeId());
- if (!changeNotes.isPresent()) {
- // If not present, no need to update attention set here since this is
- // a new change.
- continue;
- }
- List<HumanComment> drafts =
- commentsUtil.draftByChangeAuthor(
- changeNotes.get(), user.getAccountId());
- if (drafts.isEmpty()) {
- // If no comments, attention set shouldn't update since the user
- // didn't reply.
- continue;
- }
- replyAttentionSetUpdates.processAutomaticAttentionSetRulesOnReply(
- bu,
- changeNotes.get(),
- isReadyForReview(changeNotes.get()),
- user,
- drafts);
- }
- }
- }
-
- logger.atFine().log("Adding %d create requests", newChanges.size());
- for (CreateRequest create : newChanges) {
- create.addOps(bu);
- }
-
- logger.atFine().log("Adding %d group update requests", newChanges.size());
- updateGroups.forEach(r -> r.addOps(bu));
-
- logger.atFine().log("Executing batch");
- try {
- bu.execute();
- } catch (UpdateException e) {
- throw asRestApiException(e);
- }
-
- replaceByChange.values().stream()
- .forEach(
- req ->
- result.addChange(
- ReceiveCommitsResult.ChangeStatus.REPLACED, req.ontoChange));
- newChanges.stream()
- .forEach(
- req ->
- result.addChange(
- ReceiveCommitsResult.ChangeStatus.CREATED, req.changeId));
-
- if (magicBranchCmd != null) {
- magicBranchCmd.setResult(OK);
- }
- for (ReplaceRequest replace : replaceByChange.values()) {
- String rejectMessage = replace.getRejectMessage();
- if (rejectMessage == null) {
- if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
- // Not necessarily the magic branch, so need to set OK on the original
- // value.
- replace.inputCommand.setResult(OK);
- }
- } else {
- logger.atFine().log("Rejecting due to message from ReplaceOp");
- reject(replace.inputCommand, rejectMessage);
- }
- }
- }
- return null;
- })
- .defaultTimeoutMultiplier(5)
- .call();
+ if (!newChanges.isEmpty()) {
+ // TODO: Retry lock failures on new change insertions. The retry will
+ // likely have to move to a higher layer to be able to achieve that
+ // due to state that needs to be reset with each retry attempt.
+ insertChangesAndPatchSets(magicBranchCmd, newChanges, replaceProgress);
+ } else {
+ retryHelper
+ .changeUpdate(
+ "insertPatchSets",
+ updateFactory -> {
+ insertChangesAndPatchSets(magicBranchCmd, newChanges, replaceProgress);
+ return null;
+ })
+ .defaultTimeoutMultiplier(5)
+ .call();
+ }
} catch (ResourceConflictException e) {
addError(e.getMessage());
reject(magicBranchCmd, "conflict");
} catch (BadRequestException | UnprocessableEntityException | AuthException e) {
logger.atFine().withCause(e).log("Rejecting due to client error");
reject(magicBranchCmd, e.getMessage());
- } catch (RestApiException | UpdateException e) {
+ } catch (RestApiException | IOException | UpdateException e) {
throw new StorageException("Can't insert change/patch set for " + project.getName(), e);
}
@@ -1166,6 +1084,90 @@ class ReceiveCommits {
}
}
+ private void insertChangesAndPatchSets(
+ ReceiveCommand magicBranchCmd, List<CreateRequest> newChanges, Task replaceProgress)
+ throws RestApiException, IOException {
+ try (BatchUpdate bu =
+ batchUpdateFactory.create(
+ project.getNameKey(), user.materializedCopy(), TimeUtil.now());
+ ObjectInserter ins = repo.newObjectInserter();
+ ObjectReader reader = ins.newReader();
+ RevWalk rw = new RevWalk(reader)) {
+ bu.setRepository(repo, rw, ins);
+ bu.setRefLogMessage("push");
+ if (magicBranch != null) {
+ bu.setNotify(magicBranch.getNotifyForNewChange());
+ }
+
+ logger.atFine().log("Adding %d replace requests", newChanges.size());
+ for (ReplaceRequest replace : replaceByChange.values()) {
+ replace.addOps(bu, replaceProgress);
+ if (magicBranch != null) {
+ bu.setNotifyHandling(replace.ontoChange, magicBranch.getNotifyHandling(replace.notes));
+ if (magicBranch.shouldPublishComments()) {
+ bu.addOp(
+ replace.notes.getChangeId(),
+ publishCommentsOp.create(replace.psId, project.getNameKey()));
+ Optional<ChangeNotes> changeNotes = getChangeNotes(replace.notes.getChangeId());
+ if (!changeNotes.isPresent()) {
+ // If not present, no need to update attention set here since this is
+ // a new change.
+ continue;
+ }
+ List<HumanComment> drafts =
+ commentsUtil.draftByChangeAuthor(changeNotes.get(), user.getAccountId());
+ if (drafts.isEmpty()) {
+ // If no comments, attention set shouldn't update since the user
+ // didn't reply.
+ continue;
+ }
+ replyAttentionSetUpdates.processAutomaticAttentionSetRulesOnReply(
+ bu, changeNotes.get(), isReadyForReview(changeNotes.get()), user, drafts);
+ }
+ }
+ }
+
+ logger.atFine().log("Adding %d create requests", newChanges.size());
+ for (CreateRequest create : newChanges) {
+ create.addOps(bu);
+ }
+
+ logger.atFine().log("Adding %d group update requests", newChanges.size());
+ updateGroups.forEach(r -> r.addOps(bu));
+
+ logger.atFine().log("Executing batch");
+ try {
+ bu.execute();
+ } catch (UpdateException e) {
+ throw asRestApiException(e);
+ }
+
+ replaceByChange.values().stream()
+ .forEach(
+ req -> result.addChange(ReceiveCommitsResult.ChangeStatus.REPLACED, req.ontoChange));
+ newChanges.stream()
+ .forEach(
+ req -> result.addChange(ReceiveCommitsResult.ChangeStatus.CREATED, req.changeId));
+
+ if (magicBranchCmd != null) {
+ magicBranchCmd.setResult(OK);
+ }
+ for (ReplaceRequest replace : replaceByChange.values()) {
+ String rejectMessage = replace.getRejectMessage();
+ if (rejectMessage == null) {
+ if (replace.inputCommand.getResult() == NOT_ATTEMPTED) {
+ // Not necessarily the magic branch, so need to set OK on the original
+ // value.
+ replace.inputCommand.setResult(OK);
+ }
+ } else {
+ logger.atFine().log("Rejecting due to message from ReplaceOp");
+ reject(replace.inputCommand, rejectMessage);
+ }
+ }
+ }
+ }
+
private boolean isReadyForReview(ChangeNotes changeNotes) {
return (!changeNotes.getChange().isWorkInProgress() && !magicBranch.workInProgress)
|| magicBranch.ready;
diff --git a/java/com/google/gerrit/server/index/group/IndexedGroupQuery.java b/java/com/google/gerrit/server/index/group/IndexedGroupQuery.java
index 7013e27b4c..1d8cc1e28e 100644
--- a/java/com/google/gerrit/server/index/group/IndexedGroupQuery.java
+++ b/java/com/google/gerrit/server/index/group/IndexedGroupQuery.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.index.group;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.index.Index;
@@ -21,6 +23,7 @@ import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.IndexedQuery;
+import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import java.util.HashSet;
@@ -31,7 +34,7 @@ import java.util.Set;
* com.google.gerrit.index.IndexRewriter}. See {@link IndexedQuery}.
*/
public class IndexedGroupQuery extends IndexedQuery<AccountGroup.UUID, InternalGroup>
- implements DataSource<InternalGroup> {
+ implements DataSource<InternalGroup>, Matchable<InternalGroup> {
public static QueryOptions createOptions(
IndexConfig config, int start, int pageSize, int limit, Set<String> fields) {
@@ -50,4 +53,20 @@ public class IndexedGroupQuery extends IndexedQuery<AccountGroup.UUID, InternalG
throws QueryParseException {
super(index, pred, opts.convertForBackend());
}
+
+ @Override
+ public boolean match(InternalGroup object) {
+ Predicate<InternalGroup> pred = getChild(0);
+ checkState(
+ pred.isMatchable(),
+ "match invoked, but child predicate %s doesn't implement %s",
+ pred,
+ Matchable.class.getName());
+ return pred.asMatchable().match(object);
+ }
+
+ @Override
+ public int getCost() {
+ return 1;
+ }
}
diff --git a/java/com/google/gerrit/server/query/account/AccountQueryProcessor.java b/java/com/google/gerrit/server/query/account/AccountQueryProcessor.java
index 9893d1a778..eef913e13a 100644
--- a/java/com/google/gerrit/server/query/account/AccountQueryProcessor.java
+++ b/java/com/google/gerrit/server/query/account/AccountQueryProcessor.java
@@ -17,6 +17,7 @@ package com.google.gerrit.server.query.account;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.account.AccountQueryBuilder.FIELD_LIMIT;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.query.AndSource;
import com.google.gerrit.index.query.IndexPredicate;
@@ -78,7 +79,9 @@ public class AccountQueryProcessor extends QueryProcessor<AccountState> {
@Override
protected Predicate<AccountState> enforceVisibility(Predicate<AccountState> pred) {
return new AndSource<>(
- pred, new AccountIsVisibleToPredicate(accountControlFactory.get()), start, indexConfig);
+ ImmutableList.of(pred, new AccountIsVisibleToPredicate(accountControlFactory.get())),
+ start,
+ indexConfig);
}
@Override
diff --git a/java/com/google/gerrit/server/query/change/AndChangeSource.java b/java/com/google/gerrit/server/query/change/AndChangeSource.java
index 98cada3d3a..e4f768ebcc 100644
--- a/java/com/google/gerrit/server/query/change/AndChangeSource.java
+++ b/java/com/google/gerrit/server/query/change/AndChangeSource.java
@@ -16,7 +16,6 @@ package com.google.gerrit.server.query.change;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.query.AndSource;
-import com.google.gerrit.index.query.IsVisibleToPredicate;
import com.google.gerrit.index.query.Predicate;
import java.util.Collection;
import java.util.List;
@@ -28,11 +27,8 @@ public class AndChangeSource extends AndSource<ChangeData> implements ChangeData
}
public AndChangeSource(
- Predicate<ChangeData> that,
- IsVisibleToPredicate<ChangeData> isVisibleToPredicate,
- int start,
- IndexConfig indexConfig) {
- super(that, isVisibleToPredicate, start, indexConfig);
+ Collection<Predicate<ChangeData>> that, int start, IndexConfig indexConfig) {
+ super(that, start, indexConfig);
}
@Override
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
index 0f0535a67a..b7dc127051 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
@@ -17,6 +17,7 @@ package com.google.gerrit.server.query.change;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.change.ChangeQueryBuilder.FIELD_LIMIT;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.gerrit.entities.Change;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
@@ -143,7 +144,9 @@ public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
@Override
protected Predicate<ChangeData> enforceVisibility(Predicate<ChangeData> pred) {
return new AndChangeSource(
- pred, changeIsVisibleToPredicateFactory.forUser(userProvider.get()), start, indexConfig);
+ ImmutableList.of(pred, changeIsVisibleToPredicateFactory.forUser(userProvider.get())),
+ start,
+ indexConfig);
}
@Override
diff --git a/java/com/google/gerrit/server/query/group/GroupQueryProcessor.java b/java/com/google/gerrit/server/query/group/GroupQueryProcessor.java
index c6683faa87..344a978e93 100644
--- a/java/com/google/gerrit/server/query/group/GroupQueryProcessor.java
+++ b/java/com/google/gerrit/server/query/group/GroupQueryProcessor.java
@@ -17,6 +17,7 @@ package com.google.gerrit.server.query.group;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.group.GroupQueryBuilder.FIELD_LIMIT;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.query.AndSource;
@@ -80,8 +81,8 @@ public class GroupQueryProcessor extends QueryProcessor<InternalGroup> {
@Override
protected Predicate<InternalGroup> enforceVisibility(Predicate<InternalGroup> pred) {
return new AndSource<>(
- pred,
- new GroupIsVisibleToPredicate(groupControlFactory, userProvider.get()),
+ ImmutableList.of(
+ pred, new GroupIsVisibleToPredicate(groupControlFactory, userProvider.get())),
start,
indexConfig);
}
diff --git a/java/com/google/gerrit/server/query/project/ProjectQueryProcessor.java b/java/com/google/gerrit/server/query/project/ProjectQueryProcessor.java
index 6dafa92289..3877c2546c 100644
--- a/java/com/google/gerrit/server/query/project/ProjectQueryProcessor.java
+++ b/java/com/google/gerrit/server/query/project/ProjectQueryProcessor.java
@@ -17,6 +17,7 @@ package com.google.gerrit.server.query.project;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.project.ProjectQueryBuilder.FIELD_LIMIT;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.project.ProjectData;
import com.google.gerrit.index.project.ProjectIndexCollection;
@@ -82,8 +83,8 @@ public class ProjectQueryProcessor extends QueryProcessor<ProjectData> {
@Override
protected Predicate<ProjectData> enforceVisibility(Predicate<ProjectData> pred) {
return new AndSource<>(
- pred,
- new ProjectIsVisibleToPredicate(permissionBackend, userProvider.get()),
+ ImmutableList.of(
+ pred, new ProjectIsVisibleToPredicate(permissionBackend, userProvider.get())),
start,
indexConfig);
}
diff --git a/java/com/google/gerrit/server/submit/RebaseSorter.java b/java/com/google/gerrit/server/submit/RebaseSorter.java
index 47757681fa..e960284d14 100644
--- a/java/com/google/gerrit/server/submit/RebaseSorter.java
+++ b/java/com/google/gerrit/server/submit/RebaseSorter.java
@@ -40,7 +40,7 @@ public class RebaseSorter {
private final CurrentUser caller;
private final CodeReviewRevWalk rw;
private final RevFlag canMergeFlag;
- private final RevCommit initialTip;
+ private final Set<RevCommit> uninterestingBranchTips;
private final Set<RevCommit> alreadyAccepted;
private final Provider<InternalChangeQuery> queryProvider;
private final Set<CodeReviewCommit> incoming;
@@ -48,7 +48,7 @@ public class RebaseSorter {
public RebaseSorter(
CurrentUser caller,
CodeReviewRevWalk rw,
- RevCommit initialTip,
+ Set<RevCommit> uninterestingBranchTips,
Set<RevCommit> alreadyAccepted,
RevFlag canMergeFlag,
Provider<InternalChangeQuery> queryProvider,
@@ -56,7 +56,7 @@ public class RebaseSorter {
this.caller = caller;
this.rw = rw;
this.canMergeFlag = canMergeFlag;
- this.initialTip = initialTip;
+ this.uninterestingBranchTips = uninterestingBranchTips;
this.alreadyAccepted = alreadyAccepted;
this.queryProvider = queryProvider;
this.incoming = incoming;
@@ -70,15 +70,16 @@ public class RebaseSorter {
rw.resetRetain(canMergeFlag);
rw.markStart(n);
- if (initialTip != null) {
- rw.markUninteresting(initialTip);
+ for (RevCommit uninterestingBranchTip : uninterestingBranchTips) {
+ rw.markUninteresting(uninterestingBranchTip);
}
CodeReviewCommit c;
final List<CodeReviewCommit> contents = new ArrayList<>();
while ((c = rw.next()) != null) {
if (!c.has(canMergeFlag) || !incoming.contains(c)) {
- if (isAlreadyMerged(c, n.change().getDest())) {
+ if (isMergedInBranchAsSubmittedChange(c, n.change().getDest())
+ || isAlreadyMergedInAnyBranch(c)) {
rw.markUninteresting(c);
} else {
// We cannot merge n as it would bring something we
@@ -108,7 +109,7 @@ public class RebaseSorter {
return sorted;
}
- private boolean isAlreadyMerged(CodeReviewCommit commit, BranchNameKey dest) throws IOException {
+ private boolean isAlreadyMergedInAnyBranch(CodeReviewCommit commit) throws IOException {
try (CodeReviewRevWalk mirw = CodeReviewCommit.newRevWalk(rw.getObjectReader())) {
mirw.reset();
mirw.markStart(commit);
@@ -120,22 +121,24 @@ public class RebaseSorter {
return true;
}
}
-
- // check if the commit associated change is merged in the same branch
- List<ChangeData> changes = queryProvider.get().byCommit(commit);
- for (ChangeData change : changes) {
- if (change.change().isMerged() && change.change().getDest().equals(dest)) {
- logger.atFine().log(
- "Dependency %s associated with merged change %s.", commit.getName(), change.getId());
- return true;
- }
- }
return false;
} catch (StorageException e) {
throw new IOException(e);
}
}
+ private boolean isMergedInBranchAsSubmittedChange(CodeReviewCommit commit, BranchNameKey dest) {
+ List<ChangeData> changes = queryProvider.get().byBranchCommit(dest, commit.getId().getName());
+ for (ChangeData change : changes) {
+ if (change.change().isMerged()) {
+ logger.atFine().log(
+ "Dependency %s associated with merged change %s.", commit.getName(), change.getId());
+ return true;
+ }
+ }
+ return false;
+ }
+
private static <T> T removeOne(Collection<T> c) {
final Iterator<T> i = c.iterator();
final T r = i.next();
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategy.java b/java/com/google/gerrit/server/submit/SubmitStrategy.java
index bdda3fc5dd..c7b322e118 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategy.java
@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.SubmissionId;
@@ -217,11 +218,18 @@ public abstract class SubmitStrategy {
projectCache.get(destBranch.project()).orElseThrow(illegalState(destBranch.project()));
this.mergeSorter =
new MergeSorter(caller, rw, alreadyAccepted, canMergeFlag, queryProvider, incoming);
+ Set<RevCommit> uninterestingBranchTips;
+ if (project.is(BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET)) {
+ RevCommit initialTip = mergeTip.getInitialTip();
+ uninterestingBranchTips = initialTip == null ? Set.of() : Set.of(initialTip);
+ } else {
+ uninterestingBranchTips = alreadyAccepted;
+ }
this.rebaseSorter =
new RebaseSorter(
caller,
rw,
- mergeTip.getInitialTip(),
+ uninterestingBranchTips,
alreadyAccepted,
canMergeFlag,
queryProvider,
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
index ef2ca95023..0d751f1156 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
@@ -461,17 +461,19 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
allowMatchingSubmoduleSubscription(subKey, "refs/heads/master", superKey, "refs/heads/master");
allowMatchingSubmoduleSubscription(subKey, "refs/heads/dev", superKey, "refs/heads/master");
- ObjectId devHead = pushChangeTo(subRepo, "dev");
+ ObjectId revMasterBranch = pushChangeTo(subRepo, "master");
+ ObjectId revDevBranch = pushChangeTo(subRepo, "dev");
Config config = new Config();
prepareSubmoduleConfigEntry(config, subKey, nameKey("sub-master"), "master");
prepareSubmoduleConfigEntry(config, subKey, nameKey("sub-dev"), "dev");
pushSubmoduleConfig(superRepo, "master", config);
+ subRepo.reset(revMasterBranch);
ObjectId subMasterId =
pushChangeTo(
subRepo, "refs/for/master", "some message", "b.txt", "content b", "same-topic");
- subRepo.reset(devHead);
+ subRepo.reset(revDevBranch);
ObjectId subDevId =
pushChangeTo(
subRepo, "refs/for/dev", "some message in dev", "b.txt", "content b", "same-topic");
@@ -673,14 +675,16 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
TestRepository<?> repoA = cloneProject(keyA);
TestRepository<?> repoB = cloneProject(keyB);
- // bootstrap the dev branch
- ObjectId a0 = pushChangeTo(repoA, "dev");
- // bootstrap the dev branch
- ObjectId b0 = pushChangeTo(repoB, "dev");
+ // Create master- and dev branches in both repositories
+ ObjectId revMasterBranchA = pushChangeTo(repoA, "master");
+ ObjectId revMasterBranchB = pushChangeTo(repoB, "master");
+ ObjectId revDevBranchA = pushChangeTo(repoA, "dev");
+ ObjectId revDevBranchB = pushChangeTo(repoB, "dev");
// create a change for master branch in repo a
- ObjectId aHead =
+ repoA.reset(revMasterBranchA);
+ ObjectId revMasterChangeA =
pushChangeTo(
repoA,
"refs/for/master",
@@ -690,7 +694,8 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"same-topic");
// create a change for master branch in repo b
- ObjectId bHead =
+ repoB.reset(revMasterBranchB);
+ ObjectId revMasterChangeB =
pushChangeTo(
repoB,
"refs/for/master",
@@ -700,8 +705,8 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"same-topic");
// create a change for dev branch in repo a
- repoA.reset(a0);
- ObjectId aDevHead =
+ repoA.reset(revDevBranchA);
+ ObjectId revDevChangeA =
pushChangeTo(
repoA,
"refs/for/dev",
@@ -711,8 +716,8 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"same-topic");
// create a change for dev branch in repo b
- repoB.reset(b0);
- ObjectId bDevHead =
+ repoB.reset(revDevBranchB);
+ ObjectId revDevChangeB =
pushChangeTo(
repoB,
"refs/for/dev",
@@ -721,12 +726,12 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"some message in b dev.txt",
"same-topic");
- approve(getChangeId(repoA, aHead).get());
- approve(getChangeId(repoB, bHead).get());
- approve(getChangeId(repoA, aDevHead).get());
- approve(getChangeId(repoB, bDevHead).get());
+ approve(getChangeId(repoA, revMasterChangeA).get());
+ approve(getChangeId(repoB, revMasterChangeB).get());
+ approve(getChangeId(repoA, revDevChangeA).get());
+ approve(getChangeId(repoB, revDevChangeB).get());
- gApi.changes().id(getChangeId(repoA, aDevHead).get()).current().submit();
+ gApi.changes().id(getChangeId(repoA, revDevChangeA).get()).current().submit();
assertThat(projectOperations.project(keyA).getHead("refs/heads/master").getShortMessage())
.contains("some message in a master.txt");
assertThat(projectOperations.project(keyA).getHead("refs/heads/dev").getShortMessage())
@@ -746,8 +751,9 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
// bootstrap the dev branch
pushChangeTo(repoA, "dev");
- // bootstrap the dev branch
- ObjectId b0 = pushChangeTo(repoB, "dev");
+ // Create master- and dev branches in repo b
+ ObjectId revMasterBranch = pushChangeTo(repoB, "master");
+ ObjectId revDevBranch = pushChangeTo(repoB, "dev");
allowMatchingSubmoduleSubscription(keyB, "refs/heads/master", keyA, "refs/heads/master");
allowMatchingSubmoduleSubscription(keyB, "refs/heads/dev", keyA, "refs/heads/dev");
@@ -756,7 +762,8 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
createSubmoduleSubscription(repoA, "dev", keyB, "dev");
// create a change for master branch in repo b
- ObjectId bHead =
+ repoB.reset(revMasterBranch);
+ ObjectId revMasterChange =
pushChangeTo(
repoB,
"refs/for/master",
@@ -766,8 +773,8 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"same-topic");
// create a change for dev branch in repo b
- repoB.reset(b0);
- ObjectId bDevHead =
+ repoB.reset(revDevBranch);
+ ObjectId revDevChange =
pushChangeTo(
repoB,
"refs/for/dev",
@@ -776,9 +783,9 @@ public class SubmoduleSubscriptionsWholeTopicMergeIT extends AbstractSubmoduleSu
"some message in b dev.txt",
"same-topic");
- approve(getChangeId(repoB, bHead).get());
- approve(getChangeId(repoB, bDevHead).get());
- gApi.changes().id(getChangeId(repoB, bHead).get()).current().submit();
+ approve(getChangeId(repoB, revMasterChange).get());
+ approve(getChangeId(repoB, revDevChange).get());
+ gApi.changes().id(getChangeId(repoB, revMasterChange).get()).current().submit();
expectToHaveSubmoduleState(repoA, "master", keyB, repoB, "master");
expectToHaveSubmoduleState(repoA, "dev", keyB, repoB, "dev");
diff --git a/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java b/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
index 8f2d613eff..0a874db28c 100644
--- a/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
+++ b/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
@@ -183,7 +183,7 @@ public class ExternalIDCacheLoaderTest {
public void handlesTreePrefixesInDifferentialReload() throws Exception {
// Create more than 256 notes (NoteMap's current sharding limit) and check that we really have
// created a situation where NoteNames are sharded.
- ObjectId oldState = inserExternalIds(257);
+ ObjectId oldState = insertExternalIds(257);
assertAllFilesHaveSlashesInPath();
ObjectId head = insertExternalId(500, 500);
externalIdCache.put(oldState, allFromGit(oldState));
@@ -196,7 +196,7 @@ public class ExternalIDCacheLoaderTest {
@Test
public void handlesReshard() throws Exception {
// Create 256 notes (NoteMap's current sharding limit) and check that we are not yet sharding
- ObjectId oldState = inserExternalIds(256);
+ ObjectId oldState = insertExternalIds(256);
assertNoFilesHaveSlashesInPath();
// Create one more external ID and then have the Loader compute the new state
ObjectId head = insertExternalId(500, 500);
@@ -223,7 +223,7 @@ public class ExternalIDCacheLoaderTest {
return AllExternalIds.create(externalIdReader.all(revision).stream());
}
- private ObjectId inserExternalIds(int numberOfIdsToInsert) throws Exception {
+ private ObjectId insertExternalIds(int numberOfIdsToInsert) throws Exception {
ObjectId oldState = null;
// Create more than 256 notes (NoteMap's current sharding limit) and check that we really have
// created a situation where NoteNames are sharded.
diff --git a/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html b/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html
index 593ea45556..08c890d381 100644
--- a/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html
+++ b/resources/com/google/gerrit/httpd/auth/ldap/LoginForm.html
@@ -43,6 +43,7 @@
<input name="rememberme" id="f_remember"
type="checkbox"
value="1"
+ checked="checked"
tabindex="3" />
<label for="f_remember">Remember me</label>
</td>