diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java index 5396014e1e..afe6231688 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java @@ -15,9 +15,13 @@ package com.google.gerrit.pgm; import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER; +import static com.google.inject.Scopes.SINGLETON; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.google.gerrit.common.ChangeHooks; +import com.google.gerrit.common.DisabledChangeHooks; +import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; import com.google.gerrit.extensions.events.LifecycleListener; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.lifecycle.LifecycleManager; @@ -27,16 +31,46 @@ import com.google.gerrit.pgm.util.SiteProgram; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.rules.PrologModule; +import com.google.gerrit.server.CurrentUser; +import com.google.gerrit.server.InternalUser; +import com.google.gerrit.server.account.AccountByEmailCacheImpl; +import com.google.gerrit.server.account.AccountCacheImpl; +import com.google.gerrit.server.account.CapabilityControl; +import com.google.gerrit.server.account.GroupBackend; +import com.google.gerrit.server.account.GroupCacheImpl; +import com.google.gerrit.server.account.GroupIncludeCacheImpl; +import com.google.gerrit.server.account.IncludingGroupMembership; +import com.google.gerrit.server.account.InternalGroupBackend; +import com.google.gerrit.server.account.UniversalGroupBackend; import com.google.gerrit.server.cache.CacheRemovalListener; import com.google.gerrit.server.cache.h2.DefaultCacheFactory; +import com.google.gerrit.server.change.ChangeKindCache; +import com.google.gerrit.server.change.MergeabilityChecksExecutor; +import com.google.gerrit.server.change.PatchSetInserter; +import com.google.gerrit.server.config.CanonicalWebUrl; +import com.google.gerrit.server.config.CanonicalWebUrlProvider; import com.google.gerrit.server.config.FactoryModule; import com.google.gerrit.server.config.GerritServerConfig; +import com.google.gerrit.server.git.GitModule; +import com.google.gerrit.server.git.MergeUtil; +import com.google.gerrit.server.git.WorkQueue; +import com.google.gerrit.server.git.validators.CommitValidationListener; +import com.google.gerrit.server.git.validators.CommitValidators; +import com.google.gerrit.server.group.SystemGroupBackend; import com.google.gerrit.server.index.ChangeBatchIndexer; import com.google.gerrit.server.index.ChangeIndex; import com.google.gerrit.server.index.ChangeSchemas; import com.google.gerrit.server.index.IndexCollection; import com.google.gerrit.server.index.IndexModule; +import com.google.gerrit.server.mail.ReplacePatchSetSender; import com.google.gerrit.server.patch.PatchListCacheImpl; +import com.google.gerrit.server.project.AccessControlModule; +import com.google.gerrit.server.project.CommentLinkInfo; +import com.google.gerrit.server.project.CommentLinkProvider; +import com.google.gerrit.server.project.ProjectCacheImpl; +import com.google.gerrit.server.project.ProjectState; +import com.google.gerrit.server.project.SectionSortCache; import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.schema.DataSourceProvider; import com.google.gerrit.server.schema.DataSourceType; @@ -48,8 +82,11 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Provider; +import com.google.inject.Provides; import com.google.inject.ProvisionException; +import com.google.inject.Singleton; import com.google.inject.TypeLiteral; +import com.google.inject.util.Providers; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ProgressMonitor; @@ -155,8 +192,60 @@ public class Reindex extends SiteProgram { .toInstance(DynamicSet. emptySet()); install(new DefaultCacheFactory.Module()); factory(ChangeData.Factory.class); + + factory(ProjectState.Factory.class); + bind(new TypeLiteral>() {}) + .toProvider(CommentLinkProvider.class).in(SINGLETON); + bind(CurrentUser.class).toProvider(Providers.of(null)); + bind(String.class).annotatedWith(CanonicalWebUrl.class) + .toProvider(CanonicalWebUrlProvider.class); + + factory(IncludingGroupMembership.Factory.class); + bind(GroupBackend.class).to(UniversalGroupBackend.class).in(SINGLETON); + DynamicSet.setOf(binder(), GroupBackend.class); + bind(InternalGroupBackend.class).in(SINGLETON); + DynamicSet.bind(binder(), GroupBackend.class).to(SystemGroupBackend.class); + DynamicSet.bind(binder(), GroupBackend.class).to(InternalGroupBackend.class); + factory(InternalUser.Factory.class); + + factory(PatchSetInserter.Factory.class); + bind(ChangeHooks.class).to(DisabledChangeHooks.class); + bind(ReplacePatchSetSender.Factory.class).toProvider( + Providers.of(null)); + + factory(CapabilityControl.Factory.class); + factory(MergeUtil.Factory.class); + DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class); + DynamicSet.setOf(binder(), CommitValidationListener.class); + factory(CommitValidators.Factory.class); } }); + + modules.add(AccountCacheImpl.module()); + modules.add(AccountByEmailCacheImpl.module()); + modules.add(ChangeKindCache.module()); + modules.add(GroupCacheImpl.module()); + modules.add(GroupIncludeCacheImpl.module()); + modules.add(ProjectCacheImpl.module()); + modules.add(SectionSortCache.module()); + + modules.add(new AccessControlModule()); + modules.add(new GitModule()); + modules.add(new PrologModule()); + modules.add(new AbstractModule() { + @Override + protected void configure() { + } + + @Provides + @Singleton + @MergeabilityChecksExecutor + public WorkQueue.Executor createMergeabilityChecksExecutor( + WorkQueue queues) { + return queues.createQueue(1, "MergeabilityChecks"); + } + }); + return dbInjector.createChildInjector(modules); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityChecker.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityChecker.java index bf9f65d510..bb4027a488 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityChecker.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityChecker.java @@ -37,6 +37,7 @@ import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.WorkQueue.Executor; import com.google.gerrit.server.index.ChangeIndexer; +import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.util.RequestContext; import com.google.gerrit.server.util.ThreadLocalRequestContext; import com.google.gwtorm.server.OrmException; @@ -53,6 +54,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -64,7 +66,7 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { private final ThreadLocalRequestContext tl; private final SchemaFactory schemaFactory; private final IdentifiedUser.GenericFactory identifiedUserFactory; - private final ChangesCollection changes; + private final ChangeControl.GenericFactory changeControlFactory; private final Provider mergeable; private final ChangeIndexer indexer; private final ListeningExecutorService executor; @@ -75,14 +77,15 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { public MergeabilityChecker(ThreadLocalRequestContext tl, SchemaFactory schemaFactory, IdentifiedUser.GenericFactory identifiedUserFactory, - ChangesCollection changes, Provider mergeable, - ChangeIndexer indexer, @MergeabilityChecksExecutor Executor executor, + ChangeControl.GenericFactory changeControlFactory, + Provider mergeable, ChangeIndexer indexer, + @MergeabilityChecksExecutor Executor executor, MergeabilityCheckQueue mergeabilityCheckQueue, MetaDataUpdate.Server metaDataUpdateFactory) { this.tl = tl; this.schemaFactory = schemaFactory; this.identifiedUserFactory = identifiedUserFactory; - this.changes = changes; + this.changeControlFactory = changeControlFactory; this.mergeable = mergeable; this.indexer = indexer; this.executor = MoreExecutors.listeningDecorator(executor); @@ -119,7 +122,7 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { ProjectConfig newCfg = parseConfig(p, event.getNewObjectId()); if (recheckMerges(oldCfg, newCfg)) { try { - new ProjectUpdateTask(schemaFactory, p).call(); + new ProjectUpdateTask(schemaFactory, p, true).call(); } catch (Exception e) { String msg = "Failed to update mergeability flags for project " + p.get() + " on update of " + RefNames.REFS_CONFIG; @@ -168,12 +171,13 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { * mergeability flag was not updated and the change was not reindexed */ public CheckedFuture updateAsync(Change change) { - return Futures.makeChecked( - executor.submit(new ChangeUpdateTask(schemaFactory, change)), MAPPER); + return updateAsync(change, false); } - private void updateAsync(Change change, boolean force) { - executor.submit(new ChangeUpdateTask(schemaFactory, change, force)); + private CheckedFuture updateAsync(Change change, boolean force) { + return Futures.makeChecked( + executor.submit(new ChangeUpdateTask(schemaFactory, change, force)), + MAPPER); } /** @@ -211,6 +215,18 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { } } + public void update(Project.NameKey project) throws IOException { + try { + for (CheckedFuture f : new ProjectUpdateTask( + schemaFactory, project, false).call()) { + f.checkedGet(); + } + } catch (Exception e) { + Throwables.propagateIfPossible(e); + throw MAPPER.apply(e); + } + } + private class ChangeUpdateTask implements Callable { private final SchemaFactory schemaFactory; private final Change change; @@ -262,8 +278,11 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { PatchSet ps = db.patchSets().get(change.currentPatchSetId()); Mergeable m = mergeable.get(); m.setForce(force); + + ChangeControl control = + changeControlFactory.controlFor(change.getId(), context.getCurrentUser()); MergeableInfo info = m.apply( - new RevisionResource(changes.parse(change.getId()), ps)); + new RevisionResource(new ChangeResource(control), ps)); return change.isMergeable() != info.mergeable; } catch (ResourceConflictException e) { // change is closed @@ -278,7 +297,8 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { } } - private abstract class UpdateTask implements Callable { + private abstract class UpdateTask implements + Callable>> { private final SchemaFactory schemaFactory; private final boolean force; @@ -288,7 +308,7 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { } @Override - public Void call() throws Exception { + public List> call() throws Exception { List openChanges; ReviewDb db = schemaFactory.open(); try { @@ -297,10 +317,12 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { db.close(); } + List> futures = + new ArrayList<>(openChanges.size()); for (Change change : mergeabilityCheckQueue.addAll(openChanges, force)) { - updateAsync(change, force); + futures.add(updateAsync(change, force)); } - return null; + return futures; } protected abstract List loadChanges(ReviewDb db) throws OrmException; @@ -325,8 +347,8 @@ public class MergeabilityChecker implements GitReferenceUpdatedListener { private final Project.NameKey project; ProjectUpdateTask(SchemaFactory schemaFactory, - Project.NameKey project) { - super(schemaFactory, true); + Project.NameKey project, boolean force) { + super(schemaFactory, force); this.project = project; } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index c5327b4d1f..309b151653 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java @@ -32,6 +32,7 @@ import com.google.gerrit.extensions.registration.DynamicMap; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.systemstatus.MessageOfTheDay; import com.google.gerrit.extensions.webui.TopMenu; +import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.rules.PrologModule; import com.google.gerrit.rules.RulesCache; import com.google.gerrit.server.AnonymousUser; @@ -130,6 +131,7 @@ import com.google.inject.internal.UniqueAnnotations; import org.apache.velocity.runtime.RuntimeInstance; import java.util.List; +import java.util.Set; /** Starts global state with standard dependencies. */ @@ -200,6 +202,9 @@ public class GerritGlobalModule extends FactoryModule { bind(AccountVisibility.class) .toProvider(AccountVisibilityProvider.class) .in(SINGLETON); + bind(new TypeLiteral>() {}) + .annotatedWith(ProjectOwnerGroups.class) + .toProvider(ProjectOwnerGroupsProvider.class).in(SINGLETON); bind(AuthBackend.class).to(UniversalAuthBackend.class).in(SINGLETON); DynamicSet.setOf(binder(), AuthBackend.class); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeBatchIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeBatchIndexer.java index c9465102b4..0334715ccc 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeBatchIndexer.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/ChangeBatchIndexer.java @@ -30,6 +30,7 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; +import com.google.gerrit.server.change.MergeabilityChecker; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.MultiProgressMonitor; import com.google.gerrit.server.git.MultiProgressMonitor.Task; @@ -109,18 +110,21 @@ public class ChangeBatchIndexer { private final GitRepositoryManager repoManager; private final ListeningExecutorService executor; private final ChangeIndexer.Factory indexerFactory; + private final MergeabilityChecker mergeabilityChecker; @Inject ChangeBatchIndexer(SchemaFactory schemaFactory, ChangeData.Factory changeDataFactory, GitRepositoryManager repoManager, @IndexExecutor ListeningExecutorService executor, - ChangeIndexer.Factory indexerFactory) { + ChangeIndexer.Factory indexerFactory, + MergeabilityChecker mergeabilityChecker) { this.schemaFactory = schemaFactory; this.changeDataFactory = changeDataFactory; this.repoManager = repoManager; this.executor = executor; this.indexerFactory = indexerFactory; + this.mergeabilityChecker = mergeabilityChecker; } public Result indexAll(ChangeIndex index, Iterable projects, @@ -145,6 +149,12 @@ public class ChangeBatchIndexer { final AtomicBoolean ok = new AtomicBoolean(true); for (final Project.NameKey project : projects) { + try { + mergeabilityChecker.update(project); + } catch (IOException e) { + log.error("Error in mergeability checker", e); + ok.set(false); + } final ListenableFuture future = executor.submit(reindexProject( indexerFactory.create(index), project, doneTask, failedTask, verboseWriter)); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java index a4946ebc3a..7215d18177 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/AccessControlModule.java @@ -22,8 +22,6 @@ import com.google.gerrit.server.config.GitReceivePackGroups; import com.google.gerrit.server.config.GitReceivePackGroupsProvider; import com.google.gerrit.server.config.GitUploadPackGroups; import com.google.gerrit.server.config.GitUploadPackGroupsProvider; -import com.google.gerrit.server.config.ProjectOwnerGroups; -import com.google.gerrit.server.config.ProjectOwnerGroupsProvider; import com.google.inject.TypeLiteral; import java.util.Set; @@ -31,10 +29,6 @@ import java.util.Set; public class AccessControlModule extends FactoryModule { @Override protected void configure() { - bind(new TypeLiteral>() {}) // - .annotatedWith(ProjectOwnerGroups.class) // - .toProvider(ProjectOwnerGroupsProvider.class).in(SINGLETON); - bind(new TypeLiteral>() {}) // .annotatedWith(GitUploadPackGroups.class) // .toProvider(GitUploadPackGroupsProvider.class).in(SINGLETON);