Merge "Delete SQL index support"
This commit is contained in:
commit
da07edd370
@ -1852,17 +1852,12 @@ A link:http://lucene.apache.org/[Lucene] index is used.
|
|||||||
* `SOLR`
|
* `SOLR`
|
||||||
+
|
+
|
||||||
A link:http://lucene.apache.org/solr/[Solr] index is used.
|
A link:http://lucene.apache.org/solr/[Solr] index is used.
|
||||||
+
|
|
||||||
* `SQL`
|
|
||||||
+
|
|
||||||
No secondary index. Not all query operators are supported. Other
|
|
||||||
query operators are routed through the standard SQL query engine.
|
|
||||||
|
|
||||||
+
|
+
|
||||||
By default, `SQL`.
|
By default, `LUCENE`.
|
||||||
+
|
+
|
||||||
After enabling the secondary index, the index must be built using
|
After changing the secondary index type, the index must be rebuilt
|
||||||
the link:pgm-reindex.html[reindex program] before restarting the
|
using the link:pgm-reindex.html[reindex program] before restarting the
|
||||||
Gerrit server.
|
Gerrit server.
|
||||||
|
|
||||||
[[ldap]]Section ldap
|
[[ldap]]Section ldap
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
// Copyright (C) 2013 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.acceptance;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Config;
|
|
||||||
|
|
||||||
public class AbstractDaemonTestWithSecondaryIndex extends AbstractDaemonTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected GerritServer startServer(Config cfg, boolean memory)
|
|
||||||
throws Exception {
|
|
||||||
return GerritServer.start(cfg, memory, true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,7 +18,6 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.gerrit.lucene.LuceneIndexModule;
|
import com.google.gerrit.lucene.LuceneIndexModule;
|
||||||
import com.google.gerrit.pgm.Daemon;
|
import com.google.gerrit.pgm.Daemon;
|
||||||
import com.google.gerrit.pgm.Init;
|
import com.google.gerrit.pgm.Init;
|
||||||
import com.google.gerrit.pgm.Reindex;
|
|
||||||
import com.google.gerrit.server.config.FactoryModule;
|
import com.google.gerrit.server.config.FactoryModule;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.index.ChangeSchemas;
|
import com.google.gerrit.server.index.ChangeSchemas;
|
||||||
@ -51,12 +50,6 @@ public class GerritServer {
|
|||||||
|
|
||||||
/** Returns fully started Gerrit server */
|
/** Returns fully started Gerrit server */
|
||||||
static GerritServer start(Config base, boolean memory) throws Exception {
|
static GerritServer start(Config base, boolean memory) throws Exception {
|
||||||
return start(base, memory, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns fully started Gerrit server */
|
|
||||||
static GerritServer start(Config base, boolean memory, boolean index)
|
|
||||||
throws Exception {
|
|
||||||
final CyclicBarrier serverStarted = new CyclicBarrier(2);
|
final CyclicBarrier serverStarted = new CyclicBarrier(2);
|
||||||
final Daemon daemon = new Daemon(new Runnable() {
|
final Daemon daemon = new Daemon(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -78,25 +71,16 @@ public class GerritServer {
|
|||||||
mergeTestConfig(cfg);
|
mergeTestConfig(cfg);
|
||||||
cfg.setBoolean("httpd", null, "requestLog", false);
|
cfg.setBoolean("httpd", null, "requestLog", false);
|
||||||
cfg.setBoolean("sshd", null, "requestLog", false);
|
cfg.setBoolean("sshd", null, "requestLog", false);
|
||||||
if (index) {
|
cfg.setBoolean("index", "lucene", "testInmemory", true);
|
||||||
cfg.setString("index", null, "type", "lucene");
|
daemon.setLuceneModule(new LuceneIndexModule(
|
||||||
cfg.setBoolean("index", "lucene", "testInmemory", true);
|
ChangeSchemas.getLatest().getVersion(),
|
||||||
daemon.setLuceneModule(new LuceneIndexModule(
|
Runtime.getRuntime().availableProcessors(), null));
|
||||||
ChangeSchemas.getLatest().getVersion(),
|
|
||||||
Runtime.getRuntime().availableProcessors(), null));
|
|
||||||
}
|
|
||||||
daemon.setDatabaseForTesting(ImmutableList.<Module>of(
|
daemon.setDatabaseForTesting(ImmutableList.<Module>of(
|
||||||
new InMemoryTestingDatabaseModule(cfg)));
|
new InMemoryTestingDatabaseModule(cfg)));
|
||||||
daemon.start();
|
daemon.start();
|
||||||
} else {
|
} else {
|
||||||
Config cfg = base != null ? base : new Config();
|
Config cfg = base != null ? base : new Config();
|
||||||
if (index) {
|
|
||||||
cfg.setString("index", null, "type", "lucene");
|
|
||||||
}
|
|
||||||
site = initSite(cfg);
|
site = initSite(cfg);
|
||||||
if (index) {
|
|
||||||
reindex(site);
|
|
||||||
}
|
|
||||||
daemonService = Executors.newSingleThreadExecutor();
|
daemonService = Executors.newSingleThreadExecutor();
|
||||||
daemonService.submit(new Callable<Void>() {
|
daemonService.submit(new Callable<Void>() {
|
||||||
public Void call() throws Exception {
|
public Void call() throws Exception {
|
||||||
@ -137,15 +121,6 @@ public class GerritServer {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runs the reindex command. Works only if the site is not currently running. */
|
|
||||||
private static void reindex(File site) throws Exception {
|
|
||||||
Reindex reindex = new Reindex();
|
|
||||||
int rc = reindex.main(new String[] {"-d", site.getPath()});
|
|
||||||
if (rc != 0) {
|
|
||||||
throw new RuntimeException("Reindex failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void mergeTestConfig(Config cfg)
|
private static void mergeTestConfig(Config cfg)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
InetSocketAddress http = newPort();
|
InetSocketAddress http = newPort();
|
||||||
|
@ -23,7 +23,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.gerrit.acceptance.AbstractDaemonTestWithSecondaryIndex;
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
import com.google.gerrit.acceptance.AccountCreator;
|
import com.google.gerrit.acceptance.AccountCreator;
|
||||||
import com.google.gerrit.acceptance.RestResponse;
|
import com.google.gerrit.acceptance.RestResponse;
|
||||||
import com.google.gerrit.acceptance.RestSession;
|
import com.google.gerrit.acceptance.RestSession;
|
||||||
@ -49,7 +49,7 @@ import org.junit.Test;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ConflictsOperatorIT extends AbstractDaemonTestWithSecondaryIndex {
|
public class ConflictsOperatorIT extends AbstractDaemonTest {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private AccountCreator accounts;
|
private AccountCreator accounts;
|
||||||
|
@ -52,7 +52,6 @@ public class GerritConfig implements Cloneable {
|
|||||||
protected int suggestFrom;
|
protected int suggestFrom;
|
||||||
protected int changeUpdateDelay;
|
protected int changeUpdateDelay;
|
||||||
protected AccountGeneralPreferences.ChangeScreen changeScreen;
|
protected AccountGeneralPreferences.ChangeScreen changeScreen;
|
||||||
protected boolean index;
|
|
||||||
protected int largeChangeSize;
|
protected int largeChangeSize;
|
||||||
|
|
||||||
public String getLoginUrl() {
|
public String getLoginUrl() {
|
||||||
@ -274,14 +273,6 @@ public class GerritConfig implements Cloneable {
|
|||||||
this.changeScreen = ui;
|
this.changeScreen = ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndex(boolean index) {
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLargeChangeSize() {
|
public int getLargeChangeSize() {
|
||||||
return largeChangeSize;
|
return largeChangeSize;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ class RelatedChanges extends TabPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Gerrit.getConfig().hasIndex() && info.mergeable()) {
|
if (info.mergeable()) {
|
||||||
StringBuilder conflictsQuery = new StringBuilder();
|
StringBuilder conflictsQuery = new StringBuilder();
|
||||||
conflictsQuery.append("status:open");
|
conflictsQuery.append("status:open");
|
||||||
conflictsQuery.append(" is:mergeable");
|
conflictsQuery.append(" is:mergeable");
|
||||||
|
@ -26,7 +26,6 @@ import com.google.gerrit.server.config.ConfigUtil;
|
|||||||
import com.google.gerrit.server.config.DownloadConfig;
|
import com.google.gerrit.server.config.DownloadConfig;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.contact.ContactStore;
|
import com.google.gerrit.server.contact.ContactStore;
|
||||||
import com.google.gerrit.server.index.IndexCollection;
|
|
||||||
import com.google.gerrit.server.mail.EmailSender;
|
import com.google.gerrit.server.mail.EmailSender;
|
||||||
import com.google.gerrit.server.ssh.SshInfo;
|
import com.google.gerrit.server.ssh.SshInfo;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@ -50,7 +49,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
|
|||||||
private final GitWebConfig gitWebConfig;
|
private final GitWebConfig gitWebConfig;
|
||||||
private final AllProjectsName wildProject;
|
private final AllProjectsName wildProject;
|
||||||
private final SshInfo sshInfo;
|
private final SshInfo sshInfo;
|
||||||
private final IndexCollection indexCollection;
|
|
||||||
|
|
||||||
private EmailSender emailSender;
|
private EmailSender emailSender;
|
||||||
private final ContactStore contactStore;
|
private final ContactStore contactStore;
|
||||||
@ -61,7 +59,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
|
|||||||
GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
|
GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
|
||||||
final AuthConfig ac, final GitWebConfig gwc, final AllProjectsName wp,
|
final AuthConfig ac, final GitWebConfig gwc, final AllProjectsName wp,
|
||||||
final SshInfo si, final ContactStore cs,
|
final SshInfo si, final ContactStore cs,
|
||||||
final IndexCollection ic,
|
|
||||||
final ServletContext sc, final DownloadConfig dc,
|
final ServletContext sc, final DownloadConfig dc,
|
||||||
final @AnonymousCowardName String acn) {
|
final @AnonymousCowardName String acn) {
|
||||||
realm = r;
|
realm = r;
|
||||||
@ -70,7 +67,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
|
|||||||
downloadConfig = dc;
|
downloadConfig = dc;
|
||||||
gitWebConfig = gwc;
|
gitWebConfig = gwc;
|
||||||
sshInfo = si;
|
sshInfo = si;
|
||||||
indexCollection = ic;
|
|
||||||
wildProject = wp;
|
wildProject = wp;
|
||||||
contactStore = cs;
|
contactStore = cs;
|
||||||
servletContext = sc;
|
servletContext = sc;
|
||||||
@ -130,7 +126,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
|
|||||||
config.setChangeScreen(cfg.getEnum(
|
config.setChangeScreen(cfg.getEnum(
|
||||||
"gerrit", null, "changeScreen",
|
"gerrit", null, "changeScreen",
|
||||||
AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2));
|
AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2));
|
||||||
config.setIndex(indexCollection.getSearchIndex() != null);
|
|
||||||
config.setLargeChangeSize(cfg.getInt("change", "largeChange", 500));
|
config.setLargeChangeSize(cfg.getInt("change", "largeChange", 500));
|
||||||
|
|
||||||
config.setReportBugUrl(cfg.getString("gerrit", null, "reportBugUrl"));
|
config.setReportBugUrl(cfg.getString("gerrit", null, "reportBugUrl"));
|
||||||
|
@ -148,9 +148,7 @@ class AccountServiceImpl extends BaseServiceImplementation implements
|
|||||||
|
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
try {
|
try {
|
||||||
ChangeQueryBuilder builder = queryBuilder.create(currentUser.get());
|
queryBuilder.create(currentUser.get()).parse(filter);
|
||||||
builder.setAllowFileRegex(true);
|
|
||||||
builder.parse(filter);
|
|
||||||
} catch (QueryParseException badFilter) {
|
} catch (QueryParseException badFilter) {
|
||||||
throw new InvalidQueryException(badFilter.getMessage(), filter);
|
throw new InvalidQueryException(badFilter.getMessage(), filter);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ java_library2(
|
|||||||
':init-api',
|
':init-api',
|
||||||
'//gerrit-common:server',
|
'//gerrit-common:server',
|
||||||
'//gerrit-extension-api:api',
|
'//gerrit-extension-api:api',
|
||||||
|
'//gerrit-lucene:lucene',
|
||||||
'//gerrit-reviewdb:server',
|
'//gerrit-reviewdb:server',
|
||||||
'//gerrit-server:server',
|
'//gerrit-server:server',
|
||||||
'//gerrit-util-cli:cli',
|
'//gerrit-util-cli:cli',
|
||||||
|
@ -55,7 +55,7 @@ import com.google.gerrit.server.contact.HttpContactStoreConnection;
|
|||||||
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
|
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.index.IndexModule;
|
import com.google.gerrit.server.index.IndexModule;
|
||||||
import com.google.gerrit.server.index.NoIndexModule;
|
import com.google.gerrit.server.index.IndexModule.IndexType;
|
||||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
||||||
import com.google.gerrit.server.mail.SmtpEmailSender;
|
import com.google.gerrit.server.mail.SmtpEmailSender;
|
||||||
import com.google.gerrit.server.patch.IntraLineWorkerPool;
|
import com.google.gerrit.server.patch.IntraLineWorkerPool;
|
||||||
@ -310,18 +310,7 @@ public class Daemon extends SiteProgram {
|
|||||||
modules.add(new SmtpEmailSender.Module());
|
modules.add(new SmtpEmailSender.Module());
|
||||||
modules.add(new SignedTokenEmailTokenVerifier.Module());
|
modules.add(new SignedTokenEmailTokenVerifier.Module());
|
||||||
modules.add(new PluginRestApiModule());
|
modules.add(new PluginRestApiModule());
|
||||||
AbstractModule changeIndexModule;
|
modules.add(createIndexModule());
|
||||||
switch (IndexModule.getIndexType(cfgInjector)) {
|
|
||||||
case LUCENE:
|
|
||||||
changeIndexModule = luceneModule != null ? luceneModule : new LuceneIndexModule();
|
|
||||||
break;
|
|
||||||
case SOLR:
|
|
||||||
changeIndexModule = new SolrIndexModule();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
changeIndexModule = new NoIndexModule();
|
|
||||||
}
|
|
||||||
modules.add(changeIndexModule);
|
|
||||||
if (Objects.firstNonNull(httpd, true)) {
|
if (Objects.firstNonNull(httpd, true)) {
|
||||||
modules.add(new CanonicalWebUrlModule() {
|
modules.add(new CanonicalWebUrlModule() {
|
||||||
@Override
|
@Override
|
||||||
@ -354,6 +343,18 @@ public class Daemon extends SiteProgram {
|
|||||||
return cfgInjector.createChildInjector(modules);
|
return cfgInjector.createChildInjector(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AbstractModule createIndexModule() {
|
||||||
|
IndexType indexType = IndexModule.getIndexType(cfgInjector);
|
||||||
|
switch (indexType) {
|
||||||
|
case LUCENE:
|
||||||
|
return luceneModule != null ? luceneModule : new LuceneIndexModule();
|
||||||
|
case SOLR:
|
||||||
|
return new SolrIndexModule();
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("unsupported index.type = " + indexType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initSshd() {
|
private void initSshd() {
|
||||||
sshInjector = createSshInjector();
|
sshInjector = createSshInjector();
|
||||||
sysInjector.getInstance(PluginGuiceEnvironment.class)
|
sysInjector.getInstance(PluginGuiceEnvironment.class)
|
||||||
|
@ -35,8 +35,6 @@ import com.google.gerrit.server.index.ChangeIndex;
|
|||||||
import com.google.gerrit.server.index.ChangeSchemas;
|
import com.google.gerrit.server.index.ChangeSchemas;
|
||||||
import com.google.gerrit.server.index.IndexCollection;
|
import com.google.gerrit.server.index.IndexCollection;
|
||||||
import com.google.gerrit.server.index.IndexModule;
|
import com.google.gerrit.server.index.IndexModule;
|
||||||
import com.google.gerrit.server.index.IndexModule.IndexType;
|
|
||||||
import com.google.gerrit.server.index.NoIndexModule;
|
|
||||||
import com.google.gerrit.server.patch.PatchListCacheImpl;
|
import com.google.gerrit.server.patch.PatchListCacheImpl;
|
||||||
import com.google.gerrit.server.schema.DataSourceProvider;
|
import com.google.gerrit.server.schema.DataSourceProvider;
|
||||||
import com.google.gerrit.server.schema.DataSourceType;
|
import com.google.gerrit.server.schema.DataSourceType;
|
||||||
@ -91,9 +89,6 @@ public class Reindex extends SiteProgram {
|
|||||||
public int run() throws Exception {
|
public int run() throws Exception {
|
||||||
mustHaveValidSite();
|
mustHaveValidSite();
|
||||||
dbInjector = createDbInjector(MULTI_USER);
|
dbInjector = createDbInjector(MULTI_USER);
|
||||||
if (IndexModule.getIndexType(dbInjector) == IndexType.SQL) {
|
|
||||||
throw die("index.type must be configured (or not SQL)");
|
|
||||||
}
|
|
||||||
limitThreads();
|
limitThreads();
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
version = ChangeSchemas.getLatest().getVersion();
|
version = ChangeSchemas.getLatest().getVersion();
|
||||||
@ -144,7 +139,7 @@ public class Reindex extends SiteProgram {
|
|||||||
changeIndexModule = new SolrIndexModule(false, threads, outputBase);
|
changeIndexModule = new SolrIndexModule(false, threads, outputBase);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
changeIndexModule = new NoIndexModule();
|
throw new IllegalStateException("unsupported index.type");
|
||||||
}
|
}
|
||||||
modules.add(changeIndexModule);
|
modules.add(changeIndexModule);
|
||||||
modules.add(new ReviewDbModule());
|
modules.add(new ReviewDbModule());
|
||||||
|
@ -0,0 +1,178 @@
|
|||||||
|
// Copyright (C) 2013 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.pgm.init;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gerrit.lucene.LuceneChangeIndex;
|
||||||
|
import com.google.gerrit.lucene.LuceneIndexModule;
|
||||||
|
import com.google.gerrit.pgm.util.ConsoleUI;
|
||||||
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
|
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project.NameKey;
|
||||||
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
|
import com.google.gerrit.server.config.SitePaths;
|
||||||
|
import com.google.gerrit.server.config.TrackingFooter;
|
||||||
|
import com.google.gerrit.server.config.TrackingFooters;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.index.ChangeIndex;
|
||||||
|
import com.google.gerrit.server.index.ChangeSchemas;
|
||||||
|
import com.google.gerrit.server.index.IndexModule.IndexType;
|
||||||
|
import com.google.gerrit.server.patch.IntraLineDiff;
|
||||||
|
import com.google.gerrit.server.patch.IntraLineDiffKey;
|
||||||
|
import com.google.gerrit.server.patch.PatchList;
|
||||||
|
import com.google.gerrit.server.patch.PatchListCache;
|
||||||
|
import com.google.gerrit.server.patch.PatchListKey;
|
||||||
|
import com.google.gerrit.server.patch.PatchListNotAvailableException;
|
||||||
|
import com.google.gwtorm.server.OrmException;
|
||||||
|
import com.google.gwtorm.server.SchemaFactory;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.ProvisionException;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
|
import org.eclipse.jgit.lib.Config;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
|
/** Initialize the {@code index} configuration section. */
|
||||||
|
@Singleton
|
||||||
|
class InitIndex implements InitStep {
|
||||||
|
private final ConsoleUI ui;
|
||||||
|
private final Section index;
|
||||||
|
private final SitePaths site;
|
||||||
|
private final InitFlags initFlags;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
InitIndex(ConsoleUI ui,
|
||||||
|
Section.Factory sections,
|
||||||
|
SitePaths site,
|
||||||
|
InitFlags initFlags) {
|
||||||
|
this.ui = ui;
|
||||||
|
this.index = sections.get("index", null);
|
||||||
|
this.site = site;
|
||||||
|
this.initFlags = initFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws IOException {
|
||||||
|
ui.header("Index");
|
||||||
|
|
||||||
|
IndexType type = index.select("Type", "type", IndexType.LUCENE);
|
||||||
|
if (site.isNew && type == IndexType.LUCENE) {
|
||||||
|
createLuceneIndex();
|
||||||
|
} else {
|
||||||
|
ui.message("The index must be built before starting Gerrit:\n"
|
||||||
|
+ " java -jar gerrit.war reindex -d site_path\n");
|
||||||
|
initFlags.autoStart = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLuceneIndex() throws IOException {
|
||||||
|
Injector injector = Guice.createInjector(
|
||||||
|
new LuceneIndexModule(ChangeSchemas.getLatest().getVersion(), 0, null),
|
||||||
|
new MockIndexSupportModule());
|
||||||
|
|
||||||
|
ChangeIndex index = injector.getInstance(LuceneChangeIndex.class);
|
||||||
|
index.markReady(true);
|
||||||
|
index.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockIndexSupportModule extends AbstractModule {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(SitePaths.class).toInstance(site);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides @GerritServerConfig Config getConfig() {
|
||||||
|
return new Config();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides TrackingFooters newTrackingFooters() {
|
||||||
|
return new TrackingFooters(Collections.<TrackingFooter> emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides ReviewDb getReviewDb() {
|
||||||
|
throw new ProvisionException("database not initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides SchemaFactory<ReviewDb> getSchemaFactory() {
|
||||||
|
return new SchemaFactory<ReviewDb>() {
|
||||||
|
@Override
|
||||||
|
public ReviewDb open() throws OrmException {
|
||||||
|
return getReviewDb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides GitRepositoryManager getGitRepositoryManager() {
|
||||||
|
return new GitRepositoryManager() {
|
||||||
|
@Override
|
||||||
|
public Repository openRepository(Project.NameKey name)
|
||||||
|
throws RepositoryNotFoundException{
|
||||||
|
throw new RepositoryNotFoundException(name.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Repository createRepository(Project.NameKey name)
|
||||||
|
throws RepositoryNotFoundException {
|
||||||
|
throw new RepositoryNotFoundException(name.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SortedSet<Project.NameKey> list() {
|
||||||
|
return Sets.newTreeSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProjectDescription(Project.NameKey name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProjectDescription(NameKey name, String description) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides PatchListCache newPatchListCache() {
|
||||||
|
return new PatchListCache() {
|
||||||
|
@Override
|
||||||
|
public PatchList get(PatchListKey key)
|
||||||
|
throws PatchListNotAvailableException {
|
||||||
|
throw new PatchListNotAvailableException("new site, no changes");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PatchList get(Change change, PatchSet patchSet)
|
||||||
|
throws PatchListNotAvailableException {
|
||||||
|
throw new PatchListNotAvailableException("new site, no changes");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntraLineDiff getIntraLineDiff(IntraLineDiffKey key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -46,6 +46,7 @@ public class InitModule extends FactoryModule {
|
|||||||
if (standalone) {
|
if (standalone) {
|
||||||
step().to(InitDatabase.class);
|
step().to(InitDatabase.class);
|
||||||
}
|
}
|
||||||
|
step().to(InitIndex.class);
|
||||||
step().to(InitAuth.class);
|
step().to(InitAuth.class);
|
||||||
step().to(InitSendEmail.class);
|
step().to(InitSendEmail.class);
|
||||||
if (standalone) {
|
if (standalone) {
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
package com.google.gerrit.reviewdb.server;
|
package com.google.gerrit.reviewdb.server;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
import com.google.gerrit.reviewdb.client.Branch;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
import com.google.gerrit.reviewdb.client.Project;
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
@ -42,14 +41,6 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
|
|||||||
@Query("WHERE dest.projectName = ?")
|
@Query("WHERE dest.projectName = ?")
|
||||||
ResultSet<Change> byProject(Project.NameKey p) throws OrmException;
|
ResultSet<Change> byProject(Project.NameKey p) throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE owner = ? AND open = true ORDER BY createdOn, changeId")
|
|
||||||
ResultSet<Change> byOwnerOpen(Account.Id id) throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE owner = ? AND open = false ORDER BY lastUpdatedOn")
|
|
||||||
ResultSet<Change> byOwnerClosedAll(Account.Id id) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE dest = ? AND status = '" + Change.STATUS_SUBMITTED
|
@Query("WHERE dest = ? AND status = '" + Change.STATUS_SUBMITTED
|
||||||
+ "' ORDER BY lastUpdatedOn")
|
+ "' ORDER BY lastUpdatedOn")
|
||||||
ResultSet<Change> submitted(Branch.NameKey dest) throws OrmException;
|
ResultSet<Change> submitted(Branch.NameKey dest) throws OrmException;
|
||||||
@ -57,65 +48,17 @@ public interface ChangeAccess extends Access<Change, Change.Id> {
|
|||||||
@Query("WHERE status = '" + Change.STATUS_SUBMITTED + "'")
|
@Query("WHERE status = '" + Change.STATUS_SUBMITTED + "'")
|
||||||
ResultSet<Change> allSubmitted() throws OrmException;
|
ResultSet<Change> allSubmitted() throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = true AND sortKey > ? ORDER BY sortKey LIMIT ?")
|
|
||||||
ResultSet<Change> allOpenPrev(String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = true AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
|
|
||||||
ResultSet<Change> allOpenNext(String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE open = true AND dest.projectName = ?")
|
@Query("WHERE open = true AND dest.projectName = ?")
|
||||||
ResultSet<Change> byProjectOpenAll(Project.NameKey p) throws OrmException;
|
ResultSet<Change> byProjectOpenAll(Project.NameKey p) throws OrmException;
|
||||||
|
|
||||||
@Query("WHERE open = true AND dest = ?")
|
@Query("WHERE open = true AND dest = ?")
|
||||||
ResultSet<Change> byBranchOpenAll(Branch.NameKey p) throws OrmException;
|
ResultSet<Change> byBranchOpenAll(Branch.NameKey p) throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = true AND dest.projectName = ? AND sortKey > ?"
|
|
||||||
+ " ORDER BY sortKey LIMIT ?")
|
|
||||||
ResultSet<Change> byProjectOpenPrev(Project.NameKey p, String sortKey,
|
|
||||||
int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Query("WHERE open = true AND dest.projectName = ? AND sortKey < ?"
|
@Query("WHERE open = true AND dest.projectName = ? AND sortKey < ?"
|
||||||
+ " ORDER BY sortKey DESC LIMIT ?")
|
+ " ORDER BY sortKey DESC LIMIT ?")
|
||||||
ResultSet<Change> byProjectOpenNext(Project.NameKey p, String sortKey,
|
ResultSet<Change> byProjectOpenNext(Project.NameKey p, String sortKey,
|
||||||
int limit) throws OrmException;
|
int limit) throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey > ?"
|
|
||||||
+ " ORDER BY sortKey LIMIT ?")
|
|
||||||
ResultSet<Change> byProjectClosedPrev(char status, Project.NameKey p,
|
|
||||||
String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND dest.projectName = ? AND sortKey < ?"
|
|
||||||
+ " ORDER BY sortKey DESC LIMIT ?")
|
|
||||||
ResultSet<Change> byProjectClosedNext(char status, Project.NameKey p,
|
|
||||||
String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND sortKey > ? ORDER BY sortKey LIMIT ?")
|
|
||||||
ResultSet<Change> allClosedPrev(char status, String sortKey, int limit)
|
|
||||||
throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND sortKey < ? ORDER BY sortKey DESC LIMIT ?")
|
|
||||||
ResultSet<Change> allClosedNext(char status, String sortKey, int limit)
|
|
||||||
throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND dest = ? AND sortKey > ?"
|
|
||||||
+ " ORDER BY sortKey LIMIT ?")
|
|
||||||
ResultSet<Change> byBranchClosedPrev(char status, Branch.NameKey p,
|
|
||||||
String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE open = false AND status = ? AND dest = ? AND sortKey < ?"
|
|
||||||
+ " ORDER BY sortKey DESC LIMIT ?")
|
|
||||||
ResultSet<Change> byBranchClosedNext(char status, Branch.NameKey p,
|
|
||||||
String sortKey, int limit) throws OrmException;
|
|
||||||
|
|
||||||
@Query
|
@Query
|
||||||
ResultSet<Change> all() throws OrmException;
|
ResultSet<Change> all() throws OrmException;
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,4 @@ public interface PatchSetApprovalAccess extends
|
|||||||
@Query("WHERE key.patchSetId = ? AND key.accountId = ?")
|
@Query("WHERE key.patchSetId = ? AND key.accountId = ?")
|
||||||
ResultSet<PatchSetApproval> byPatchSetUser(PatchSet.Id patchSet,
|
ResultSet<PatchSetApproval> byPatchSetUser(PatchSet.Id patchSet,
|
||||||
Account.Id account) throws OrmException;
|
Account.Id account) throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE changeOpen = true AND key.accountId = ?")
|
|
||||||
ResultSet<PatchSetApproval> openByUser(Account.Id account)
|
|
||||||
throws OrmException;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE changeOpen = false AND key.accountId = ? ORDER BY changeSortKey")
|
|
||||||
ResultSet<PatchSetApproval> closedByUserAll(Account.Id account)
|
|
||||||
throws OrmException;
|
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,4 @@ public interface TrackingIdAccess extends Access<TrackingId, TrackingId.Key> {
|
|||||||
|
|
||||||
@Query("WHERE key.changeId = ?")
|
@Query("WHERE key.changeId = ?")
|
||||||
ResultSet<TrackingId> byChange(Change.Id change) throws OrmException;
|
ResultSet<TrackingId> byChange(Change.Id change) throws OrmException;
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Query("WHERE key.trackingKey = ?")
|
|
||||||
ResultSet<TrackingId> byTrackingId(TrackingId.Id trackingId)
|
|
||||||
throws OrmException;
|
|
||||||
}
|
}
|
||||||
|
@ -69,23 +69,11 @@ ON account_project_watches (project_name);
|
|||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- ChangeAccess
|
-- ChangeAccess
|
||||||
-- covers: byOwnerOpen
|
|
||||||
CREATE INDEX changes_byOwnerOpen
|
|
||||||
ON changes (open, owner_account_id, created_on, change_id);
|
|
||||||
|
|
||||||
-- covers: byOwnerClosed
|
|
||||||
CREATE INDEX changes_byOwnerClosed
|
|
||||||
ON changes (open, owner_account_id, last_updated_on);
|
|
||||||
|
|
||||||
-- covers: submitted, allSubmitted
|
-- covers: submitted, allSubmitted
|
||||||
CREATE INDEX changes_submitted
|
CREATE INDEX changes_submitted
|
||||||
ON changes (status, dest_project_name, dest_branch_name, last_updated_on);
|
ON changes (status, dest_project_name, dest_branch_name, last_updated_on);
|
||||||
|
|
||||||
-- covers: allOpenPrev, allOpenNext
|
-- covers: byProjectOpenAll
|
||||||
CREATE INDEX changes_allOpen
|
|
||||||
ON changes (open, sort_key);
|
|
||||||
|
|
||||||
-- covers: byProjectOpenPrev, byProjectOpenNext
|
|
||||||
CREATE INDEX changes_byProjectOpen
|
CREATE INDEX changes_byProjectOpen
|
||||||
ON changes (open, dest_project_name, sort_key);
|
ON changes (open, dest_project_name, sort_key);
|
||||||
|
|
||||||
@ -93,30 +81,10 @@ ON changes (open, dest_project_name, sort_key);
|
|||||||
CREATE INDEX changes_byProject
|
CREATE INDEX changes_byProject
|
||||||
ON changes (dest_project_name);
|
ON changes (dest_project_name);
|
||||||
|
|
||||||
-- covers: allClosedPrev, allClosedNext
|
|
||||||
CREATE INDEX changes_allClosed
|
|
||||||
ON changes (open, status, sort_key);
|
|
||||||
|
|
||||||
-- covers: byBranchClosedPrev, byBranchClosedNext
|
|
||||||
CREATE INDEX changes_byBranchClosed
|
|
||||||
ON changes (status, dest_project_name, dest_branch_name, sort_key);
|
|
||||||
|
|
||||||
CREATE INDEX changes_key
|
CREATE INDEX changes_key
|
||||||
ON changes (change_key);
|
ON changes (change_key);
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
|
||||||
-- PatchSetApprovalAccess
|
|
||||||
-- @PrimaryKey covers: byPatchSet, byPatchSetUser
|
|
||||||
-- covers: openByUser
|
|
||||||
CREATE INDEX patch_set_approvals_openByUser
|
|
||||||
ON patch_set_approvals (change_open, account_id);
|
|
||||||
|
|
||||||
-- covers: closedByUser
|
|
||||||
CREATE INDEX patch_set_approvals_closedByU
|
|
||||||
ON patch_set_approvals (change_open, account_id, change_sort_key);
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- ChangeMessageAccess
|
-- ChangeMessageAccess
|
||||||
-- @PrimaryKey covers: byChange
|
-- @PrimaryKey covers: byChange
|
||||||
|
@ -117,63 +117,24 @@ ON account_project_watches (project_name);
|
|||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- ChangeAccess
|
-- ChangeAccess
|
||||||
-- covers: byOwnerOpen
|
|
||||||
CREATE INDEX changes_byOwnerOpen
|
|
||||||
ON changes (owner_account_id, created_on, change_id)
|
|
||||||
WHERE open = 'Y';
|
|
||||||
|
|
||||||
-- covers: byOwnerClosed
|
|
||||||
CREATE INDEX changes_byOwnerClosed
|
|
||||||
ON changes (owner_account_id, last_updated_on)
|
|
||||||
WHERE open = 'N';
|
|
||||||
|
|
||||||
-- covers: submitted, allSubmitted
|
-- covers: submitted, allSubmitted
|
||||||
CREATE INDEX changes_submitted
|
CREATE INDEX changes_submitted
|
||||||
ON changes (dest_project_name, dest_branch_name, last_updated_on)
|
ON changes (dest_project_name, dest_branch_name, last_updated_on)
|
||||||
WHERE status = 's';
|
WHERE status = 's';
|
||||||
|
|
||||||
-- covers: allOpenPrev, allOpenNext
|
-- covers: byProjectOpenAll
|
||||||
CREATE INDEX changes_allOpen
|
|
||||||
ON changes (sort_key)
|
|
||||||
WHERE open = 'Y';
|
|
||||||
|
|
||||||
-- covers: byProjectOpenPrev, byProjectOpenNext
|
|
||||||
CREATE INDEX changes_byProjectOpen
|
CREATE INDEX changes_byProjectOpen
|
||||||
ON changes (dest_project_name, sort_key)
|
ON changes (dest_project_name, sort_key)
|
||||||
WHERE open = 'Y';
|
WHERE open = 'Y';
|
||||||
|
|
||||||
-- covers: allClosedPrev, allClosedNext
|
|
||||||
CREATE INDEX changes_allClosed
|
|
||||||
ON changes (status, sort_key)
|
|
||||||
WHERE open = 'N';
|
|
||||||
|
|
||||||
-- covers: byProject
|
-- covers: byProject
|
||||||
CREATE INDEX changes_byProject
|
CREATE INDEX changes_byProject
|
||||||
ON changes (dest_project_name);
|
ON changes (dest_project_name);
|
||||||
|
|
||||||
-- covers: byBranchClosedPrev, byBranchClosedNext
|
|
||||||
CREATE INDEX changes_byBranchClosed
|
|
||||||
ON changes (status, dest_project_name, dest_branch_name, sort_key)
|
|
||||||
WHERE open = 'N';
|
|
||||||
|
|
||||||
CREATE INDEX changes_key
|
CREATE INDEX changes_key
|
||||||
ON changes (change_key);
|
ON changes (change_key);
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
|
||||||
-- PatchSetApprovalAccess
|
|
||||||
-- @PrimaryKey covers: byPatchSet, byPatchSetUser
|
|
||||||
-- covers: openByUser
|
|
||||||
CREATE INDEX patch_set_approvals_openByUser
|
|
||||||
ON patch_set_approvals (account_id)
|
|
||||||
WHERE change_open = 'Y';
|
|
||||||
|
|
||||||
-- covers: closedByUser
|
|
||||||
CREATE INDEX patch_set_approvals_closedByU
|
|
||||||
ON patch_set_approvals (account_id, change_sort_key)
|
|
||||||
WHERE change_open = 'N';
|
|
||||||
|
|
||||||
|
|
||||||
-- *********************************************************************
|
-- *********************************************************************
|
||||||
-- ChangeMessageAccess
|
-- ChangeMessageAccess
|
||||||
-- @PrimaryKey covers: byChange
|
-- @PrimaryKey covers: byChange
|
||||||
|
@ -32,49 +32,6 @@ import java.io.IOException;
|
|||||||
* appropriate.
|
* appropriate.
|
||||||
*/
|
*/
|
||||||
public interface ChangeIndex {
|
public interface ChangeIndex {
|
||||||
/** Instance indicating secondary index is disabled. */
|
|
||||||
public static final ChangeIndex DISABLED = new ChangeIndex() {
|
|
||||||
@Override
|
|
||||||
public Schema<ChangeData> getSchema() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insert(ChangeData cd) throws IOException {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void replace(ChangeData cd) throws IOException {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(ChangeData cd) throws IOException {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteAll() throws IOException {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ChangeDataSource getSource(Predicate<ChangeData> p, int limit) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void markReady(boolean ready) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @return the schema version used by this index. */
|
/** @return the schema version used by this index. */
|
||||||
public Schema<ChangeData> getSchema();
|
public Schema<ChangeData> getSchema();
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
package com.google.gerrit.server.index;
|
package com.google.gerrit.server.index;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.Callables;
|
|
||||||
import com.google.common.util.concurrent.CheckedFuture;
|
import com.google.common.util.concurrent.CheckedFuture;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
@ -38,24 +37,6 @@ public abstract class ChangeIndexer {
|
|||||||
ChangeIndexer create(IndexCollection indexes);
|
ChangeIndexer create(IndexCollection indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Instance indicating secondary index is disabled. */
|
|
||||||
public static final ChangeIndexer DISABLED = new ChangeIndexer(null) {
|
|
||||||
@Override
|
|
||||||
public CheckedFuture<?, IOException> indexAsync(ChangeData cd) {
|
|
||||||
return Futures.immediateCheckedFuture(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Callable<?> indexTask(ChangeData cd) {
|
|
||||||
return Callables.returning(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Callable<?> deleteTask(ChangeData cd) {
|
|
||||||
return Callables.returning(null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final Function<Exception, IOException> MAPPER =
|
private static final Function<Exception, IOException> MAPPER =
|
||||||
new Function<Exception, IOException>() {
|
new Function<Exception, IOException>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,7 +16,6 @@ package com.google.gerrit.server.index;
|
|||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gerrit.common.Nullable;
|
|
||||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
@ -39,11 +38,7 @@ public class IndexCollection implements LifecycleListener {
|
|||||||
this.searchIndex = new AtomicReference<ChangeIndex>();
|
this.searchIndex = new AtomicReference<ChangeIndex>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @return the current search index version. */
|
||||||
* @return the current search index version, or null if the secondary index is
|
|
||||||
* disabled.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
public ChangeIndex getSearchIndex() {
|
public ChangeIndex getSearchIndex() {
|
||||||
return searchIndex.get();
|
return searchIndex.get();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
|
import com.google.gerrit.server.query.change.BasicChangeRewrites;
|
||||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
@ -37,14 +38,14 @@ import org.eclipse.jgit.lib.Config;
|
|||||||
*/
|
*/
|
||||||
public class IndexModule extends LifecycleModule {
|
public class IndexModule extends LifecycleModule {
|
||||||
public enum IndexType {
|
public enum IndexType {
|
||||||
SQL, LUCENE, SOLR
|
LUCENE, SOLR
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Type of secondary index. */
|
/** Type of secondary index. */
|
||||||
public static IndexType getIndexType(Injector injector) {
|
public static IndexType getIndexType(Injector injector) {
|
||||||
Config cfg = injector.getInstance(
|
Config cfg = injector.getInstance(
|
||||||
Key.get(Config.class, GerritServerConfig.class));
|
Key.get(Config.class, GerritServerConfig.class));
|
||||||
return cfg.getEnum("index", null, "type", IndexType.SQL);
|
return cfg.getEnum("index", null, "type", IndexType.LUCENE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final int threads;
|
private final int threads;
|
||||||
@ -63,7 +64,7 @@ public class IndexModule extends LifecycleModule {
|
|||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(ChangeQueryRewriter.class).to(IndexRewriteImpl.class);
|
bind(ChangeQueryRewriter.class).to(IndexRewriteImpl.class);
|
||||||
bind(IndexRewriteImpl.BasicRewritesImpl.class);
|
bind(BasicChangeRewrites.class);
|
||||||
bind(IndexCollection.class);
|
bind(IndexCollection.class);
|
||||||
listener().to(IndexCollection.class);
|
listener().to(IndexCollection.class);
|
||||||
install(new FactoryModuleBuilder()
|
install(new FactoryModuleBuilder()
|
||||||
|
@ -25,7 +25,6 @@ import com.google.gerrit.server.query.NotPredicate;
|
|||||||
import com.google.gerrit.server.query.OrPredicate;
|
import com.google.gerrit.server.query.OrPredicate;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryParseException;
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
import com.google.gerrit.server.query.QueryRewriter;
|
|
||||||
import com.google.gerrit.server.query.change.AndSource;
|
import com.google.gerrit.server.query.change.AndSource;
|
||||||
import com.google.gerrit.server.query.change.BasicChangeRewrites;
|
import com.google.gerrit.server.query.change.BasicChangeRewrites;
|
||||||
import com.google.gerrit.server.query.change.ChangeData;
|
import com.google.gerrit.server.query.change.ChangeData;
|
||||||
@ -33,7 +32,6 @@ import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
|||||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
||||||
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
|
import com.google.gerrit.server.query.change.ChangeStatusPredicate;
|
||||||
import com.google.gerrit.server.query.change.OrSource;
|
import com.google.gerrit.server.query.change.OrSource;
|
||||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
@ -125,27 +123,21 @@ public class IndexRewriteImpl implements ChangeQueryRewriter {
|
|||||||
|
|
||||||
private final IndexCollection indexes;
|
private final IndexCollection indexes;
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
private final BasicRewritesImpl basicRewrites;
|
private final BasicChangeRewrites basicRewrites;
|
||||||
private final SqlRewriterImpl sqlRewriter;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
IndexRewriteImpl(IndexCollection indexes,
|
IndexRewriteImpl(IndexCollection indexes,
|
||||||
Provider<ReviewDb> db,
|
Provider<ReviewDb> db,
|
||||||
BasicRewritesImpl basicRewrites,
|
BasicChangeRewrites basicRewrites) {
|
||||||
SqlRewriterImpl sqlRewriter) {
|
|
||||||
this.indexes = indexes;
|
this.indexes = indexes;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.basicRewrites = basicRewrites;
|
this.basicRewrites = basicRewrites;
|
||||||
this.sqlRewriter = sqlRewriter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Predicate<ChangeData> rewrite(Predicate<ChangeData> in)
|
public Predicate<ChangeData> rewrite(Predicate<ChangeData> in)
|
||||||
throws QueryParseException {
|
throws QueryParseException {
|
||||||
ChangeIndex index = indexes.getSearchIndex();
|
ChangeIndex index = indexes.getSearchIndex();
|
||||||
if (index == null) {
|
|
||||||
return sqlRewriter.rewrite(in);
|
|
||||||
}
|
|
||||||
in = basicRewrites.rewrite(in);
|
in = basicRewrites.rewrite(in);
|
||||||
int limit = ChangeQueryBuilder.hasLimit(in)
|
int limit = ChangeQueryBuilder.hasLimit(in)
|
||||||
? ChangeQueryBuilder.getLimit(in)
|
? ChangeQueryBuilder.getLimit(in)
|
||||||
@ -271,14 +263,4 @@ public class IndexRewriteImpl implements ChangeQueryRewriter {
|
|||||||
|| p instanceof OrPredicate
|
|| p instanceof OrPredicate
|
||||||
|| p instanceof NotPredicate);
|
|| p instanceof NotPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class BasicRewritesImpl extends BasicChangeRewrites {
|
|
||||||
private static final QueryRewriter.Definition<ChangeData, BasicRewritesImpl> mydef =
|
|
||||||
new QueryRewriter.Definition<ChangeData, BasicRewritesImpl>(
|
|
||||||
BasicRewritesImpl.class, SqlRewriterImpl.BUILDER);
|
|
||||||
@Inject
|
|
||||||
BasicRewritesImpl(Provider<ReviewDb> db, IndexCollection indexes) {
|
|
||||||
super(mydef, db, indexes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
// Copyright (C) 2013 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.index;
|
|
||||||
|
|
||||||
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
|
||||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
|
|
||||||
public class NoIndexModule extends AbstractModule {
|
|
||||||
// TODO(dborowitz): This module should go away when the index becomes
|
|
||||||
// obligatory, as should the interfaces that exist only to support the
|
|
||||||
// non-index case.
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(ChangeIndex.class).toInstance(ChangeIndex.DISABLED);
|
|
||||||
bind(ChangeIndexer.class).toInstance(ChangeIndexer.DISABLED);
|
|
||||||
bind(ChangeQueryRewriter.class).to(SqlRewriterImpl.class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -202,7 +202,6 @@ public class ProjectWatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (filter != null) {
|
if (filter != null) {
|
||||||
qb.setAllowFileRegex(true);
|
|
||||||
Predicate<ChangeData> filterPredicate = qb.parse(filter);
|
Predicate<ChangeData> filterPredicate = qb.parse(filter);
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
p = filterPredicate;
|
p = filterPredicate;
|
||||||
|
@ -24,18 +24,23 @@ import com.google.gerrit.server.index.Schema;
|
|||||||
import com.google.gerrit.server.query.IntPredicate;
|
import com.google.gerrit.server.query.IntPredicate;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryRewriter;
|
import com.google.gerrit.server.query.QueryRewriter;
|
||||||
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.OutOfScopeException;
|
import com.google.inject.OutOfScopeException;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.name.Named;
|
import com.google.inject.name.Named;
|
||||||
|
|
||||||
public abstract class BasicChangeRewrites extends QueryRewriter<ChangeData> {
|
public class BasicChangeRewrites extends QueryRewriter<ChangeData> {
|
||||||
protected static final ChangeQueryBuilder BUILDER = new ChangeQueryBuilder(
|
private static final ChangeQueryBuilder BUILDER = new ChangeQueryBuilder(
|
||||||
new ChangeQueryBuilder.Arguments( //
|
new ChangeQueryBuilder.Arguments( //
|
||||||
new InvalidProvider<ReviewDb>(), //
|
new InvalidProvider<ReviewDb>(), //
|
||||||
new InvalidProvider<ChangeQueryRewriter>(), //
|
new InvalidProvider<ChangeQueryRewriter>(), //
|
||||||
null, null, null, null, null, null, null, //
|
null, null, null, null, null, null, null, //
|
||||||
null, null, null, null, null, null, null), null);
|
null, null, null, null, null, null, null), null);
|
||||||
|
|
||||||
|
private static final QueryRewriter.Definition<ChangeData, BasicChangeRewrites> mydef =
|
||||||
|
new QueryRewriter.Definition<ChangeData, BasicChangeRewrites>(
|
||||||
|
BasicChangeRewrites.class, BUILDER);
|
||||||
|
|
||||||
static Schema<ChangeData> schema(@Nullable IndexCollection indexes) {
|
static Schema<ChangeData> schema(@Nullable IndexCollection indexes) {
|
||||||
ChangeIndex index = indexes != null ? indexes.getSearchIndex() : null;
|
ChangeIndex index = indexes != null ? indexes.getSearchIndex() : null;
|
||||||
return index != null ? index.getSchema() : null;
|
return index != null ? index.getSchema() : null;
|
||||||
@ -44,10 +49,9 @@ public abstract class BasicChangeRewrites extends QueryRewriter<ChangeData> {
|
|||||||
protected final Provider<ReviewDb> dbProvider;
|
protected final Provider<ReviewDb> dbProvider;
|
||||||
private final IndexCollection indexes;
|
private final IndexCollection indexes;
|
||||||
|
|
||||||
protected BasicChangeRewrites(
|
@Inject
|
||||||
Definition<ChangeData, ? extends QueryRewriter<ChangeData>> def,
|
public BasicChangeRewrites(Provider<ReviewDb> dbProvider, IndexCollection indexes) {
|
||||||
Provider<ReviewDb> dbProvider, IndexCollection indexes) {
|
super(mydef);
|
||||||
super(def);
|
|
||||||
this.dbProvider = dbProvider;
|
this.dbProvider = dbProvider;
|
||||||
this.indexes = indexes;
|
this.indexes = indexes;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
|
|
||||||
private final Arguments args;
|
private final Arguments args;
|
||||||
private final CurrentUser currentUser;
|
private final CurrentUser currentUser;
|
||||||
private boolean allowFileRegex;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ChangeQueryBuilder(Arguments args, @Assisted CurrentUser currentUser) {
|
public ChangeQueryBuilder(Arguments args, @Assisted CurrentUser currentUser) {
|
||||||
@ -219,10 +218,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllowFileRegex(boolean on) {
|
|
||||||
allowFileRegex = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> age(String value) {
|
public Predicate<ChangeData> age(String value) {
|
||||||
return new AgePredicate(args.dbProvider, value);
|
return new AgePredicate(args.dbProvider, value);
|
||||||
@ -243,7 +238,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
|
|
||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> comment(String value) throws QueryParseException {
|
public Predicate<ChangeData> comment(String value) throws QueryParseException {
|
||||||
ChangeIndex index = requireIndex(FIELD_COMMENT, value);
|
ChangeIndex index = args.indexes.getSearchIndex();
|
||||||
return new CommentPredicate(args.dbProvider, index, value);
|
return new CommentPredicate(args.dbProvider, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +302,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("mergeable".equalsIgnoreCase(value)) {
|
if ("mergeable".equalsIgnoreCase(value)) {
|
||||||
requireIndex(FIELD_IS, "mergeable");
|
|
||||||
return new IsMergeablePredicate(args.dbProvider);
|
return new IsMergeablePredicate(args.dbProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +323,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> conflicts(String value) throws OrmException,
|
public Predicate<ChangeData> conflicts(String value) throws OrmException,
|
||||||
QueryParseException {
|
QueryParseException {
|
||||||
requireIndex(FIELD_CONFLICTS, value);
|
|
||||||
return new ConflictsPredicate(args.dbProvider, args.patchListCache,
|
return new ConflictsPredicate(args.dbProvider, args.patchListCache,
|
||||||
args.submitStrategyFactory, args.changeControlGenericFactory,
|
args.submitStrategyFactory, args.changeControlGenericFactory,
|
||||||
args.userFactory, args.repoManager, args.projectCache,
|
args.userFactory, args.repoManager, args.projectCache,
|
||||||
@ -389,12 +382,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> file(String file) throws QueryParseException {
|
public Predicate<ChangeData> file(String file) throws QueryParseException {
|
||||||
if (file.startsWith("^")) {
|
if (file.startsWith("^")) {
|
||||||
if (!allowFileRegex) {
|
|
||||||
requireIndex(FIELD_FILE, file);
|
|
||||||
}
|
|
||||||
return new RegexFilePredicate(args.dbProvider, args.patchListCache, file);
|
return new RegexFilePredicate(args.dbProvider, args.patchListCache, file);
|
||||||
} else {
|
} else {
|
||||||
requireIndex(FIELD_FILE, file);
|
|
||||||
return new EqualsFilePredicate(args.dbProvider, args.patchListCache, file);
|
return new EqualsFilePredicate(args.dbProvider, args.patchListCache, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,10 +445,6 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> message(String text) throws QueryParseException {
|
public Predicate<ChangeData> message(String text) throws QueryParseException {
|
||||||
ChangeIndex index = args.indexes.getSearchIndex();
|
ChangeIndex index = args.indexes.getSearchIndex();
|
||||||
if (index == null) {
|
|
||||||
return new LegacyMessagePredicate(args.dbProvider, args.repoManager, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MessagePredicate(args.dbProvider, index, text);
|
return new MessagePredicate(args.dbProvider, index, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,13 +738,4 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
}
|
}
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangeIndex requireIndex(String field, String value)
|
|
||||||
throws QueryParseException {
|
|
||||||
ChangeIndex idx = args.indexes.getSearchIndex();
|
|
||||||
if (idx == null) {
|
|
||||||
throw error("secondary index must be enabled for " + field + ":" + value);
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
// Copyright (C) 2013 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.query.change;
|
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
|
||||||
import org.eclipse.jgit.errors.MissingObjectException;
|
|
||||||
import org.eclipse.jgit.lib.Repository;
|
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
|
||||||
import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
|
|
||||||
import org.eclipse.jgit.revwalk.filter.RevFilter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Predicate to match changes that contains specified text in commit messages
|
|
||||||
* body.
|
|
||||||
*/
|
|
||||||
public class LegacyMessagePredicate extends RevWalkPredicate {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory
|
|
||||||
.getLogger(LegacyMessagePredicate.class);
|
|
||||||
|
|
||||||
private final RevFilter rFilter;
|
|
||||||
|
|
||||||
public LegacyMessagePredicate(Provider<ReviewDb> db,
|
|
||||||
GitRepositoryManager repoManager, String text) {
|
|
||||||
super(db, repoManager, ChangeQueryBuilder.FIELD_MESSAGE, text);
|
|
||||||
this.rFilter = MessageRevFilter.create(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(Repository repo, RevWalk rw, Arguments args) {
|
|
||||||
try {
|
|
||||||
return rFilter.include(rw, rw.parseCommit(args.objectId));
|
|
||||||
} catch (MissingObjectException e) {
|
|
||||||
log.error(args.projectName.get() + "\" commit does not exist.", e);
|
|
||||||
} catch (IncorrectObjectTypeException e) {
|
|
||||||
log.error(args.projectName.get() + "\" revision is not a commit.", e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error(
|
|
||||||
"Could not search for commit message in \"" + args.projectName.get()
|
|
||||||
+ "\" repository.", e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCost() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,658 +0,0 @@
|
|||||||
// Copyright (C) 2009 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.query.change;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
|
||||||
import com.google.gerrit.reviewdb.server.ChangeAccess;
|
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
|
||||||
import com.google.gerrit.server.query.IntPredicate;
|
|
||||||
import com.google.gerrit.server.query.Predicate;
|
|
||||||
import com.google.gerrit.server.query.QueryRewriter;
|
|
||||||
import com.google.gerrit.server.query.RewritePredicate;
|
|
||||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder.LimitPredicate;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
|
||||||
import com.google.gwtorm.server.ResultSet;
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.name.Named;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public class SqlRewriterImpl extends BasicChangeRewrites
|
|
||||||
implements ChangeQueryRewriter {
|
|
||||||
private static final QueryRewriter.Definition<ChangeData, SqlRewriterImpl> mydef =
|
|
||||||
new QueryRewriter.Definition<ChangeData, SqlRewriterImpl>(
|
|
||||||
SqlRewriterImpl.class, BUILDER);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
@VisibleForTesting
|
|
||||||
public SqlRewriterImpl(Provider<ReviewDb> dbProvider) {
|
|
||||||
super(mydef, dbProvider, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Predicate<ChangeData> and(Collection<? extends Predicate<ChangeData>> l) {
|
|
||||||
return hasSource(l) ? new AndSource(dbProvider, l) : super.and(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Predicate<ChangeData> or(Collection<? extends Predicate<ChangeData>> l) {
|
|
||||||
return hasSource(l) ? new OrSource(l) : super.or(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:open P=(project:*) B=(ref:*)")
|
|
||||||
public Predicate<ChangeData> r05_byBranchOpen(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("B") final RefPredicate b) {
|
|
||||||
return new ChangeSource(500) {
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byBranchOpenAll(
|
|
||||||
new Branch.NameKey(p.getValueKey(), b.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen()
|
|
||||||
&& p.match(cd)
|
|
||||||
&& b.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:merged P=(project:*) B=(ref:*) S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r05_byBranchMergedPrev(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("B") final RefPredicate b,
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byBranchClosedPrev(Change.Status.MERGED.getCode(), //
|
|
||||||
new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& b.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:merged P=(project:*) B=(ref:*) S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r05_byBranchMergedNext(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("B") final RefPredicate b,
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byBranchClosedNext(Change.Status.MERGED.getCode(), //
|
|
||||||
new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& b.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectOpenPrev(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(500, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectOpenPrev(p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen() //
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:open P=(project:*) S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectOpenNext(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(500, s.getValue(), l.intValue()) {
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectOpenNext(p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen() //
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:merged P=(project:*) S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectMergedPrev(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectClosedPrev(Change.Status.MERGED.getCode(), //
|
|
||||||
p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:merged P=(project:*) S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectMergedNext(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectClosedNext(Change.Status.MERGED.getCode(), //
|
|
||||||
p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:abandoned P=(project:*) S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectAbandonedPrev(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectClosedPrev(Change.Status.ABANDONED.getCode(), //
|
|
||||||
p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:abandoned P=(project:*) S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r10_byProjectAbandonedNext(
|
|
||||||
@Named("P") final ProjectPredicate p,
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(40000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.byProjectClosedNext(Change.Status.ABANDONED.getCode(), //
|
|
||||||
p.getValueKey(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
|
|
||||||
&& p.match(cd) //
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:open S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byOpenPrev(
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(2000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allOpenPrev(key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:open S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byOpenNext(
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(2000, s.getValue(), l.intValue()) {
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allOpenNext(key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:merged S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byMergedPrev(
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(50000, s.getValue(), l.intValue()) {
|
|
||||||
{
|
|
||||||
init("r20_byMergedPrev", s, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allClosedPrev(Change.Status.MERGED.getCode(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:merged S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byMergedNext(
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(50000, s.getValue(), l.intValue()) {
|
|
||||||
{
|
|
||||||
init("r20_byMergedNext", s, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allClosedNext(Change.Status.MERGED.getCode(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.MERGED
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:abandoned S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byAbandonedPrev(
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(50000, s.getValue(), l.intValue()) {
|
|
||||||
{
|
|
||||||
init("r20_byAbandonedPrev", s, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allClosedPrev(Change.Status.ABANDONED.getCode(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:abandoned S=(sortkey_before:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byAbandonedNext(
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return new PaginatedSource(50000, s.getValue(), l.intValue()) {
|
|
||||||
{
|
|
||||||
init("r20_byAbandonedNext", s, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException {
|
|
||||||
return a.allClosedNext(Change.Status.ABANDONED.getCode(), key, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
|
|
||||||
&& s.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byClosedPrev(
|
|
||||||
@Named("S") final SortKeyPredicate.After s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return or(r20_byMergedPrev(s, l), r20_byAbandonedPrev(s, l));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
|
|
||||||
public Predicate<ChangeData> r20_byClosedNext(
|
|
||||||
@Named("S") final SortKeyPredicate.Before s,
|
|
||||||
@Named("L") final IntPredicate<ChangeData> l) {
|
|
||||||
return or(r20_byMergedNext(s, l), r20_byAbandonedNext(s, l));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:open O=(owner:*)")
|
|
||||||
public Predicate<ChangeData> r25_byOwnerOpen(
|
|
||||||
@Named("O") final OwnerPredicate o) {
|
|
||||||
return new ChangeSource(50) {
|
|
||||||
{
|
|
||||||
init("r25_byOwnerOpen", o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a) throws OrmException {
|
|
||||||
return a.byOwnerOpen(o.getAccountId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isOpen() && o.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:closed O=(owner:*)")
|
|
||||||
public Predicate<ChangeData> r25_byOwnerClosed(
|
|
||||||
@Named("O") final OwnerPredicate o) {
|
|
||||||
return new ChangeSource(5000) {
|
|
||||||
{
|
|
||||||
init("r25_byOwnerClosed", o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a) throws OrmException {
|
|
||||||
return a.byOwnerClosedAll(o.getAccountId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus().isClosed() && o.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("O=(owner:*)")
|
|
||||||
public Predicate<ChangeData> r26_byOwner(@Named("O") OwnerPredicate o) {
|
|
||||||
return or(r25_byOwnerOpen(o), r25_byOwnerClosed(o));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:open R=(reviewer:*)")
|
|
||||||
public Predicate<ChangeData> r30_byReviewerOpen(
|
|
||||||
@Named("R") final ReviewerPredicate r) {
|
|
||||||
return new Source() {
|
|
||||||
{
|
|
||||||
init("r30_byReviewerOpen", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public ResultSet<ChangeData> read() throws OrmException {
|
|
||||||
return ChangeDataResultSet.patchSetApproval(dbProvider.get()
|
|
||||||
.patchSetApprovals().openByUser(r.getAccountId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
Change change = cd.change(dbProvider);
|
|
||||||
return change != null && change.getStatus().isOpen() && r.match(cd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCardinality() {
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCost() {
|
|
||||||
return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("status:closed R=(reviewer:*)")
|
|
||||||
public Predicate<ChangeData> r30_byReviewerClosed(
|
|
||||||
@Named("R") final ReviewerPredicate r) {
|
|
||||||
return new Source() {
|
|
||||||
{
|
|
||||||
init("r30_byReviewerClosed", r);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public ResultSet<ChangeData> read() throws OrmException {
|
|
||||||
return ChangeDataResultSet.patchSetApproval(dbProvider.get()
|
|
||||||
.patchSetApprovals().closedByUserAll(r.getAccountId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
Change change = cd.change(dbProvider);
|
|
||||||
return change != null && change.getStatus().isClosed() && r.match(cd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCardinality() {
|
|
||||||
return 5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCost() {
|
|
||||||
return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Rewrite("R=(reviewer:*)")
|
|
||||||
public Predicate<ChangeData> r31_byReviewer(
|
|
||||||
@Named("R") final ReviewerPredicate r) {
|
|
||||||
return or(r30_byReviewerOpen(r), r30_byReviewerClosed(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:closed")
|
|
||||||
public Predicate<ChangeData> r99_allClosed() {
|
|
||||||
return r20_byClosedNext(
|
|
||||||
new SortKeyPredicate.Before(null, dbProvider, "z"),
|
|
||||||
new LimitPredicate(Integer.MAX_VALUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("status:submitted")
|
|
||||||
public Predicate<ChangeData> r99_allSubmitted() {
|
|
||||||
return new ChangeSource(50) {
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a) throws OrmException {
|
|
||||||
return a.allSubmitted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return cd.change(dbProvider).getStatus() == Change.Status.SUBMITTED;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rewrite("P=(project:*)")
|
|
||||||
public Predicate<ChangeData> r99_byProject(
|
|
||||||
@Named("P") final ProjectPredicate p) {
|
|
||||||
return new ChangeSource(1000000) {
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a) throws OrmException {
|
|
||||||
return a.byProject(p.getValueKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean match(ChangeData cd) throws OrmException {
|
|
||||||
return p.match(cd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean hasSource(Collection<? extends Predicate<ChangeData>> l) {
|
|
||||||
for (Predicate<ChangeData> p : l) {
|
|
||||||
if (p instanceof ChangeDataSource) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract static class Source extends RewritePredicate<ChangeData>
|
|
||||||
implements ChangeDataSource {
|
|
||||||
@Override
|
|
||||||
public boolean hasChange() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class ChangeSource extends Source {
|
|
||||||
private final int cardinality;
|
|
||||||
|
|
||||||
ChangeSource(int card) {
|
|
||||||
this.cardinality = card;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract ResultSet<Change> scan(ChangeAccess a) throws OrmException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResultSet<ChangeData> read() throws OrmException {
|
|
||||||
return ChangeDataResultSet.change(scan(dbProvider.get().changes()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChange() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCardinality() {
|
|
||||||
return cardinality;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCost() {
|
|
||||||
return ChangeCosts.cost(ChangeCosts.CHANGES_SCAN, getCardinality());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class PaginatedSource extends ChangeSource implements
|
|
||||||
Paginated {
|
|
||||||
private final String startKey;
|
|
||||||
private final int limit;
|
|
||||||
|
|
||||||
PaginatedSource(int card, String start, int lim) {
|
|
||||||
super(card);
|
|
||||||
this.startKey = start;
|
|
||||||
this.limit = lim;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int limit() {
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
ResultSet<Change> scan(ChangeAccess a) throws OrmException {
|
|
||||||
return scan(a, startKey, limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResultSet<ChangeData> restart(ChangeData last) throws OrmException {
|
|
||||||
return ChangeDataResultSet.change(scan(dbProvider.get().changes(), //
|
|
||||||
last.change(dbProvider).getSortKey(), //
|
|
||||||
limit));
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract ResultSet<Change> scan(ChangeAccess a, String key, int limit)
|
|
||||||
throws OrmException;
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,21 +14,14 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.query.change;
|
package com.google.gerrit.server.query.change;
|
||||||
|
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
|
||||||
import com.google.gerrit.reviewdb.client.TrackingId;
|
import com.google.gerrit.reviewdb.client.TrackingId;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
import com.google.gerrit.server.index.ChangeField;
|
import com.google.gerrit.server.index.ChangeField;
|
||||||
import com.google.gerrit.server.index.IndexPredicate;
|
import com.google.gerrit.server.index.IndexPredicate;
|
||||||
import com.google.gwtorm.server.ListResultSet;
|
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.gwtorm.server.ResultSet;
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
class TrackingIdPredicate extends IndexPredicate<ChangeData> {
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
class TrackingIdPredicate extends IndexPredicate<ChangeData> implements
|
|
||||||
ChangeDataSource {
|
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
|
|
||||||
TrackingIdPredicate(Provider<ReviewDb> db, String trackingId) {
|
TrackingIdPredicate(Provider<ReviewDb> db, String trackingId) {
|
||||||
@ -46,34 +39,10 @@ class TrackingIdPredicate extends IndexPredicate<ChangeData> implements
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public ResultSet<ChangeData> read() throws OrmException {
|
|
||||||
HashSet<Change.Id> ids = new HashSet<Change.Id>();
|
|
||||||
for (TrackingId sc : db.get().trackingIds() //
|
|
||||||
.byTrackingId(new TrackingId.Id(getValue()))) {
|
|
||||||
ids.add(sc.getChangeId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<ChangeData> r = new ArrayList<ChangeData>(ids.size());
|
|
||||||
for (Change.Id id : ids) {
|
|
||||||
r.add(new ChangeData(id));
|
|
||||||
}
|
|
||||||
return new ListResultSet<ChangeData>(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasChange() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCardinality() {
|
|
||||||
return ChangeCosts.CARD_TRACKING_IDS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCost() {
|
public int getCost() {
|
||||||
return ChangeCosts.cost(ChangeCosts.TR_SCAN, getCardinality());
|
return ChangeCosts.cost(
|
||||||
|
ChangeCosts.TR_SCAN,
|
||||||
|
ChangeCosts.CARD_TRACKING_IDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ import com.google.gerrit.reviewdb.client.Change;
|
|||||||
import com.google.gerrit.server.query.AndPredicate;
|
import com.google.gerrit.server.query.AndPredicate;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryParseException;
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
import com.google.gerrit.server.query.RewritePredicate;
|
|
||||||
import com.google.gerrit.server.query.change.AndSource;
|
import com.google.gerrit.server.query.change.AndSource;
|
||||||
|
import com.google.gerrit.server.query.change.BasicChangeRewrites;
|
||||||
import com.google.gerrit.server.query.change.ChangeData;
|
import com.google.gerrit.server.query.change.ChangeData;
|
||||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
||||||
import com.google.gerrit.server.query.change.OrSource;
|
import com.google.gerrit.server.query.change.OrSource;
|
||||||
import com.google.gerrit.server.query.change.SqlRewriterImpl;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -56,8 +56,7 @@ public class IndexRewriteTest {
|
|||||||
rewrite = new IndexRewriteImpl(
|
rewrite = new IndexRewriteImpl(
|
||||||
indexes,
|
indexes,
|
||||||
null,
|
null,
|
||||||
new IndexRewriteImpl.BasicRewritesImpl(null, indexes),
|
new BasicChangeRewrites(null, indexes));
|
||||||
new SqlRewriterImpl(null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -202,19 +201,6 @@ public class IndexRewriteTest {
|
|||||||
out.getChildren());
|
out.getChildren());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNoChangeIndexUsesSqlRewrites() throws Exception {
|
|
||||||
Predicate<ChangeData> in = parse("status:open project:p ref:b");
|
|
||||||
Predicate<ChangeData> out;
|
|
||||||
|
|
||||||
out = rewrite(in);
|
|
||||||
assertTrue(out instanceof AndPredicate || out instanceof IndexedChangeQuery);
|
|
||||||
|
|
||||||
indexes.setSearchIndex(null);
|
|
||||||
out = rewrite(in);
|
|
||||||
assertTrue(out instanceof RewritePredicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Predicate<ChangeData> parse(String query) throws QueryParseException {
|
private Predicate<ChangeData> parse(String query) throws QueryParseException {
|
||||||
return queryBuilder.parse(query);
|
return queryBuilder.parse(query);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
// Copyright (C) 2013 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.query.change;
|
|
||||||
|
|
||||||
import com.google.gerrit.testutil.InMemoryModule;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
import org.eclipse.jgit.lib.Config;
|
|
||||||
|
|
||||||
public class SqlQueryChangesTest extends AbstractQueryChangesTest {
|
|
||||||
protected Injector createInjector() {
|
|
||||||
Config cfg = InMemoryModule.newDefaultConfig();
|
|
||||||
cfg.setString("index", null, "type", "sql");
|
|
||||||
return Guice.createInjector(new InMemoryModule(cfg));
|
|
||||||
}
|
|
||||||
}
|
|
@ -43,7 +43,6 @@ import com.google.gerrit.server.git.GitRepositoryManager;
|
|||||||
import com.google.gerrit.server.git.PerThreadRequestScope;
|
import com.google.gerrit.server.git.PerThreadRequestScope;
|
||||||
import com.google.gerrit.server.index.ChangeSchemas;
|
import com.google.gerrit.server.index.ChangeSchemas;
|
||||||
import com.google.gerrit.server.index.IndexModule.IndexType;
|
import com.google.gerrit.server.index.IndexModule.IndexType;
|
||||||
import com.google.gerrit.server.index.NoIndexModule;
|
|
||||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
||||||
import com.google.gerrit.server.mail.SmtpEmailSender;
|
import com.google.gerrit.server.mail.SmtpEmailSender;
|
||||||
import com.google.gerrit.server.schema.Current;
|
import com.google.gerrit.server.schema.Current;
|
||||||
@ -83,6 +82,9 @@ public class InMemoryModule extends FactoryModule {
|
|||||||
cfg.setString("user", null, "email", "gerrit@localhost");
|
cfg.setString("user", null, "email", "gerrit@localhost");
|
||||||
cfg.setBoolean("sendemail", null, "enable", false);
|
cfg.setBoolean("sendemail", null, "enable", false);
|
||||||
cfg.setString("cache", null, "directory", null);
|
cfg.setString("cache", null, "directory", null);
|
||||||
|
cfg.setString("index", null, "type", "lucene");
|
||||||
|
cfg.setBoolean("index", "lucene", "testInmemory", true);
|
||||||
|
cfg.setInt("index", "lucene", "testVersion", 4);
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ public class InMemoryModule extends FactoryModule {
|
|||||||
|
|
||||||
IndexType indexType = null;
|
IndexType indexType = null;
|
||||||
try {
|
try {
|
||||||
indexType = cfg.getEnum("index", null, "type", IndexType.SQL);
|
indexType = cfg.getEnum("index", null, "type", IndexType.LUCENE);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// Custom index type, caller must provide their own module.
|
// Custom index type, caller must provide their own module.
|
||||||
}
|
}
|
||||||
@ -164,9 +166,6 @@ public class InMemoryModule extends FactoryModule {
|
|||||||
case LUCENE:
|
case LUCENE:
|
||||||
install(luceneIndexModule());
|
install(luceneIndexModule());
|
||||||
break;
|
break;
|
||||||
case SQL:
|
|
||||||
install(new NoIndexModule());
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new ProvisionException(
|
throw new ProvisionException(
|
||||||
"index type unsupported in tests: " + indexType);
|
"index type unsupported in tests: " + indexType);
|
||||||
|
@ -40,7 +40,6 @@ import com.google.gerrit.server.git.LocalDiskRepositoryManager;
|
|||||||
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
|
import com.google.gerrit.server.git.ReceiveCommitsExecutorModule;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.index.IndexModule;
|
import com.google.gerrit.server.index.IndexModule;
|
||||||
import com.google.gerrit.server.index.NoIndexModule;
|
|
||||||
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
|
||||||
import com.google.gerrit.server.mail.SmtpEmailSender;
|
import com.google.gerrit.server.mail.SmtpEmailSender;
|
||||||
import com.google.gerrit.server.patch.IntraLineWorkerPool;
|
import com.google.gerrit.server.patch.IntraLineWorkerPool;
|
||||||
@ -268,7 +267,7 @@ public class WebAppInitializer extends GuiceServletContextListener
|
|||||||
changeIndexModule = new SolrIndexModule();
|
changeIndexModule = new SolrIndexModule();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
changeIndexModule = new NoIndexModule();
|
throw new IllegalStateException("unsupported index.type");
|
||||||
}
|
}
|
||||||
modules.add(changeIndexModule);
|
modules.add(changeIndexModule);
|
||||||
modules.add(new CanonicalWebUrlModule() {
|
modules.add(new CanonicalWebUrlModule() {
|
||||||
|
Loading…
Reference in New Issue
Block a user