Merge "Add REST endpoints for draft changes"
diff --git a/.buckconfig b/.buckconfig
index e60c7cd5..171acb5 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -15,3 +15,6 @@
[java]
src_roots = java, resources
+
+[project]
+ ignore = .git
diff --git a/ReleaseNotes/ReleaseNotes-2.6.2.txt b/ReleaseNotes/ReleaseNotes-2.6.2.txt
index 2a7a7b3..af00a71 100644
--- a/ReleaseNotes/ReleaseNotes-2.6.2.txt
+++ b/ReleaseNotes/ReleaseNotes-2.6.2.txt
@@ -21,10 +21,6 @@
If the title is not specified, the path of the dashboard config file
is used as title.
-* link:https://code.google.com/p/gerrit/issues/detail?id=2010[Issue 2010]:
-Fix null-pointer exception when searching for changes with the query
-`owner:self`.
-
* Properly handle double-click on external group in GroupTable.
+
Double-clicking on an external group opens the group's URL (if it
@@ -41,11 +37,15 @@
* link:https://code.google.com/p/gerrit/issues/detail?id=1966[Issue 1966]:
Fix Gerrit plugins under Tomcat by avoiding Guice static filter.
-* link:https://code.google.com/p/gerrit/issues/detail?id=2054[Issue 2054]:
-Expand capabilities of `ldap.groupMemberPattern`.
+* link:https://code.google.com/p/gerrit/issues/detail?id=2010[Issue 2010]:
+Fix null-pointer exception when searching for changes with the query
+`owner:self`.
* link:https://code.google.com/p/gerrit/issues/detail?id=2039[Issue 2039]:
-Fix browser NPE when ChangeCache is incomplete.
+Fix browser null-pointer exception when ChangeCache is incomplete.
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=2054[Issue 2054]:
+Expand capabilities of `ldap.groupMemberPattern`.
* link:https://code.google.com/p/gerrit/issues/detail?id=2056[Issue 2056]:
Display custom NoOp label score for open changes.
@@ -56,5 +56,12 @@
* link:https://code.google.com/p/gerrit/issues/detail?id=2098[Issue 2098]:
Fix re-enabling of disabled plugins.
+* link:https://code.google.com/p/gerrit/issues/detail?id=2127[Issue 2127]:
+Remove hard-coded documentation links from the admin page.
+
+* link:https://code.google.com/p/gerrit/issues/detail?id=2128[Issue 2128]:
+Fix null-pointer exception when deleting draft patch set when previous
+draft was already deleted.
+
No other changes since 2.6.1.
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 3a95fc3..adb346f 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -14,20 +14,51 @@
package com.google.gerrit.acceptance;
-import org.junit.After;
-import org.junit.Before;
+import org.eclipse.jgit.lib.Config;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
public abstract class AbstractDaemonTest {
protected GerritServer server;
- @Before
- public final void beforeTest() throws Exception {
- server = GerritServer.start();
+ @Rule
+ public TestRule testRunner = new TestRule() {
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ beforeTest(config(description));
+ base.evaluate();
+ afterTest();
+ }
+ };
+ }
+ };
+
+ private static Config config(Description description) {
+ GerritConfigs cfgs = description.getAnnotation(GerritConfigs.class);
+ GerritConfig cfg = description.getAnnotation(GerritConfig.class);
+ if (cfgs != null && cfg != null) {
+ throw new IllegalStateException("Use either @GerritConfigs or @GerritConfig not both");
+ }
+ if (cfgs != null) {
+ return ConfigAnnotationParser.parse(cfgs);
+ } else if (cfg != null) {
+ return ConfigAnnotationParser.parse(cfg);
+ } else {
+ return null;
+ }
+ }
+
+ private void beforeTest(Config cfg) throws Exception {
+ server = GerritServer.start(cfg);
server.getTestInjector().injectMembers(this);
}
- @After
- public final void afterTest() throws Exception {
+ private void afterTest() throws Exception {
server.stop();
}
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
new file mode 100644
index 0000000..cf60fb4
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
@@ -0,0 +1,58 @@
+// 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 com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+
+import org.eclipse.jgit.lib.Config;
+
+import java.util.ArrayList;
+
+class ConfigAnnotationParser {
+
+ private static Splitter splitter = Splitter.on(".").trimResults();
+
+ static Config parse(GerritConfigs annotation) {
+ if (annotation == null) {
+ return null;
+ }
+
+ Config cfg = new Config();
+ for (GerritConfig c : annotation.value()) {
+ parse(cfg, c);
+ }
+ return cfg;
+ }
+
+ static Config parse(GerritConfig annotation) {
+ Config cfg = new Config();
+ parse(cfg, annotation);
+ return cfg;
+ }
+
+ static private void parse(Config cfg, GerritConfig c) {
+ ArrayList<String> l = Lists.newArrayList(splitter.split(c.name()));
+ if (l.size() == 2) {
+ cfg.setString(l.get(0), null, l.get(1), c.value());
+ } else if (l.size() == 3) {
+ cfg.setString(l.get(0), l.get(1), l.get(2), c.value());
+ } else {
+ throw new IllegalArgumentException(
+ "GerritConfig.name must be of the format"
+ + " section.subsection.name or section.name");
+ }
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfig.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfig.java
new file mode 100644
index 0000000..5cb1229
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfig.java
@@ -0,0 +1,28 @@
+// 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 static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+public @interface GerritConfig {
+ String name();
+ String value();
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfigs.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfigs.java
new file mode 100644
index 0000000..58bb9f2
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritConfigs.java
@@ -0,0 +1,27 @@
+// 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 static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+public @interface GerritConfigs {
+ public GerritConfig[] value();
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
index de70796..f97d2b9 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
@@ -23,6 +23,7 @@
import com.google.inject.Module;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
@@ -42,11 +43,11 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-class GerritServer {
+public class GerritServer {
/** Returns fully started Gerrit server */
- static GerritServer start() throws Exception {
- final File site = initSite();
+ static GerritServer start(Config base) throws Exception {
+ final File site = initSite(base);
final CyclicBarrier serverStarted = new CyclicBarrier(2);
final Daemon daemon = new Daemon(new Runnable() {
public void run() {
@@ -80,7 +81,7 @@
return new GerritServer(site, i, daemon, daemonService);
}
- private static File initSite() throws Exception {
+ private static File initSite(Config base) throws Exception {
File tmp = TempFileUtil.createTempDirectory();
Init init = new Init();
int rc = init.main(new String[] {
@@ -93,10 +94,11 @@
InetSocketAddress http = newPort();
InetSocketAddress sshd = newPort();
String url = "http://" + format(http) + "/";
- FileBasedConfig cfg = new FileBasedConfig(
+ MergeableFileBasedConfig cfg = new MergeableFileBasedConfig(
new File(new File(tmp, "etc"), "gerrit.config"),
FS.DETECTED);
cfg.load();
+ cfg.merge(base);
cfg.setString("gerrit", null, "canonicalWebUrl", url);
cfg.setString("httpd", null, "listenUrl", url);
cfg.setString("sshd", null, "listenAddress", format(sshd));
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/MergeableFileBasedConfig.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/MergeableFileBasedConfig.java
new file mode 100644
index 0000000..f1baa9d
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/MergeableFileBasedConfig.java
@@ -0,0 +1,60 @@
+// 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 com.google.common.collect.Lists;
+
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+
+import java.io.File;
+
+/**
+ * A file based Config that can merge another Config instance.
+ */
+public class MergeableFileBasedConfig extends FileBasedConfig {
+ public MergeableFileBasedConfig(File cfgLocation, FS fs) {
+ super(cfgLocation, fs);
+ }
+
+ /**
+ * Merge another Config into this Config.
+ *
+ * In case a configuration parameter exists both in this instance and in the
+ * merged instance then the value in this instance will simply replaced by
+ * the value from the merged instance.
+ *
+ * @param s Config to merge into this instance
+ */
+ public void merge(Config s) {
+ if (s == null) {
+ return;
+ }
+ for (String section : s.getSections()) {
+ for (String subsection : s.getSubsections(section)) {
+ for (String name : s.getNames(section, subsection)) {
+ setStringList(section, subsection, name, Lists.newArrayList(s
+ .getStringList(section, subsection, name)));
+ }
+ }
+
+ for (String name : s.getNames(section)) {
+ setStringList(section, null, name,
+ Lists.newArrayList(s.getStringList(section, null, name)));
+ }
+ }
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseGerritConfigAnnotationTest.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseGerritConfigAnnotationTest.java
new file mode 100644
index 0000000..0931e12
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/UseGerritConfigAnnotationTest.java
@@ -0,0 +1,46 @@
+// 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 static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+
+public class UseGerritConfigAnnotationTest extends AbstractDaemonTest {
+
+ @Inject
+ @GerritServerConfig
+ Config serverConfig;
+
+ @Test
+ @GerritConfig(name="x.y", value="z")
+ public void testOne() {
+ assertEquals("z", serverConfig.getString("x", null, "y"));
+ }
+
+ @Test
+ @GerritConfigs({
+ @GerritConfig(name="x.y", value="z"),
+ @GerritConfig(name="a.b", value="c"),
+ })
+ public void testMultiple() {
+ assertEquals("z", serverConfig.getString("x", null, "y"));
+ assertEquals("c", serverConfig.getString("a", null, "b"));
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
index adec292..d20b0f6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/changedetail/DeleteDraftPatchSet.java
@@ -112,9 +112,7 @@
}
if (change.currentPatchSetId().equals(patchSetId)) {
try {
- PatchSet.Id id =
- new PatchSet.Id(patchSetId.getParentKey(), patchSetId.get() - 1);
- change.setCurrentPatchSet(patchSetInfoFactory.get(db, id));
+ change.setCurrentPatchSet(patchSetInfoFactory.get(db, highestId));
} catch (PatchSetInfoNotAvailableException e) {
throw new NoSuchChangeException(changeId);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
index 76d873a..24186b8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
@@ -160,6 +160,7 @@
} else {
changes = changes.subList(0, imp.getLimit());
}
+ data.set(n, changes);
more.set(n, true);
}
}