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.SubmitRule;
|
||||
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.MergeSuperSetComputation;
|
||||
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.update.BatchUpdate;
|
||||
import com.google.gerrit.server.util.IdGenerator;
|
||||
@@ -453,6 +455,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
factory(VersionedAuthorizedKeys.Factory.class);
|
||||
|
||||
bind(AccountManager.class);
|
||||
bind(SubscriptionGraph.Factory.class).to(ConfiguredSubscriptionGraphFactory.class);
|
||||
|
||||
bind(new TypeLiteral<List<CommentLinkInfo>>() {}).toProvider(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 Provider<InternalChangeQuery> queryProvider;
|
||||
private final SubmitStrategyFactory submitStrategyFactory;
|
||||
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
||||
private final SubmoduleOp.Factory subOpFactory;
|
||||
private final SubmoduleCommits.Factory submoduleCommitsFactory;
|
||||
private final Provider<MergeOpRepoManager> ormProvider;
|
||||
private final NotifyResolver notifyResolver;
|
||||
private final RetryHelper retryHelper;
|
||||
@@ -256,6 +258,8 @@ public class MergeOp implements AutoCloseable {
|
||||
MergeValidators.Factory mergeValidatorsFactory,
|
||||
Provider<InternalChangeQuery> queryProvider,
|
||||
SubmitStrategyFactory submitStrategyFactory,
|
||||
SubmoduleCommits.Factory submoduleCommitsFactory,
|
||||
SubscriptionGraph.Factory subscriptionGraphFactory,
|
||||
SubmoduleOp.Factory subOpFactory,
|
||||
Provider<MergeOpRepoManager> ormProvider,
|
||||
NotifyResolver notifyResolver,
|
||||
@@ -269,6 +273,8 @@ public class MergeOp implements AutoCloseable {
|
||||
this.mergeValidatorsFactory = mergeValidatorsFactory;
|
||||
this.queryProvider = queryProvider;
|
||||
this.submitStrategyFactory = submitStrategyFactory;
|
||||
this.submoduleCommitsFactory = submoduleCommitsFactory;
|
||||
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
||||
this.subOpFactory = subOpFactory;
|
||||
this.ormProvider = ormProvider;
|
||||
this.notifyResolver = notifyResolver;
|
||||
@@ -605,9 +611,13 @@ public class MergeOp implements AutoCloseable {
|
||||
commitStatus.maybeFailVerbose();
|
||||
|
||||
try {
|
||||
SubmoduleOp submoduleOp = subOpFactory.create(branches, orm);
|
||||
List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, submoduleOp, dryrun);
|
||||
this.allProjects = submoduleOp.getProjectsInOrder();
|
||||
SubscriptionGraph subscriptionGraph = subscriptionGraphFactory.compute(branches, orm);
|
||||
SubmoduleCommits submoduleCommits = submoduleCommitsFactory.create(orm);
|
||||
UpdateOrderCalculator updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph);
|
||||
List<SubmitStrategy> strategies =
|
||||
getSubmitStrategies(
|
||||
toSubmit, updateOrderCalculator, submoduleCommits, subscriptionGraph, dryrun);
|
||||
this.allProjects = updateOrderCalculator.getProjectsInOrder();
|
||||
try {
|
||||
BatchUpdate.execute(
|
||||
orm.batchUpdates(allProjects),
|
||||
@@ -658,12 +668,19 @@ public class MergeOp implements AutoCloseable {
|
||||
}
|
||||
|
||||
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 {
|
||||
List<SubmitStrategy> strategies = new ArrayList<>();
|
||||
Set<BranchNameKey> allBranches = submoduleOp.getBranchesInOrder();
|
||||
Set<BranchNameKey> allBranches = updateOrderCalculator.getBranchesInOrder();
|
||||
Set<CodeReviewCommit> allCommits =
|
||||
toSubmit.values().stream().map(BranchBatch::commits).flatMap(Set::stream).collect(toSet());
|
||||
|
||||
GitlinkOp.Factory gitlinkOpFactory = new GitlinkOp.Factory(submoduleCommits, subscriptionGraph);
|
||||
|
||||
for (BranchNameKey branch : allBranches) {
|
||||
OpenRepo or = orm.getRepo(branch.project());
|
||||
if (toSubmit.containsKey(branch)) {
|
||||
@@ -688,19 +705,19 @@ public class MergeOp implements AutoCloseable {
|
||||
commitStatus,
|
||||
submissionId,
|
||||
submitInput,
|
||||
submoduleOp.getSubmoduleCommits(),
|
||||
submoduleOp.getSubscriptionGraph(),
|
||||
submoduleCommits,
|
||||
subscriptionGraph,
|
||||
dryrun);
|
||||
strategies.add(strategy);
|
||||
strategy.addOps(or.getUpdate(), commitsToSubmit);
|
||||
if (submitting.submitType().equals(SubmitType.FAST_FORWARD_ONLY)
|
||||
&& submoduleOp.getSubscriptionGraph().hasSubscription(branch)) {
|
||||
submoduleOp.addOp(or.getUpdate(), branch);
|
||||
&& subscriptionGraph.hasSubscription(branch)) {
|
||||
or.getUpdate().addRepoOnlyOp(gitlinkOpFactory.create(branch));
|
||||
}
|
||||
} else {
|
||||
// no open change for this branch
|
||||
// add submodule triggered op into BatchUpdate
|
||||
submoduleOp.addOp(or.getUpdate(), branch);
|
||||
or.getUpdate().addRepoOnlyOp(gitlinkOpFactory.create(branch));
|
||||
}
|
||||
}
|
||||
return strategies;
|
||||
|
@@ -21,10 +21,15 @@ import com.google.common.flogger.FluentLogger;
|
||||
import com.google.gerrit.entities.BranchNameKey;
|
||||
import com.google.gerrit.entities.SubmoduleSubscription;
|
||||
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.git.CodeReviewCommit;
|
||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||
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.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -58,6 +63,22 @@ class SubmoduleCommits {
|
||||
private final long maxCommitMessages;
|
||||
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) {
|
||||
this.orm = orm;
|
||||
this.myIdent = myIdent;
|
||||
|
@@ -15,116 +15,59 @@
|
||||
package com.google.gerrit.server.submit;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.gerrit.common.UsedAt;
|
||||
import com.google.gerrit.entities.BranchNameKey;
|
||||
import com.google.gerrit.entities.Project;
|
||||
import com.google.gerrit.entities.SubmoduleSubscription;
|
||||
import com.google.gerrit.exceptions.StorageException;
|
||||
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.submit.MergeOpRepoManager.OpenRepo;
|
||||
import com.google.gerrit.server.update.BatchUpdate;
|
||||
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.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
|
||||
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
|
||||
public static class Factory {
|
||||
private final SubscriptionGraph.Factory subscriptionGraphFactory;
|
||||
private final Provider<PersonIdent> serverIdent;
|
||||
private final Config cfg;
|
||||
private final SubmoduleCommits.Factory submoduleCommitsFactory;
|
||||
|
||||
@Inject
|
||||
Factory(
|
||||
SubscriptionGraph.Factory subscriptionGraphFactory,
|
||||
@GerritPersonIdent Provider<PersonIdent> serverIdent,
|
||||
@GerritServerConfig Config cfg) {
|
||||
SubmoduleCommits.Factory submoduleCommitsFactory) {
|
||||
this.subscriptionGraphFactory = subscriptionGraphFactory;
|
||||
this.serverIdent = serverIdent;
|
||||
this.cfg = cfg;
|
||||
this.submoduleCommitsFactory = submoduleCommitsFactory;
|
||||
}
|
||||
|
||||
public SubmoduleOp create(Set<BranchNameKey> updatedBranches, MergeOpRepoManager orm)
|
||||
throws SubmoduleConflictException {
|
||||
SubscriptionGraph subscriptionGraph;
|
||||
if (cfg.getBoolean("submodule", "enableSuperProjectSubscriptions", true)) {
|
||||
subscriptionGraph = subscriptionGraphFactory.compute(updatedBranches, orm);
|
||||
} else {
|
||||
logger.atFine().log("Updating superprojects disabled");
|
||||
subscriptionGraph =
|
||||
SubscriptionGraph.createEmptyGraph(ImmutableSet.copyOf(updatedBranches));
|
||||
}
|
||||
return new SubmoduleOp(serverIdent.get(), cfg, orm, subscriptionGraph);
|
||||
return new SubmoduleOp(
|
||||
orm,
|
||||
subscriptionGraphFactory.compute(updatedBranches, orm),
|
||||
submoduleCommitsFactory.create(orm));
|
||||
}
|
||||
}
|
||||
|
||||
private final MergeOpRepoManager orm;
|
||||
private final SubscriptionGraph subscriptionGraph;
|
||||
private final SubmoduleCommits submoduleCommits;
|
||||
private final UpdateOrderCalculator updateOrderCalculator;
|
||||
|
||||
private SubmoduleOp(
|
||||
PersonIdent myIdent,
|
||||
Config cfg,
|
||||
MergeOpRepoManager orm,
|
||||
SubscriptionGraph subscriptionGraph) {
|
||||
SubscriptionGraph subscriptionGraph,
|
||||
SubmoduleCommits submoduleCommits) {
|
||||
this.orm = orm;
|
||||
this.subscriptionGraph = subscriptionGraph;
|
||||
this.submoduleCommits = new SubmoduleCommits(orm, myIdent, cfg);
|
||||
}
|
||||
|
||||
// TODO(ifrade): subscription graph should be instantiated somewhere else and passed to
|
||||
// SubmoduleOp
|
||||
SubscriptionGraph getSubscriptionGraph() {
|
||||
return subscriptionGraph;
|
||||
}
|
||||
|
||||
SubmoduleCommits getSubmoduleCommits() {
|
||||
return submoduleCommits;
|
||||
this.submoduleCommits = submoduleCommits;
|
||||
this.updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph);
|
||||
}
|
||||
|
||||
@UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
|
||||
@@ -133,13 +76,15 @@ public class SubmoduleOp {
|
||||
}
|
||||
|
||||
public void updateSuperProjects() throws RestApiException {
|
||||
ImmutableSet<Project.NameKey> projects = getProjectsInOrder();
|
||||
ImmutableSet<Project.NameKey> projects = updateOrderCalculator.getProjectsInOrder();
|
||||
if (projects == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedHashSet<Project.NameKey> superProjects = new LinkedHashSet<>();
|
||||
try {
|
||||
GitlinkOp.Factory gitlinkOpFactory =
|
||||
new GitlinkOp.Factory(submoduleCommits, subscriptionGraph);
|
||||
for (Project.NameKey project : projects) {
|
||||
// only need superprojects
|
||||
if (subscriptionGraph.isAffectedSuperProject(project)) {
|
||||
@@ -147,7 +92,7 @@ public class SubmoduleOp {
|
||||
// get a new BatchUpdate for the super project
|
||||
OpenRepo or = orm.getRepo(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);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@Override
|
||||
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