Merge "Console log and reporting on invalid comment ranges"
diff --git a/.gitignore b/.gitignore
index e702ac9..1b93f20a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
.DS_Store
.gwt_work_dir
/.apt_generated
+/.bazel_path
/.buckd
/.classpath
/.factorypath
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index b0a07c7..6a01607 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1543,6 +1543,10 @@
+
Connect to a MySQL database server.
+
+* `MARIADB`
++
+Connect to a MariaDB database server.
++
* `ORACLE`
+
Connect to an Oracle database server.
diff --git a/Documentation/database-setup.txt b/Documentation/database-setup.txt
index 8667f43..3fd0c91 100644
--- a/Documentation/database-setup.txt
+++ b/Documentation/database-setup.txt
@@ -74,6 +74,14 @@
Visit MySQL's link:http://dev.mysql.com/doc/[documentation] for further
information regarding using MySQL.
+[[createdb_mariadb]]
+=== MariaDB
+
+Refer to MySQL section above how to create MariaDB database.
+
+Visit MariaDB's link:https://mariadb.com/kb/en/mariadb/[documentation] for further
+information regarding using MariaDB.
+
[[createdb_oracle]]
=== Oracle
diff --git a/WORKSPACE b/WORKSPACE
index a74a29d..fc074fc 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -186,15 +186,15 @@
maven_jar(
name = "gwtorm_client",
- artifact = "com.google.gerrit:gwtorm:1.17",
- sha1 = "97bdc872f00388910c9af70771f07bbb32f1b949",
- src_sha1 = "889e35d7295b1af49161a28daaea9905ffa76a63",
+ artifact = "com.google.gerrit:gwtorm:1.18",
+ sha1 = "f326dec463439a92ccb32f05b38345e21d0b5ecf",
+ src_sha1 = "e0b973d5cafef3d145fa80cdf032fcead1186d29",
)
maven_jar(
name = "protobuf",
- artifact = "com.google.protobuf:protobuf-java:2.5.0",
- sha1 = "a10732c76bfacdbd633a7eb0f7968b1059a65dfa",
+ artifact = "com.google.protobuf:protobuf-java:3.0.0-beta-2",
+ sha1 = "de80fe047052445869b96f6def6baca7182c95af",
)
maven_jar(
@@ -595,8 +595,14 @@
# Keep this version of Soy synchronized with the version used in Gitiles.
maven_jar(
name = "soy",
- artifact = "com.google.template:soy:2016-08-09",
- sha1 = "43d33651e95480d515fe26c10a662faafe3ad1e4",
+ artifact = "com.google.template:soy:2017-02-01",
+ sha1 = "8638940b207779fe3b75e55b6e65abbefb6af678",
+)
+
+maven_jar(
+ name = "html_types",
+ artifact = "com.google.common.html.types:types:1.0.4",
+ sha1 = "2adf4c8bfccc0ff7346f9186ac5aa57d829ad065",
)
maven_jar(
@@ -607,8 +613,8 @@
maven_jar(
name = "dropwizard_core",
- artifact = "io.dropwizard.metrics:metrics-core:3.1.2",
- sha1 = "224f03afd2521c6c94632f566beb1bb5ee32cf07",
+ artifact = "io.dropwizard.metrics:metrics-core:3.2.1",
+ sha1 = "f453a6b2660c369c62b83ded443391ae1bfd23a0",
)
# This version must match the version that also appears in
@@ -900,23 +906,23 @@
maven_jar(
name = "elasticsearch",
- artifact = "org.elasticsearch:elasticsearch:2.4.0",
- sha1 = "aeb9704a76fa8654c348f38fcbb993a952a7ab07",
+ artifact = "org.elasticsearch:elasticsearch:2.4.4",
+ sha1 = "e69930bc794c539d34778e665d6f8ccbffd42c6f",
)
# Java REST client for Elasticsearch.
-JEST_VERSION = "2.0.3"
+JEST_VERSION = "2.4.0"
maven_jar(
name = "jest_common",
artifact = "io.searchbox:jest-common:" + JEST_VERSION,
- sha1 = "f304c66894aaf2f6c17a886bc826f09c7a161cf9",
+ sha1 = "ea779ebe7c438a53dce431f85b0d4e1d8faee2ac",
)
maven_jar(
name = "jest",
artifact = "io.searchbox:jest:" + JEST_VERSION,
- sha1 = "b8f9ed1423489b361804e47f640515ea9f1fa08d",
+ sha1 = "e2a604a584e6633545ac6b1fe99ef888ab96dae9",
)
maven_jar(
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 2131142..24b3724 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -648,28 +648,32 @@
String changeId, String ref, TestAccount testAccount, TestRepository<?> repo)
throws Exception {
Collections.shuffle(RANDOM);
- return amendChange(changeId, ref, testAccount, repo, PushOneCommit.SUBJECT,
- PushOneCommit.FILE_NAME, new String(Chars.toArray(RANDOM)));
+ return amendChange(
+ changeId,
+ ref,
+ testAccount,
+ repo,
+ PushOneCommit.SUBJECT,
+ PushOneCommit.FILE_NAME,
+ new String(Chars.toArray(RANDOM)));
}
- protected PushOneCommit.Result amendChange(String changeId, String subject, String fileName,
- String content) throws Exception {
+ protected PushOneCommit.Result amendChange(
+ String changeId, String subject, String fileName, String content) throws Exception {
return amendChange(changeId, "refs/for/master", admin, testRepo, subject, fileName, content);
}
protected PushOneCommit.Result amendChange(
- String changeId, String ref, TestAccount testAccount, TestRepository<?> repo, String subject,
- String fileName, String content)
+ String changeId,
+ String ref,
+ TestAccount testAccount,
+ TestRepository<?> repo,
+ String subject,
+ String fileName,
+ String content)
throws Exception {
PushOneCommit push =
- pushFactory.create(
- db,
- testAccount.getIdent(),
- repo,
- subject,
- fileName,
- content,
- changeId);
+ pushFactory.create(db, testAccount.getIdent(), repo, subject, fileName, content, changeId);
return push.to(ref);
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
index a395132..d137fba3 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -99,6 +99,17 @@
}
@Test
+ public void addMembersWithAtSign() throws Exception {
+ String g = createGroup("users");
+ TestAccount u10 = accounts.create("u10", "u10@example.com", "Full Name 10");
+ TestAccount u11_at =
+ accounts.create("u11@something", "u11@example.com", "Full Name 11 With At");
+ TestAccount u11 = accounts.create("u11", "u11.another@example.com", "Full Name 11 Without At");
+ gApi.groups().id(g).addMembers(u10.username, u11_at.username);
+ assertMembers(g, u10, u11_at);
+ }
+
+ @Test
public void includeRemoveGroup() throws Exception {
String p = createGroup("parent");
String g = createGroup("newGroup");
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
index 77ca14f..d8aa35c 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
@@ -419,8 +419,8 @@
RevCommit headAfterChange1 = change1.getCommit();
PushOneCommit.Result change2 = createChange("subject 2", "fileName 2", "content 2");
testRepo.reset(headAfterChange1);
- change1 = amendChange(change1.getChangeId(), "subject 1 amend", "fileName 2",
- "rework content 2");
+ change1 =
+ amendChange(change1.getChangeId(), "subject 1 amend", "fileName 2", "rework content 2");
submit(change1.getChangeId());
headAfterChange1 = getRemoteHead();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
index ab543e8..112c578 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
@@ -23,26 +23,38 @@
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.common.GroupInfo;
+import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.account.WatchConfig;
import com.google.gerrit.server.account.WatchConfig.NotifyType;
+import com.google.gerrit.server.account.WatchConfig.ProjectWatchKey;
import com.google.gerrit.server.git.NotifyConfig;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.mail.Address;
import com.google.gerrit.testutil.FakeEmailSender.Message;
+import com.google.inject.Inject;
+import java.util.Collections;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.junit.Test;
+
@NoHttpd
@Sandboxed
public class ProjectWatchIT extends AbstractDaemonTest {
+ @Inject private WatchConfig.Accessor watchConfig;
+
@Test
public void newPatchSetsNotifyConfig() throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
@@ -480,4 +492,34 @@
// assert email notification
assertThat(sender.getMessages()).isEmpty();
}
+
+ @Test
+ public void deleteAllProjectWatches() throws Exception {
+ Map<ProjectWatchKey, Set<NotifyType>> watches = new HashMap<>();
+ watches.put(ProjectWatchKey.create(project, "*"), ImmutableSet.of(NotifyType.ALL));
+ watchConfig.upsertProjectWatches(admin.getId(), watches);
+ assertThat(watchConfig.getProjectWatches(admin.getId())).isNotEmpty();
+
+ watchConfig.deleteAllProjectWatches(admin.getId());
+ assertThat(watchConfig.getProjectWatches(admin.getId())).isEmpty();
+ }
+
+ @Test
+ public void deleteAllProjectWatchesIfWatchConfigIsTheOnlyFileInUserBranch() throws Exception {
+ // Create account that has no files in its refs/users/ branch.
+ Account.Id id = new Account.Id(db.nextAccountId());
+ Account a = new Account(id, TimeUtil.nowTs());
+ db.accounts().insert(Collections.singleton(a));
+
+ // Add a project watch so that a watch.config file in the refs/users/ branch is created.
+ Map<ProjectWatchKey, Set<NotifyType>> watches = new HashMap<>();
+ watches.put(ProjectWatchKey.create(project, "*"), ImmutableSet.of(NotifyType.ALL));
+ watchConfig.upsertProjectWatches(id, watches);
+ assertThat(watchConfig.getProjectWatches(id)).isNotEmpty();
+
+ // Delete all project watches so that the watch.config file in the refs/users/ branch is
+ // deleted.
+ watchConfig.deleteAllProjectWatches(id);
+ assertThat(watchConfig.getProjectWatches(id)).isEmpty();
+ }
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java
index 77a0a5f..1ac42d1 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/IoUtil.java
@@ -26,6 +26,7 @@
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Set;
@@ -54,7 +55,7 @@
}.start();
}
- public static void loadJARs(Iterable<Path> jars) {
+ public static void loadJARs(Collection<Path> jars) {
ClassLoader cl = IoUtil.class.getClassLoader();
if (!(cl instanceof URLClassLoader)) {
throw noAddURL("Not loaded by URLClassLoader", null);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/PluginServletContext.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
index a5ba2e8..53b49a4 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/plugins/PluginServletContext.java
@@ -39,7 +39,7 @@
return (ServletContext)
Proxy.newProxyInstance(
PluginServletContext.class.getClassLoader(),
- new Class[] {ServletContext.class, API.class},
+ new Class<?>[] {ServletContext.class, API.class},
new Handler(plugin, contextPath));
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java
index d2e3b58..85453fb 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java
@@ -14,6 +14,7 @@
package com.google.gerrit.httpd.raw;
+import static com.google.common.base.MoreObjects.firstNonNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.escape.Escaper;
@@ -25,7 +26,10 @@
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
+import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
@@ -117,8 +121,24 @@
}
}
- private ProcessBuilder newBuildProcess(Label label) {
- return new ProcessBuilder("bazel", "build", label.fullName());
+ private Properties loadBuildProperties(Path propPath) throws IOException {
+ Properties properties = new Properties();
+ try (InputStream in = Files.newInputStream(propPath)) {
+ properties.load(in);
+ } catch (NoSuchFileException e) {
+ // Ignore; will be run from PATH, with a descriptive error if it fails.
+ }
+ return properties;
+ }
+
+ private ProcessBuilder newBuildProcess(Label label) throws IOException {
+ Properties properties = loadBuildProperties(sourceRoot.resolve(".bazel_path"));
+ String bazel = firstNonNull(properties.getProperty("bazel"), "bazel");
+ ProcessBuilder proc = new ProcessBuilder(bazel, "build", label.fullName());
+ if (properties.containsKey("PATH")) {
+ proc.environment().put("PATH", properties.getProperty("PATH"));
+ }
+ return proc;
}
/** returns the root relative path to the artifact for the given label */
diff --git a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
index eecaf36..a7af056 100644
--- a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
+++ b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -54,7 +54,7 @@
/** Main class for a JAR file to run code from "WEB-INF/lib". */
public final class GerritLauncher {
- private static final String pkg = "com.google.gerrit.pgm";
+ private static final String PKG = "com.google.gerrit.pgm";
public static final String NOT_ARCHIVED = "NOT_ARCHIVED";
private static ClassLoader daemonClassLoader;
@@ -173,17 +173,17 @@
try {
try {
String cn = programClassName(name);
- clazz = Class.forName(pkg + "." + cn, true, loader);
+ clazz = Class.forName(PKG + "." + cn, true, loader);
} catch (ClassNotFoundException cnfe) {
if (name.equals(name.toLowerCase())) {
- clazz = Class.forName(pkg + "." + name, true, loader);
+ clazz = Class.forName(PKG + "." + name, true, loader);
} else {
throw cnfe;
}
}
} catch (ClassNotFoundException cnfe) {
System.err.println("fatal: unknown command " + name);
- System.err.println(" (no " + pkg + "." + name + ")");
+ System.err.println(" (no " + PKG + "." + name + ")");
return 1;
}
@@ -200,7 +200,8 @@
if ((main.getModifiers() & Modifier.STATIC) == Modifier.STATIC) {
res = main.invoke(null, new Object[] {argv});
} else {
- res = main.invoke(clazz.getConstructor(new Class[] {}).newInstance(), new Object[] {argv});
+ res =
+ main.invoke(clazz.getConstructor(new Class<?>[] {}).newInstance(), new Object[] {argv});
}
} catch (InvocationTargetException ite) {
if (ite.getCause() instanceof Exception) {
@@ -604,7 +605,7 @@
return resolveInSourceRoot("eclipse-out");
}
- static String SOURCE_ROOT_RESOURCE = "/gerrit-launcher/workspace-root.txt";
+ static final String SOURCE_ROOT_RESOURCE = "/gerrit-launcher/workspace-root.txt";
/**
* Locate a path in the source tree.
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java
index 45206c9..b80bf35 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java
@@ -40,6 +40,9 @@
.annotatedWith(Names.named("jdbc"))
.to(JDBCInitializer.class);
bind(DatabaseConfigInitializer.class)
+ .annotatedWith(Names.named("mariadb"))
+ .to(MariaDbInitializer.class);
+ bind(DatabaseConfigInitializer.class)
.annotatedWith(Names.named("mysql"))
.to(MySqlInitializer.class);
bind(DatabaseConfigInitializer.class)
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitDatabase.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitDatabase.java
index 5565158..349ab55 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitDatabase.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitDatabase.java
@@ -85,6 +85,8 @@
if (dci instanceof MySqlInitializer) {
libraries.mysqlDriver.downloadRequired();
+ } else if (dci instanceof MariaDbInitializer) {
+ libraries.mariadbDriver.downloadRequired();
} else if (dci instanceof OracleInitializer) {
libraries.oracleDriver.downloadRequired();
} else if (dci instanceof DB2Initializer) {
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
index 4659ee3..e3a1d66 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/JDBCInitializer.java
@@ -37,6 +37,8 @@
database.set("driver", "org.apache.derby.jdbc.EmbeddedDriver");
} else if (url.startsWith("jdbc:h2:")) {
database.set("driver", "org.h2.Driver");
+ } else if (url.startsWith("jdbc:mariadb:")) {
+ database.set("driver", "org.mariadb.jdbc.Driver");
} else if (url.startsWith("jdbc:mysql:")) {
database.set("driver", "com.mysql.jdbc.Driver");
} else if (url.startsWith("jdbc:postgresql:")) {
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Libraries.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Libraries.java
index 526f172..3259f96 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Libraries.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/Libraries.java
@@ -43,6 +43,7 @@
/* final */ LibraryDownloader db2Driver;
/* final */ LibraryDownloader db2DriverLicense;
/* final */ LibraryDownloader hanaDriver;
+ /* final */ LibraryDownloader mariadbDriver;
/* final */ LibraryDownloader mysqlDriver;
/* final */ LibraryDownloader oracleDriver;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/MariaDbInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/MariaDbInitializer.java
new file mode 100644
index 0000000..db32113
--- /dev/null
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/MariaDbInitializer.java
@@ -0,0 +1,32 @@
+// Copyright (C) 2017 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 static com.google.gerrit.pgm.init.api.InitUtil.username;
+
+import com.google.gerrit.pgm.init.api.Section;
+
+class MariaDbInitializer implements DatabaseConfigInitializer {
+
+ @Override
+ public void initConfig(Section databaseSection) {
+ final String defPort = "(mariadb default)";
+ databaseSection.string("Server hostname", "hostname", "localhost");
+ databaseSection.string("Server port", "port", defPort, true);
+ databaseSection.string("Database name", "database", "reviewdb");
+ databaseSection.string("Database username", "username", username());
+ databaseSection.password("username", "password");
+ }
+}
diff --git a/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/libraries.config b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/libraries.config
index f4564f5..26ac9d6 100644
--- a/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/libraries.config
+++ b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/libraries.config
@@ -18,6 +18,12 @@
sha1 = b0878056f15616989144d6114d36d3942321d0d1
remove = mysql-connector-java-.*[.]jar
+[library "mariadbDriver"]
+ name = MariaDB Connector/J 1.5.9
+ url = https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/1.5.9/mariadb-java-client-1.5.9.jar
+ sha1 = 75d4d6e4cdb9a551a102e92a14c640768174e214
+ remove = mariadb-java-client-.*[.]jar
+
[library "oracleDriver"]
name = Oracle JDBC driver 11g Release 2 (11.2.0)
url = file:///u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
index e1f894f..f1c7056 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
@@ -45,7 +45,7 @@
*/
public final class Account {
public static final String USER_NAME_PATTERN_FIRST = "[a-zA-Z0-9]";
- public static final String USER_NAME_PATTERN_REST = "[a-zA-Z0-9._-]";
+ public static final String USER_NAME_PATTERN_REST = "[a-zA-Z0-9._@-]";
public static final String USER_NAME_PATTERN_LAST = "[a-zA-Z0-9]";
/** Regular expression that {@link #userName} must match. */
diff --git a/gerrit-server/src/main/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java b/gerrit-server/src/main/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
index cbd2378..7256e8c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/metrics/proc/OperatingSystemMXBeanProvider.java
@@ -52,10 +52,10 @@
private OperatingSystemMXBeanProvider(OperatingSystemMXBean sys)
throws ReflectiveOperationException {
this.sys = sys;
- getProcessCpuTime = sys.getClass().getMethod("getProcessCpuTime", new Class[] {});
+ getProcessCpuTime = sys.getClass().getMethod("getProcessCpuTime", new Class<?>[] {});
getProcessCpuTime.setAccessible(true);
getOpenFileDescriptorCount =
- sys.getClass().getMethod("getOpenFileDescriptorCount", new Class[] {});
+ sys.getClass().getMethod("getOpenFileDescriptorCount", new Class<?>[] {});
getOpenFileDescriptorCount.setAccessible(true);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java b/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java
index 6b3a58f..4ab42f3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java
@@ -35,6 +35,8 @@
@SuppressWarnings("deprecation")
@Singleton
public class Sequences {
+ public static final String CHANGES = "changes";
+
private final Provider<ReviewDb> db;
private final NotesMigration migration;
private final RepoSequence changeSeq;
@@ -54,7 +56,7 @@
new RepoSequence(
repoManager,
allProjects,
- "changes",
+ CHANGES,
new RepoSequence.Seed() {
@Override
public int get() throws OrmException {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalId.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalId.java
index d057f56..cd10b7b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalId.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalId.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.account;
+import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toSet;
@@ -71,7 +72,7 @@
private static final long serialVersionUID = 1L;
public static Key create(@Nullable String scheme, String id) {
- return new AutoValue_ExternalId_Key(scheme, id);
+ return new AutoValue_ExternalId_Key(Strings.emptyToNull(scheme), id);
}
public static ExternalId.Key from(AccountExternalId.Key externalIdKey) {
@@ -158,7 +159,8 @@
public static ExternalId create(
Key key, Account.Id accountId, @Nullable String email, @Nullable String hashedPassword) {
- return new AutoValue_ExternalId(key, accountId, email, hashedPassword);
+ return new AutoValue_ExternalId(
+ key, accountId, Strings.emptyToNull(email), Strings.emptyToNull(hashedPassword));
}
public static ExternalId createWithPassword(
@@ -174,16 +176,16 @@
}
public static ExternalId createWithEmail(
- String scheme, String id, Account.Id accountId, String email) {
+ String scheme, String id, Account.Id accountId, @Nullable String email) {
return createWithEmail(Key.create(scheme, id), accountId, email);
}
- public static ExternalId createWithEmail(Key key, Account.Id accountId, String email) {
- return new AutoValue_ExternalId(key, accountId, email, null);
+ public static ExternalId createWithEmail(Key key, Account.Id accountId, @Nullable String email) {
+ return new AutoValue_ExternalId(key, accountId, Strings.emptyToNull(email), null);
}
public static ExternalId createEmail(Account.Id accountId, String email) {
- return createWithEmail(SCHEME_MAILTO, email, accountId, email);
+ return createWithEmail(SCHEME_MAILTO, email, accountId, checkNotNull(email));
}
/**
@@ -243,7 +245,11 @@
accountIdStr, EXTERNAL_ID_SECTION, externalIdKeyStr, ACCOUNT_ID_KEY));
}
- return new AutoValue_ExternalId(externalIdKey, new Account.Id(accountId), email, password);
+ return new AutoValue_ExternalId(
+ externalIdKey,
+ new Account.Id(accountId),
+ Strings.emptyToNull(email),
+ Strings.emptyToNull(password));
}
private static ConfigInvalidException invalidConfig(String noteId, String message) {
@@ -259,8 +265,8 @@
return new AutoValue_ExternalId(
ExternalId.Key.parse(externalId.getExternalId()),
externalId.getAccountId(),
- externalId.getEmailAddress(),
- externalId.getPassword());
+ Strings.emptyToNull(externalId.getEmailAddress()),
+ Strings.emptyToNull(externalId.getPassword()));
}
public static Set<ExternalId> from(Collection<AccountExternalId> externalIds) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 3198017..d9fea44 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -994,7 +994,7 @@
break;
default:
- reject(cmd);
+ reject(cmd, "prohibited by Gerrit: unknown command type " + cmd.getType());
continue;
}
@@ -1113,7 +1113,7 @@
break;
default:
- reject(cmd);
+ reject(cmd, "prohibited by Gerrit: don't know how to handle config update of type " + cmd.getType());
continue;
}
}
@@ -1145,7 +1145,7 @@
validateNewCommits(ctl, cmd);
batch.addCommand(cmd);
} else {
- reject(cmd);
+ reject(cmd, "prohibited by Gerrit: create access denied for " + cmd.getRefName());
}
}
@@ -1168,7 +1168,7 @@
} else {
errors.put(Error.UPDATE, ctl.getRefName());
}
- reject(cmd);
+ reject(cmd, "prohibited by Gerrit: ref update access denied");
}
}
@@ -2878,10 +2878,6 @@
return r;
}
- private void reject(ReceiveCommand cmd) {
- reject(cmd, "prohibited by Gerrit");
- }
-
private void reject(ReceiveCommand cmd, String why) {
cmd.setResult(REJECTED_OTHER_REASON, why);
commandProgress.update(1);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
index 9d8d1ac..536858b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
@@ -281,12 +281,7 @@
return;
}
- // Reuse tree from parent commit unless there are contents in newTree or
- // there is no tree for a parent commit.
- ObjectId res =
- newTree.getEntryCount() != 0 || srcTree == null
- ? newTree.writeTree(inserter)
- : srcTree.copy();
+ ObjectId res = newTree.writeTree(inserter);
if (res.equals(srcTree) && !update.allowEmpty() && (commit.getTreeId() == null)) {
// If there are no changes to the content, don't create the commit.
return;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
index 0101cd7..0b097d3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
@@ -16,6 +16,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_SEQUENCES;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
@@ -52,6 +54,7 @@
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
/**
* Class for managing an incrementing sequence backed by a git repository.
@@ -117,7 +120,15 @@
Retryer<RefUpdate.Result> retryer) {
this.repoManager = checkNotNull(repoManager, "repoManager");
this.projectName = checkNotNull(projectName, "projectName");
- this.refName = RefNames.REFS_SEQUENCES + checkNotNull(name, "name");
+
+ checkArgument(
+ name != null
+ && !name.startsWith(REFS)
+ && !name.startsWith(REFS_SEQUENCES.substring(REFS.length())),
+ "name should be a suffix to follow \"refs/sequences/\", got: %s",
+ name);
+ this.refName = RefNames.REFS_SEQUENCES + name;
+
this.seed = checkNotNull(seed, "seed");
checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
@@ -265,4 +276,10 @@
ru.setForceUpdate(true); // Required for non-commitish updates.
return ru.update(rw);
}
+
+ public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
+ throws IOException {
+ ObjectId newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
+ return new ReceiveCommand(ObjectId.zeroId(), newId, RefNames.REFS_SEQUENCES + name);
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
index 8a57c73..62144ec 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
@@ -163,8 +163,7 @@
protected final Definition<T, ? extends QueryBuilder<T>> builderDef;
- @SuppressWarnings("rawtypes")
- protected final Map<String, OperatorFactory> opFactories;
+ protected final Map<String, OperatorFactory<?, ?>> opFactories;
@SuppressWarnings({"unchecked", "rawtypes"})
protected QueryBuilder(Definition<T, ? extends QueryBuilder<T>> def) {
@@ -296,12 +295,11 @@
throw error("Unsupported query:" + value);
}
- @SuppressWarnings("unchecked")
- private Predicate<T>[] children(final Tree r)
+ private List<Predicate<T>> children(final Tree r)
throws QueryParseException, IllegalArgumentException {
- final Predicate<T>[] p = new Predicate[r.getChildCount()];
- for (int i = 0; i < p.length; i++) {
- p[i] = toPredicate(r.getChild(i));
+ List<Predicate<T>> p = new ArrayList<>(r.getChildCount());
+ for (int i = 0; i < r.getChildCount(); i++) {
+ p.add(toPredicate(r.getChild(i)));
}
return p;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/AllProjectsCreator.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/AllProjectsCreator.java
index 3f1d32c..9a56aa4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/AllProjectsCreator.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/AllProjectsCreator.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.schema;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.gerrit.reviewdb.client.RefNames.REFS_SEQUENCES;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.PROJECT_OWNERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -35,28 +37,39 @@
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.server.notedb.RepoSequence;
import com.google.inject.Inject;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
/** Creates the {@code All-Projects} repository and initial ACLs. */
public class AllProjectsCreator {
private final GitRepositoryManager mgr;
private final AllProjectsName allProjectsName;
private final PersonIdent serverUser;
+ private final NotesMigration notesMigration;
private String message;
+ private int firstChangeId = ReviewDb.FIRST_CHANGE_ID;
private GroupReference admin;
private GroupReference batch;
@@ -69,10 +82,12 @@
GitRepositoryManager mgr,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
- @GerritPersonIdent PersonIdent serverUser) {
+ @GerritPersonIdent PersonIdent serverUser,
+ NotesMigration notesMigration) {
this.mgr = mgr;
this.allProjectsName = allProjectsName;
this.serverUser = serverUser;
+ this.notesMigration = notesMigration;
this.anonymous = systemGroupBackend.getGroup(ANONYMOUS_USERS);
this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
@@ -94,6 +109,12 @@
return this;
}
+ public AllProjectsCreator setFirstChangeIdForNoteDb(int id) {
+ checkArgument(id > 0, "id must be positive: %s", id);
+ firstChangeId = id;
+ return this;
+ }
+
public void create() throws IOException, ConfigInvalidException {
try (Repository git = mgr.openRepository(allProjectsName)) {
initAllProjects(git);
@@ -112,8 +133,9 @@
}
private void initAllProjects(Repository git) throws IOException, ConfigInvalidException {
+ BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
+ new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git, bru)) {
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
md.setMessage(
@@ -177,6 +199,8 @@
grant(config, meta, Permission.SUBMIT, admin, owners);
config.commitToNewRef(md, RefNames.REFS_CONFIG);
+ initSequences(git, bru);
+ execute(git, bru);
}
}
@@ -195,4 +219,27 @@
c.getLabelSections().put(type.getName(), type);
return type;
}
+
+ private void initSequences(Repository git, BatchRefUpdate bru) throws IOException {
+ if (notesMigration.readChangeSequence()
+ && git.exactRef(REFS_SEQUENCES + Sequences.CHANGES) == null) {
+ // Can't easily reuse the inserter from MetaDataUpdate, but this shouldn't slow down site
+ // initialization unduly.
+ try (ObjectInserter ins = git.newObjectInserter()) {
+ bru.addCommand(RepoSequence.storeNew(ins, Sequences.CHANGES, firstChangeId));
+ ins.flush();
+ }
+ }
+ }
+
+ private void execute(Repository git, BatchRefUpdate bru) throws IOException {
+ try (RevWalk rw = new RevWalk(git)) {
+ bru.execute(rw, NullProgressMonitor.INSTANCE);
+ }
+ for (ReceiveCommand cmd : bru.getCommands()) {
+ if (cmd.getResult() != ReceiveCommand.Result.OK) {
+ throw new IOException("Failed to initialize " + allProjectsName + " refs:\n" + bru);
+ }
+ }
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceModule.java
index 65843d8..ee57c8b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/DataSourceModule.java
@@ -25,6 +25,7 @@
bind(DataSourceType.class).annotatedWith(Names.named("derby")).to(Derby.class);
bind(DataSourceType.class).annotatedWith(Names.named("h2")).to(H2.class);
bind(DataSourceType.class).annotatedWith(Names.named("jdbc")).to(JDBC.class);
+ bind(DataSourceType.class).annotatedWith(Names.named("mariadb")).to(MariaDb.class);
bind(DataSourceType.class).annotatedWith(Names.named("mysql")).to(MySql.class);
bind(DataSourceType.class).annotatedWith(Names.named("oracle")).to(Oracle.class);
bind(DataSourceType.class).annotatedWith(Names.named("postgresql")).to(PostgreSQL.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/MariaDb.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/MariaDb.java
new file mode 100644
index 0000000..ed18a86
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/MariaDb.java
@@ -0,0 +1,54 @@
+// Copyright (C) 2017 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.schema;
+
+import static com.google.gerrit.server.schema.JdbcUtil.hostname;
+import static com.google.gerrit.server.schema.JdbcUtil.port;
+
+import com.google.gerrit.server.config.ConfigSection;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+import org.eclipse.jgit.lib.Config;
+
+class MariaDb extends BaseDataSourceType {
+ private final Config cfg;
+
+ @Inject
+ MariaDb(@GerritServerConfig Config cfg) {
+ super("org.mariadb.jdbc.Driver");
+ this.cfg = cfg;
+ }
+
+ @Override
+ public String getUrl() {
+ StringBuilder b = new StringBuilder();
+ ConfigSection dbs = new ConfigSection(cfg, "database");
+ b.append("jdbc:mariadb://");
+ b.append(hostname(dbs.optional("hostname")));
+ b.append(port(dbs.optional("port")));
+ b.append("/");
+ b.append(dbs.required("database"));
+ return b.toString();
+ }
+
+ @Override
+ public boolean usePool() {
+ // MariaDB has given us trouble with the connection pool,
+ // sometimes the backend disconnects and the pool winds
+ // up with a stale connection. Fortunately opening up
+ // a new MariaDB connection is usually very fast.
+ return false;
+ }
+}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
index 112fdd6..9a32365 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/schema/SchemaUpdaterTest.java
@@ -30,6 +30,7 @@
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.notedb.ConfigNotesMigration;
import com.google.gerrit.testutil.InMemoryDatabase;
import com.google.gerrit.testutil.InMemoryH2Type;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
@@ -108,6 +109,7 @@
bind(DataSourceType.class).to(InMemoryH2Type.class);
bind(SystemGroupBackend.class);
+ install(new ConfigNotesMigration.Module());
}
})
.getInstance(SchemaUpdater.class);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
index d5b1712..0a9e182 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
@@ -420,7 +420,7 @@
private void initKeyExchanges(Config cfg) {
List<NamedFactory<KeyExchange>> a = ServerBuilder.setUpDefaultKeyExchanges(true);
setKeyExchangeFactories(
- filter(cfg, "kex", (NamedFactory<KeyExchange>[]) a.toArray(new NamedFactory[a.size()])));
+ filter(cfg, "kex", (NamedFactory<KeyExchange>[]) a.toArray(new NamedFactory<?>[a.size()])));
}
private void initProviderBouncyCastle(Config cfg) {
@@ -528,14 +528,14 @@
a.add(null);
setCipherFactories(
- filter(cfg, "cipher", (NamedFactory<Cipher>[]) a.toArray(new NamedFactory[a.size()])));
+ filter(cfg, "cipher", (NamedFactory<Cipher>[]) a.toArray(new NamedFactory<?>[a.size()])));
}
@SuppressWarnings("unchecked")
private void initMacs(Config cfg) {
List<NamedFactory<Mac>> m = BaseBuilder.setUpDefaultMacs(true);
setMacFactories(
- filter(cfg, "mac", (NamedFactory<Mac>[]) m.toArray(new NamedFactory[m.size()])));
+ filter(cfg, "mac", (NamedFactory<Mac>[]) m.toArray(new NamedFactory<?>[m.size()])));
}
@SafeVarargs
diff --git a/gerrit-war/src/main/webapp/WEB-INF/extra/jetty7/gerrit.xml b/gerrit-war/src/main/webapp/WEB-INF/extra/jetty7/gerrit.xml
index 3ae9440..02aa1b9 100644
--- a/gerrit-war/src/main/webapp/WEB-INF/extra/jetty7/gerrit.xml
+++ b/gerrit-war/src/main/webapp/WEB-INF/extra/jetty7/gerrit.xml
@@ -49,6 +49,10 @@
<Set name="driverClassName">com.mysql.jdbc.Driver</Set>
<Set name="url">jdbc:mysql://localhost/reviewdb?user=gerrit2&password=secretkey</Set>
-->
+<!-- MariaDB
+ <Set name="driverClassName">org.mariadb.jdbc.Driver</Set>
+ <Set name="url">jdbc:mariadb://localhost/reviewdb?user=gerrit2&password=secretkey</Set>
+-->
<!-- H2
<Set name="driverClassName">org.h2.Driver</Set>
<Set name="url">jdbc:h2:file:ReviewDb</Set>
diff --git a/lib/BUILD b/lib/BUILD
index fe1933c..c2148bf 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -264,6 +264,7 @@
":args4j",
":gson",
":guava",
+ ":html-types",
":icu4j",
":jsr305",
":protobuf",
@@ -279,6 +280,13 @@
)
java_library(
+ name = "html-types",
+ data = ["//lib:LICENSE-Apache2.0"],
+ visibility = ["//visibility:public"],
+ exports = ["@html_types//jar"],
+)
+
+java_library(
name = "icu4j",
data = ["//lib:LICENSE-icu4j"],
visibility = ["//visibility:public"],
diff --git a/plugins/replication b/plugins/replication
index 305c864..7bdacab 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 305c864db28eb0c77c8499bc04c87de3f849cf3c
+Subproject commit 7bdacabfcc4c9b17b773f2783bf406c02ad738fb
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
index 1f7f85c..77d1c05 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
@@ -31,6 +31,10 @@
return window.localStorage;
},
},
+ _exceededQuota: {
+ type: Boolean,
+ value: false,
+ },
},
getDraftComment: function(location) {
@@ -94,7 +98,20 @@
},
_setObject: function(key, obj) {
- this._storage.setItem(key, JSON.stringify(obj));
+ if (this._exceededQuota) { return; }
+ try {
+ this._storage.setItem(key, JSON.stringify(obj));
+ } catch (exc) {
+ // Catch for QuotaExceededError and disable writes on local storage the
+ // first time that it occurs.
+ if (exc.code === 22) {
+ this._exceededQuota = true;
+ console.warn('Local storage quota exceeded: disabling');
+ return;
+ } else {
+ throw exc;
+ }
+ }
},
});
})();
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
index f6c24cb..b17a9c9 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
@@ -31,19 +31,21 @@
<script>
suite('gr-storage tests', function() {
var element;
- var storage;
- function cleanupStorage() {
- // Make sure there are no entries in storage.
- for (var key in window.localStorage) {
- window.localStorage.removeItem(key);
- }
+ function mockStorage(opt_quotaExceeded) {
+ return {
+ getItem: function(key) { return this[key]; },
+ removeItem: function(key) { delete this[key]; },
+ setItem: function(key, value) {
+ if (opt_quotaExceeded) { throw {code: 22}; /* Quota exceeded */ }
+ this[key] = value;
+ },
+ };
}
setup(function() {
element = fixture('basic');
- storage = element._storage;
- cleanupStorage();
+ element._storage = mockStorage();
});
test('storing, retrieving and erasing drafts', function() {
@@ -68,18 +70,16 @@
// Setting the draft stores it under the expected key.
element.setDraftComment(location, 'my comment');
- assert.isOk(storage.getItem(key));
- assert.equal(JSON.parse(storage.getItem(key)).message, 'my comment');
- assert.isOk(JSON.parse(storage.getItem(key)).updated);
+ assert.isOk(element._storage.getItem(key));
+ assert.equal(JSON.parse(element._storage.getItem(key)).message,
+ 'my comment');
+ assert.isOk(JSON.parse(element._storage.getItem(key)).updated);
// Erasing the draft removes the key.
element.eraseDraftComment(location);
- assert.isNotOk(storage.getItem(key));
-
- cleanupStorage();
+ assert.isNotOk(element._storage.getItem(key));
});
-
test('automatically removes old drafts', function() {
var changeNum = 1234;
var patchNum = 5;
@@ -100,7 +100,7 @@
var cleanupSpy = sinon.spy(element, '_cleanupDrafts');
// Create a message with a timestamp that is a second behind the max age.
- storage.setItem(key, JSON.stringify({
+ element._storage.setItem(key, JSON.stringify({
message: 'old message',
updated: Date.now() - 24 * 60 * 60 * 1000 - 1000,
}));
@@ -110,10 +110,9 @@
assert.isTrue(cleanupSpy.called);
assert.isNotOk(draft);
- assert.isNotOk(storage.getItem(key));
+ assert.isNotOk(element._storage.getItem(key));
cleanupSpy.restore();
- cleanupStorage();
});
test('_getDraftKey', function() {
@@ -138,5 +137,25 @@
expectedResult = 'draft:1234:5:my_source_file.js:123:1-1-1-2';
assert.equal(element._getDraftKey(location), expectedResult);
});
+
+ test('exceeded quota disables storage', function() {
+ element._storage = mockStorage(true);
+ assert.isFalse(element._exceededQuota);
+
+ var changeNum = 1234;
+ var patchNum = 5;
+ var path = 'my_source_file.js';
+ var line = 123;
+ var location = {
+ changeNum: changeNum,
+ patchNum: patchNum,
+ path: path,
+ line: line,
+ };
+ var key = element._getDraftKey(location);
+ element.setDraftComment(location, 'my comment');
+ assert.isTrue(element._exceededQuota);
+ assert.isNotOk(element._storage.getItem(key));
+ });
});
</script>
diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py
index 7ea0989..5e8d69a 100755
--- a/tools/eclipse/project.py
+++ b/tools/eclipse/project.py
@@ -56,6 +56,12 @@
def retrieve_ext_location():
return check_output(['bazel', 'info', 'output_base']).strip()
+def gen_bazel_path():
+ bazel = check_output(['which', 'bazel']).strip()
+ with open(path.join(ROOT, ".bazel_path"), 'w') as fd:
+ fd.write("bazel=%s\n" % bazel)
+ fd.write("PATH=%s\n" % environ["PATH"])
+
def _query_classpath(target):
deps = []
t = cp_targets[target]
@@ -258,6 +264,7 @@
gen_project(args.project_name)
gen_classpath(ext_location)
gen_factorypath(ext_location)
+ gen_bazel_path()
# TODO(davido): Remove this when GWT gone
gwt_working_dir = ".gwt_work_dir"
diff --git a/tools/maven/api.sh b/tools/maven/api.sh
index 8c441fb..e72e3cb 100755
--- a/tools/maven/api.sh
+++ b/tools/maven/api.sh
@@ -16,9 +16,9 @@
set -e
-if [[ "$#" != "1" ]] ; then
+if [[ "$#" -lt "1" ]] ; then
cat <<EOF
-Usage: run "$0 COMMAND" from the top of your workspace,
+Usage: run "$0 COMMAND [build_args...]" from the top of your workspace,
where COMMAND is one of
install
@@ -54,12 +54,13 @@
exit 1
;;
esac
+shift
if [[ "${VERBOSE:-x}" != "x" ]]; then
set -o xtrace
fi
-bazel build //tools/maven:gen_${command} || \
+bazel build //tools/maven:gen_${command} "$@" || \
{ echo "bazel failed to build gen_${command}. Use VERBOSE=1 for more info" ; exit 1 ; }
./bazel-genfiles/tools/maven/${command}.sh