diff options
author | Luca Milanesio <luca.milanesio@gmail.com> | 2023-04-22 17:20:53 -0700 |
---|---|---|
committer | Luca Milanesio <luca.milanesio@gmail.com> | 2023-04-22 17:32:53 -0700 |
commit | 9978b91a581d5f91c8b57cf708144f60ccd5ed36 (patch) | |
tree | 2b93673a03e8e6716c7074e588eff238b5f60801 | |
parent | 1626b4358e2de41e7b267088da0845d1b6f01161 (diff) | |
parent | 686fb694cd7ff696e40e3e3b37b5c378ce6fdcc2 (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
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> |