Merge changes Ie5d1b547,Ib623ce65,Ie1ab3bfa,I66ed2bd8,Ib320b0ed, ...
* changes: MergeOp: Use factories of the subscription components MergeOp: Pass the specific objects, instead of submoduleOp SubmoduleOp: Move subscription graph instantiation to its own factory UpdateOrderCalculator: Move update order calculation out of submoduleOp SubmoduleCommits: Define its own guice factory GitlinkOp: Move it to its own class and factory
This commit is contained in:
@@ -187,9 +187,11 @@ import com.google.gerrit.server.rules.PrologModule;
|
|||||||
import com.google.gerrit.server.rules.RulesCache;
|
import com.google.gerrit.server.rules.RulesCache;
|
||||||
import com.google.gerrit.server.rules.SubmitRule;
|
import com.google.gerrit.server.rules.SubmitRule;
|
||||||
import com.google.gerrit.server.ssh.SshAddressesModule;
|
import com.google.gerrit.server.ssh.SshAddressesModule;
|
||||||
|
import com.google.gerrit.server.submit.ConfiguredSubscriptionGraphFactory;
|
||||||
import com.google.gerrit.server.submit.GitModules;
|
import com.google.gerrit.server.submit.GitModules;
|
||||||
import com.google.gerrit.server.submit.MergeSuperSetComputation;
|
import com.google.gerrit.server.submit.MergeSuperSetComputation;
|
||||||
import com.google.gerrit.server.submit.SubmitStrategy;
|
import com.google.gerrit.server.submit.SubmitStrategy;
|
||||||
|
import com.google.gerrit.server.submit.SubscriptionGraph;
|
||||||
import com.google.gerrit.server.tools.ToolsCatalog;
|
import com.google.gerrit.server.tools.ToolsCatalog;
|
||||||
import com.google.gerrit.server.update.BatchUpdate;
|
import com.google.gerrit.server.update.BatchUpdate;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
@@ -453,6 +455,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
factory(VersionedAuthorizedKeys.Factory.class);
|
factory(VersionedAuthorizedKeys.Factory.class);
|
||||||
|
|
||||||
bind(AccountManager.class);
|
bind(AccountManager.class);
|
||||||
|
bind(SubscriptionGraph.Factory.class).to(ConfiguredSubscriptionGraphFactory.class);
|
||||||
|
|
||||||
bind(new TypeLiteral<List<CommentLinkInfo>>() {}).toProvider(CommentLinkProvider.class);
|
bind(new TypeLiteral<List<CommentLinkInfo>>() {}).toProvider(CommentLinkProvider.class);
|
||||||
DynamicSet.bind(binder(), GerritConfigListener.class).to(CommentLinkProvider.class);
|
DynamicSet.bind(binder(), GerritConfigListener.class).to(CommentLinkProvider.class);
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (C) 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.submit;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
import com.google.gerrit.entities.BranchNameKey;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a (@link {@link SubscriptionGraph.Factory} to honor the gerrit configuration.
|
||||||
|
*
|
||||||
|
* <p>If superproject subscriptions are disabled in the conf, return an empty graph.
|
||||||
|
*/
|
||||||
|
public class ConfiguredSubscriptionGraphFactory implements SubscriptionGraph.Factory {
|
||||||
|
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
|
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
||||||
|
private final Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ConfiguredSubscriptionGraphFactory(
|
||||||
|
@VanillaSubscriptionGraph SubscriptionGraph.Factory subscriptionGraphFactory,
|
||||||
|
@GerritServerConfig Config cfg) {
|
||||||
|
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubscriptionGraph compute(Set<BranchNameKey> updatedBranches, MergeOpRepoManager orm)
|
||||||
|
throws SubmoduleConflictException {
|
||||||
|
if (cfg.getBoolean("submodule", "enableSuperProjectSubscriptions", true)) {
|
||||||
|
return subscriptionGraphFactory.compute(updatedBranches, orm);
|
||||||
|
} else {
|
||||||
|
logger.atFine().log("Updating superprojects disabled");
|
||||||
|
return SubscriptionGraph.createEmptyGraph(ImmutableSet.copyOf(updatedBranches));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
64
java/com/google/gerrit/server/submit/GitlinkOp.java
Normal file
64
java/com/google/gerrit/server/submit/GitlinkOp.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (C) 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.submit;
|
||||||
|
|
||||||
|
import com.google.gerrit.entities.BranchNameKey;
|
||||||
|
import com.google.gerrit.entities.SubmoduleSubscription;
|
||||||
|
import com.google.gerrit.server.git.CodeReviewCommit;
|
||||||
|
import com.google.gerrit.server.update.RepoContext;
|
||||||
|
import com.google.gerrit.server.update.RepoOnlyOp;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/** Only used for branches without code review changes */
|
||||||
|
public class GitlinkOp implements RepoOnlyOp {
|
||||||
|
|
||||||
|
static class Factory {
|
||||||
|
private SubmoduleCommits submoduleCommits;
|
||||||
|
private SubscriptionGraph subscriptionGraph;
|
||||||
|
|
||||||
|
Factory(SubmoduleCommits submoduleCommits, SubscriptionGraph subscriptionGraph) {
|
||||||
|
this.submoduleCommits = submoduleCommits;
|
||||||
|
this.subscriptionGraph = subscriptionGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
GitlinkOp create(BranchNameKey branch) {
|
||||||
|
return new GitlinkOp(branch, submoduleCommits, subscriptionGraph.getSubscriptions(branch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BranchNameKey branch;
|
||||||
|
private final SubmoduleCommits commitHelper;
|
||||||
|
private final Collection<SubmoduleSubscription> branchTargets;
|
||||||
|
|
||||||
|
GitlinkOp(
|
||||||
|
BranchNameKey branch,
|
||||||
|
SubmoduleCommits commitHelper,
|
||||||
|
Collection<SubmoduleSubscription> branchTargets) {
|
||||||
|
this.branch = branch;
|
||||||
|
this.commitHelper = commitHelper;
|
||||||
|
this.branchTargets = branchTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateRepo(RepoContext ctx) throws Exception {
|
||||||
|
Optional<CodeReviewCommit> commit = commitHelper.composeGitlinksCommit(branch, branchTargets);
|
||||||
|
if (commit.isPresent()) {
|
||||||
|
CodeReviewCommit c = commit.get();
|
||||||
|
ctx.addRefUpdate(c.getParent(0), c, branch.branch());
|
||||||
|
commitHelper.addBranchTip(branch, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -226,7 +226,9 @@ public class MergeOp implements AutoCloseable {
|
|||||||
private final MergeValidators.Factory mergeValidatorsFactory;
|
private final MergeValidators.Factory mergeValidatorsFactory;
|
||||||
private final Provider<InternalChangeQuery> queryProvider;
|
private final Provider<InternalChangeQuery> queryProvider;
|
||||||
private final SubmitStrategyFactory submitStrategyFactory;
|
private final SubmitStrategyFactory submitStrategyFactory;
|
||||||
|
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
||||||
private final SubmoduleOp.Factory subOpFactory;
|
private final SubmoduleOp.Factory subOpFactory;
|
||||||
|
private final SubmoduleCommits.Factory submoduleCommitsFactory;
|
||||||
private final Provider<MergeOpRepoManager> ormProvider;
|
private final Provider<MergeOpRepoManager> ormProvider;
|
||||||
private final NotifyResolver notifyResolver;
|
private final NotifyResolver notifyResolver;
|
||||||
private final RetryHelper retryHelper;
|
private final RetryHelper retryHelper;
|
||||||
@@ -256,6 +258,8 @@ public class MergeOp implements AutoCloseable {
|
|||||||
MergeValidators.Factory mergeValidatorsFactory,
|
MergeValidators.Factory mergeValidatorsFactory,
|
||||||
Provider<InternalChangeQuery> queryProvider,
|
Provider<InternalChangeQuery> queryProvider,
|
||||||
SubmitStrategyFactory submitStrategyFactory,
|
SubmitStrategyFactory submitStrategyFactory,
|
||||||
|
SubmoduleCommits.Factory submoduleCommitsFactory,
|
||||||
|
SubscriptionGraph.Factory subscriptionGraphFactory,
|
||||||
SubmoduleOp.Factory subOpFactory,
|
SubmoduleOp.Factory subOpFactory,
|
||||||
Provider<MergeOpRepoManager> ormProvider,
|
Provider<MergeOpRepoManager> ormProvider,
|
||||||
NotifyResolver notifyResolver,
|
NotifyResolver notifyResolver,
|
||||||
@@ -269,6 +273,8 @@ public class MergeOp implements AutoCloseable {
|
|||||||
this.mergeValidatorsFactory = mergeValidatorsFactory;
|
this.mergeValidatorsFactory = mergeValidatorsFactory;
|
||||||
this.queryProvider = queryProvider;
|
this.queryProvider = queryProvider;
|
||||||
this.submitStrategyFactory = submitStrategyFactory;
|
this.submitStrategyFactory = submitStrategyFactory;
|
||||||
|
this.submoduleCommitsFactory = submoduleCommitsFactory;
|
||||||
|
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
||||||
this.subOpFactory = subOpFactory;
|
this.subOpFactory = subOpFactory;
|
||||||
this.ormProvider = ormProvider;
|
this.ormProvider = ormProvider;
|
||||||
this.notifyResolver = notifyResolver;
|
this.notifyResolver = notifyResolver;
|
||||||
@@ -605,9 +611,13 @@ public class MergeOp implements AutoCloseable {
|
|||||||
commitStatus.maybeFailVerbose();
|
commitStatus.maybeFailVerbose();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SubmoduleOp submoduleOp = subOpFactory.create(branches, orm);
|
SubscriptionGraph subscriptionGraph = subscriptionGraphFactory.compute(branches, orm);
|
||||||
List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, submoduleOp, dryrun);
|
SubmoduleCommits submoduleCommits = submoduleCommitsFactory.create(orm);
|
||||||
this.allProjects = submoduleOp.getProjectsInOrder();
|
UpdateOrderCalculator updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph);
|
||||||
|
List<SubmitStrategy> strategies =
|
||||||
|
getSubmitStrategies(
|
||||||
|
toSubmit, updateOrderCalculator, submoduleCommits, subscriptionGraph, dryrun);
|
||||||
|
this.allProjects = updateOrderCalculator.getProjectsInOrder();
|
||||||
try {
|
try {
|
||||||
BatchUpdate.execute(
|
BatchUpdate.execute(
|
||||||
orm.batchUpdates(allProjects),
|
orm.batchUpdates(allProjects),
|
||||||
@@ -658,12 +668,19 @@ public class MergeOp implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<SubmitStrategy> getSubmitStrategies(
|
private List<SubmitStrategy> getSubmitStrategies(
|
||||||
Map<BranchNameKey, BranchBatch> toSubmit, SubmoduleOp submoduleOp, boolean dryrun)
|
Map<BranchNameKey, BranchBatch> toSubmit,
|
||||||
|
UpdateOrderCalculator updateOrderCalculator,
|
||||||
|
SubmoduleCommits submoduleCommits,
|
||||||
|
SubscriptionGraph subscriptionGraph,
|
||||||
|
boolean dryrun)
|
||||||
throws IntegrationConflictException, NoSuchProjectException, IOException {
|
throws IntegrationConflictException, NoSuchProjectException, IOException {
|
||||||
List<SubmitStrategy> strategies = new ArrayList<>();
|
List<SubmitStrategy> strategies = new ArrayList<>();
|
||||||
Set<BranchNameKey> allBranches = submoduleOp.getBranchesInOrder();
|
Set<BranchNameKey> allBranches = updateOrderCalculator.getBranchesInOrder();
|
||||||
Set<CodeReviewCommit> allCommits =
|
Set<CodeReviewCommit> allCommits =
|
||||||
toSubmit.values().stream().map(BranchBatch::commits).flatMap(Set::stream).collect(toSet());
|
toSubmit.values().stream().map(BranchBatch::commits).flatMap(Set::stream).collect(toSet());
|
||||||
|
|
||||||
|
GitlinkOp.Factory gitlinkOpFactory = new GitlinkOp.Factory(submoduleCommits, subscriptionGraph);
|
||||||
|
|
||||||
for (BranchNameKey branch : allBranches) {
|
for (BranchNameKey branch : allBranches) {
|
||||||
OpenRepo or = orm.getRepo(branch.project());
|
OpenRepo or = orm.getRepo(branch.project());
|
||||||
if (toSubmit.containsKey(branch)) {
|
if (toSubmit.containsKey(branch)) {
|
||||||
@@ -688,19 +705,19 @@ public class MergeOp implements AutoCloseable {
|
|||||||
commitStatus,
|
commitStatus,
|
||||||
submissionId,
|
submissionId,
|
||||||
submitInput,
|
submitInput,
|
||||||
submoduleOp.getSubmoduleCommits(),
|
submoduleCommits,
|
||||||
submoduleOp.getSubscriptionGraph(),
|
subscriptionGraph,
|
||||||
dryrun);
|
dryrun);
|
||||||
strategies.add(strategy);
|
strategies.add(strategy);
|
||||||
strategy.addOps(or.getUpdate(), commitsToSubmit);
|
strategy.addOps(or.getUpdate(), commitsToSubmit);
|
||||||
if (submitting.submitType().equals(SubmitType.FAST_FORWARD_ONLY)
|
if (submitting.submitType().equals(SubmitType.FAST_FORWARD_ONLY)
|
||||||
&& submoduleOp.getSubscriptionGraph().hasSubscription(branch)) {
|
&& subscriptionGraph.hasSubscription(branch)) {
|
||||||
submoduleOp.addOp(or.getUpdate(), branch);
|
or.getUpdate().addRepoOnlyOp(gitlinkOpFactory.create(branch));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no open change for this branch
|
// no open change for this branch
|
||||||
// add submodule triggered op into BatchUpdate
|
// add submodule triggered op into BatchUpdate
|
||||||
submoduleOp.addOp(or.getUpdate(), branch);
|
or.getUpdate().addRepoOnlyOp(gitlinkOpFactory.create(branch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strategies;
|
return strategies;
|
||||||
|
|||||||
@@ -21,10 +21,15 @@ import com.google.common.flogger.FluentLogger;
|
|||||||
import com.google.gerrit.entities.BranchNameKey;
|
import com.google.gerrit.entities.BranchNameKey;
|
||||||
import com.google.gerrit.entities.SubmoduleSubscription;
|
import com.google.gerrit.entities.SubmoduleSubscription;
|
||||||
import com.google.gerrit.exceptions.StorageException;
|
import com.google.gerrit.exceptions.StorageException;
|
||||||
|
import com.google.gerrit.server.GerritPersonIdent;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.config.VerboseSuperprojectUpdate;
|
import com.google.gerrit.server.config.VerboseSuperprojectUpdate;
|
||||||
import com.google.gerrit.server.git.CodeReviewCommit;
|
import com.google.gerrit.server.git.CodeReviewCommit;
|
||||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
|
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -58,6 +63,22 @@ class SubmoduleCommits {
|
|||||||
private final long maxCommitMessages;
|
private final long maxCommitMessages;
|
||||||
private final BranchTips branchTips = new BranchTips();
|
private final BranchTips branchTips = new BranchTips();
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class Factory {
|
||||||
|
private final Provider<PersonIdent> serverIdent;
|
||||||
|
private final Config cfg;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Factory(@GerritPersonIdent Provider<PersonIdent> serverIdent, @GerritServerConfig Config cfg) {
|
||||||
|
this.serverIdent = serverIdent;
|
||||||
|
this.cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmoduleCommits create(MergeOpRepoManager orm) {
|
||||||
|
return new SubmoduleCommits(orm, serverIdent.get(), cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SubmoduleCommits(MergeOpRepoManager orm, PersonIdent myIdent, Config cfg) {
|
SubmoduleCommits(MergeOpRepoManager orm, PersonIdent myIdent, Config cfg) {
|
||||||
this.orm = orm;
|
this.orm = orm;
|
||||||
this.myIdent = myIdent;
|
this.myIdent = myIdent;
|
||||||
|
|||||||
@@ -15,116 +15,59 @@
|
|||||||
package com.google.gerrit.server.submit;
|
package com.google.gerrit.server.submit;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.flogger.FluentLogger;
|
|
||||||
import com.google.gerrit.common.UsedAt;
|
import com.google.gerrit.common.UsedAt;
|
||||||
import com.google.gerrit.entities.BranchNameKey;
|
import com.google.gerrit.entities.BranchNameKey;
|
||||||
import com.google.gerrit.entities.Project;
|
import com.google.gerrit.entities.Project;
|
||||||
import com.google.gerrit.entities.SubmoduleSubscription;
|
|
||||||
import com.google.gerrit.exceptions.StorageException;
|
import com.google.gerrit.exceptions.StorageException;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||||
import com.google.gerrit.server.GerritPersonIdent;
|
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
|
||||||
import com.google.gerrit.server.git.CodeReviewCommit;
|
|
||||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
|
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
|
||||||
import com.google.gerrit.server.update.BatchUpdate;
|
import com.google.gerrit.server.update.BatchUpdate;
|
||||||
import com.google.gerrit.server.update.BatchUpdateListener;
|
import com.google.gerrit.server.update.BatchUpdateListener;
|
||||||
import com.google.gerrit.server.update.RepoContext;
|
|
||||||
import com.google.gerrit.server.update.RepoOnlyOp;
|
|
||||||
import com.google.gerrit.server.update.UpdateException;
|
import com.google.gerrit.server.update.UpdateException;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.eclipse.jgit.lib.Config;
|
|
||||||
import org.eclipse.jgit.lib.PersonIdent;
|
|
||||||
|
|
||||||
public class SubmoduleOp {
|
public class SubmoduleOp {
|
||||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
|
||||||
|
|
||||||
/** Only used for branches without code review changes */
|
|
||||||
public static class GitlinkOp implements RepoOnlyOp {
|
|
||||||
private final BranchNameKey branch;
|
|
||||||
private final SubmoduleCommits commitHelper;
|
|
||||||
private final Collection<SubmoduleSubscription> branchTargets;
|
|
||||||
|
|
||||||
GitlinkOp(
|
|
||||||
BranchNameKey branch,
|
|
||||||
SubmoduleCommits commitHelper,
|
|
||||||
Collection<SubmoduleSubscription> branchTargets) {
|
|
||||||
this.branch = branch;
|
|
||||||
this.commitHelper = commitHelper;
|
|
||||||
this.branchTargets = branchTargets;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateRepo(RepoContext ctx) throws Exception {
|
|
||||||
Optional<CodeReviewCommit> commit = commitHelper.composeGitlinksCommit(branch, branchTargets);
|
|
||||||
if (commit.isPresent()) {
|
|
||||||
CodeReviewCommit c = commit.get();
|
|
||||||
ctx.addRefUpdate(c.getParent(0), c, branch.branch());
|
|
||||||
commitHelper.addBranchTip(branch, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class Factory {
|
public static class Factory {
|
||||||
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
||||||
private final Provider<PersonIdent> serverIdent;
|
private final SubmoduleCommits.Factory submoduleCommitsFactory;
|
||||||
private final Config cfg;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Factory(
|
Factory(
|
||||||
SubscriptionGraph.Factory subscriptionGraphFactory,
|
SubscriptionGraph.Factory subscriptionGraphFactory,
|
||||||
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
SubmoduleCommits.Factory submoduleCommitsFactory) {
|
||||||
@GerritServerConfig Config cfg) {
|
|
||||||
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
||||||
this.serverIdent = serverIdent;
|
this.submoduleCommitsFactory = submoduleCommitsFactory;
|
||||||
this.cfg = cfg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubmoduleOp create(Set<BranchNameKey> updatedBranches, MergeOpRepoManager orm)
|
public SubmoduleOp create(Set<BranchNameKey> updatedBranches, MergeOpRepoManager orm)
|
||||||
throws SubmoduleConflictException {
|
throws SubmoduleConflictException {
|
||||||
SubscriptionGraph subscriptionGraph;
|
return new SubmoduleOp(
|
||||||
if (cfg.getBoolean("submodule", "enableSuperProjectSubscriptions", true)) {
|
orm,
|
||||||
subscriptionGraph = subscriptionGraphFactory.compute(updatedBranches, orm);
|
subscriptionGraphFactory.compute(updatedBranches, orm),
|
||||||
} else {
|
submoduleCommitsFactory.create(orm));
|
||||||
logger.atFine().log("Updating superprojects disabled");
|
|
||||||
subscriptionGraph =
|
|
||||||
SubscriptionGraph.createEmptyGraph(ImmutableSet.copyOf(updatedBranches));
|
|
||||||
}
|
|
||||||
return new SubmoduleOp(serverIdent.get(), cfg, orm, subscriptionGraph);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final MergeOpRepoManager orm;
|
private final MergeOpRepoManager orm;
|
||||||
private final SubscriptionGraph subscriptionGraph;
|
private final SubscriptionGraph subscriptionGraph;
|
||||||
private final SubmoduleCommits submoduleCommits;
|
private final SubmoduleCommits submoduleCommits;
|
||||||
|
private final UpdateOrderCalculator updateOrderCalculator;
|
||||||
|
|
||||||
private SubmoduleOp(
|
private SubmoduleOp(
|
||||||
PersonIdent myIdent,
|
|
||||||
Config cfg,
|
|
||||||
MergeOpRepoManager orm,
|
MergeOpRepoManager orm,
|
||||||
SubscriptionGraph subscriptionGraph) {
|
SubscriptionGraph subscriptionGraph,
|
||||||
|
SubmoduleCommits submoduleCommits) {
|
||||||
this.orm = orm;
|
this.orm = orm;
|
||||||
this.subscriptionGraph = subscriptionGraph;
|
this.subscriptionGraph = subscriptionGraph;
|
||||||
this.submoduleCommits = new SubmoduleCommits(orm, myIdent, cfg);
|
this.submoduleCommits = submoduleCommits;
|
||||||
}
|
this.updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph);
|
||||||
|
|
||||||
// TODO(ifrade): subscription graph should be instantiated somewhere else and passed to
|
|
||||||
// SubmoduleOp
|
|
||||||
SubscriptionGraph getSubscriptionGraph() {
|
|
||||||
return subscriptionGraph;
|
|
||||||
}
|
|
||||||
|
|
||||||
SubmoduleCommits getSubmoduleCommits() {
|
|
||||||
return submoduleCommits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
|
@UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
|
||||||
@@ -133,13 +76,15 @@ public class SubmoduleOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateSuperProjects() throws RestApiException {
|
public void updateSuperProjects() throws RestApiException {
|
||||||
ImmutableSet<Project.NameKey> projects = getProjectsInOrder();
|
ImmutableSet<Project.NameKey> projects = updateOrderCalculator.getProjectsInOrder();
|
||||||
if (projects == null) {
|
if (projects == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedHashSet<Project.NameKey> superProjects = new LinkedHashSet<>();
|
LinkedHashSet<Project.NameKey> superProjects = new LinkedHashSet<>();
|
||||||
try {
|
try {
|
||||||
|
GitlinkOp.Factory gitlinkOpFactory =
|
||||||
|
new GitlinkOp.Factory(submoduleCommits, subscriptionGraph);
|
||||||
for (Project.NameKey project : projects) {
|
for (Project.NameKey project : projects) {
|
||||||
// only need superprojects
|
// only need superprojects
|
||||||
if (subscriptionGraph.isAffectedSuperProject(project)) {
|
if (subscriptionGraph.isAffectedSuperProject(project)) {
|
||||||
@@ -147,7 +92,7 @@ public class SubmoduleOp {
|
|||||||
// get a new BatchUpdate for the super project
|
// get a new BatchUpdate for the super project
|
||||||
OpenRepo or = orm.getRepo(project);
|
OpenRepo or = orm.getRepo(project);
|
||||||
for (BranchNameKey branch : subscriptionGraph.getAffectedSuperBranches(project)) {
|
for (BranchNameKey branch : subscriptionGraph.getAffectedSuperBranches(project)) {
|
||||||
addOp(or.getUpdate(), branch);
|
or.getUpdate().addRepoOnlyOp(gitlinkOpFactory.create(branch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,60 +101,4 @@ public class SubmoduleOp {
|
|||||||
throw new StorageException("Cannot update gitlinks", e);
|
throw new StorageException("Cannot update gitlinks", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableSet<Project.NameKey> getProjectsInOrder() throws SubmoduleConflictException {
|
|
||||||
LinkedHashSet<Project.NameKey> projects = new LinkedHashSet<>();
|
|
||||||
for (Project.NameKey project : subscriptionGraph.getAffectedSuperProjects()) {
|
|
||||||
addAllSubmoduleProjects(project, new LinkedHashSet<>(), projects);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BranchNameKey branch : subscriptionGraph.getUpdatedBranches()) {
|
|
||||||
projects.add(branch.project());
|
|
||||||
}
|
|
||||||
return ImmutableSet.copyOf(projects);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAllSubmoduleProjects(
|
|
||||||
Project.NameKey project,
|
|
||||||
LinkedHashSet<Project.NameKey> current,
|
|
||||||
LinkedHashSet<Project.NameKey> projects)
|
|
||||||
throws SubmoduleConflictException {
|
|
||||||
if (current.contains(project)) {
|
|
||||||
throw new SubmoduleConflictException(
|
|
||||||
"Project level circular subscriptions detected: "
|
|
||||||
+ CircularPathFinder.printCircularPath(current, project));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (projects.contains(project)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
current.add(project);
|
|
||||||
Set<Project.NameKey> subprojects = new HashSet<>();
|
|
||||||
for (BranchNameKey branch : subscriptionGraph.getAffectedSuperBranches(project)) {
|
|
||||||
Collection<SubmoduleSubscription> subscriptions = subscriptionGraph.getSubscriptions(branch);
|
|
||||||
for (SubmoduleSubscription s : subscriptions) {
|
|
||||||
subprojects.add(s.getSubmodule().project());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Project.NameKey p : subprojects) {
|
|
||||||
addAllSubmoduleProjects(p, current, projects);
|
|
||||||
}
|
|
||||||
|
|
||||||
current.remove(project);
|
|
||||||
projects.add(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableSet<BranchNameKey> getBranchesInOrder() {
|
|
||||||
LinkedHashSet<BranchNameKey> branches = new LinkedHashSet<>();
|
|
||||||
branches.addAll(subscriptionGraph.getSortedSuperprojectAndSubmoduleBranches());
|
|
||||||
branches.addAll(subscriptionGraph.getUpdatedBranches());
|
|
||||||
return ImmutableSet.copyOf(branches);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addOp(BatchUpdate bu, BranchNameKey branch) {
|
|
||||||
bu.addRepoOnlyOp(
|
|
||||||
new GitlinkOp(branch, submoduleCommits, subscriptionGraph.getSubscriptions(branch)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public class SubscriptionGraph {
|
|||||||
public static class Module extends AbstractModule {
|
public static class Module extends AbstractModule {
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(Factory.class).to(DefaultFactory.class);
|
bind(Factory.class).annotatedWith(VanillaSubscriptionGraph.class).to(DefaultFactory.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
// Copyright (C) 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.submit;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.gerrit.entities.BranchNameKey;
|
||||||
|
import com.google.gerrit.entities.Project;
|
||||||
|
import com.google.gerrit.entities.SubmoduleSubscription;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts the projects or branches affected by the update.
|
||||||
|
*
|
||||||
|
* <p>The subscription graph contains all branches (and projects) affected by the update, but the
|
||||||
|
* updates must be executed in the right order, so no superproject reference is updated before its
|
||||||
|
* target.
|
||||||
|
*/
|
||||||
|
class UpdateOrderCalculator {
|
||||||
|
|
||||||
|
private final SubscriptionGraph subscriptionGraph;
|
||||||
|
|
||||||
|
UpdateOrderCalculator(SubscriptionGraph subscriptionGraph) {
|
||||||
|
this.subscriptionGraph = subscriptionGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet<Project.NameKey> getProjectsInOrder() throws SubmoduleConflictException {
|
||||||
|
LinkedHashSet<Project.NameKey> projects = new LinkedHashSet<>();
|
||||||
|
for (Project.NameKey project : subscriptionGraph.getAffectedSuperProjects()) {
|
||||||
|
addAllSubmoduleProjects(project, new LinkedHashSet<>(), projects);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BranchNameKey branch : subscriptionGraph.getUpdatedBranches()) {
|
||||||
|
projects.add(branch.project());
|
||||||
|
}
|
||||||
|
return ImmutableSet.copyOf(projects);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAllSubmoduleProjects(
|
||||||
|
Project.NameKey project,
|
||||||
|
LinkedHashSet<Project.NameKey> current,
|
||||||
|
LinkedHashSet<Project.NameKey> projects)
|
||||||
|
throws SubmoduleConflictException {
|
||||||
|
if (current.contains(project)) {
|
||||||
|
throw new SubmoduleConflictException(
|
||||||
|
"Project level circular subscriptions detected: "
|
||||||
|
+ CircularPathFinder.printCircularPath(current, project));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projects.contains(project)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.add(project);
|
||||||
|
Set<Project.NameKey> subprojects = new HashSet<>();
|
||||||
|
for (BranchNameKey branch : subscriptionGraph.getAffectedSuperBranches(project)) {
|
||||||
|
Collection<SubmoduleSubscription> subscriptions = subscriptionGraph.getSubscriptions(branch);
|
||||||
|
for (SubmoduleSubscription s : subscriptions) {
|
||||||
|
subprojects.add(s.getSubmodule().project());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Project.NameKey p : subprojects) {
|
||||||
|
addAllSubmoduleProjects(p, current, projects);
|
||||||
|
}
|
||||||
|
|
||||||
|
current.remove(project);
|
||||||
|
projects.add(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet<BranchNameKey> getBranchesInOrder() {
|
||||||
|
LinkedHashSet<BranchNameKey> branches = new LinkedHashSet<>();
|
||||||
|
branches.addAll(subscriptionGraph.getSortedSuperprojectAndSubmoduleBranches());
|
||||||
|
branches.addAll(subscriptionGraph.getUpdatedBranches());
|
||||||
|
return ImmutableSet.copyOf(branches);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.submit;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import com.google.inject.BindingAnnotation;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marker on a {@link SubscriptionGraph.Factory} without gerrit configuration.
|
||||||
|
*
|
||||||
|
* <p>See {@link ConfiguredSubscriptionGraphFactory}.
|
||||||
|
*/
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@BindingAnnotation
|
||||||
|
public @interface VanillaSubscriptionGraph {}
|
||||||
Reference in New Issue
Block a user