Merge "Use allow/block/deny methods to improve test readability"
diff --git a/.buckconfig b/.buckconfig
index df8bfdc..f0422c9 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -1,8 +1,10 @@
[alias]
all = //:all
api = //:api
- api_deploy = //tools/maven:deploy
- api_install = //tools/maven:install
+ api_deploy = //tools/maven:api_deploy
+ api_install = //tools/maven:api_install
+ war_deploy = //tools/maven:war_deploy
+ war_install = //tools/maven:war_install
chrome = //:chrome
docs = //Documentation:html
firefox = //:firefox
diff --git a/Documentation/dev-buck.txt b/Documentation/dev-buck.txt
index 91cc585..2bcf5c2 100644
--- a/Documentation/dev-buck.txt
+++ b/Documentation/dev-buck.txt
@@ -129,18 +129,30 @@
buck-out/gen/gerrit-plugin-api/plugin-api-javadoc.jar
----
-Install {extension,plugin,gwt}-api and gerrit.war to the local maven repository:
+Install {extension,plugin,gwt}-api to the local maven repository:
----
buck build api_install
----
-Deploy {extension,plugin,gwt}-api and gerrit.war to the remote maven repository:
+Deploy {extension,plugin,gwt}-api to the remote maven repository:
----
buck build api_deploy
----
+Install gerrit.war to the local maven repository:
+
+----
+ buck build war_install
+----
+
+Deploy gerrit.war to the remote maven repository:
+
+----
+ buck build war_deploy
+----
+
The type of the repo is induced from the Gerrit version name, i.e.
* `2.9-SNAPSHOT`: snapshot repo
diff --git a/Documentation/dev-release.txt b/Documentation/dev-release.txt
index 9c00467..1af54c7 100644
--- a/Documentation/dev-release.txt
+++ b/Documentation/dev-release.txt
@@ -156,6 +156,12 @@
* The WAR file to upload is `buck-out/gen/release.war`
* Upload WAR to the storage bucket via `https://cloud.google.com/console` (manual via web browser)
+* Push the WAR file to the Maven storage bucket:
++
+----
+ buck build war_deploy
+----
+
[[push-stable]]
diff --git a/Documentation/images/user-review-ui-change-screen-commit-info-merge-commit.png b/Documentation/images/user-review-ui-change-screen-commit-info-merge-commit.png
index 75cd60c..097637e 100644
--- a/Documentation/images/user-review-ui-change-screen-commit-info-merge-commit.png
+++ b/Documentation/images/user-review-ui-change-screen-commit-info-merge-commit.png
Binary files differ
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
index d656e1e..a01525a 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -15,8 +15,12 @@
package com.google.gerrit.acceptance.api.change;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
@@ -28,6 +32,8 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeStatus;
import com.google.gerrit.extensions.common.LabelInfo;
+import com.google.gerrit.extensions.common.ListChangesOption;
+import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Account;
@@ -37,6 +43,8 @@
import org.junit.Test;
import java.io.IOException;
+import java.util.EnumSet;
+import java.util.List;
import java.util.Set;
@NoHttpd
@@ -164,4 +172,88 @@
assertEquals(in.branch, info.branch);
assertEquals(in.subject, info.subject);
}
+
+ @Test
+ public void queryChangesNoQuery() throws Exception {
+ PushOneCommit.Result r1 = createChange();
+ PushOneCommit.Result r2 = createChange();
+ List<ChangeInfo> results = gApi.changes().query().get();
+ assertEquals(2, results.size());
+ assertEquals(r2.getChangeId(), results.get(0).changeId);
+ assertEquals(r1.getChangeId(), results.get(1).changeId);
+ }
+
+ @Test
+ public void queryChangesNoResults() throws Exception {
+ createChange();
+ List<ChangeInfo> results = gApi.changes().query("status:open").get();
+ assertEquals(1, results.size());
+ results = gApi.changes().query("status:closed").get();
+ assertTrue(results.isEmpty());
+ }
+
+ @Test
+ public void queryChangesOneTerm() throws Exception {
+ PushOneCommit.Result r1 = createChange();
+ PushOneCommit.Result r2 = createChange();
+ List<ChangeInfo> results = gApi.changes().query("status:open").get();
+ assertEquals(2, results.size());
+ assertEquals(r2.getChangeId(), results.get(0).changeId);
+ assertEquals(r1.getChangeId(), results.get(1).changeId);
+ }
+
+ @Test
+ public void queryChangesMultipleTerms() throws Exception {
+ PushOneCommit.Result r1 = createChange();
+ createChange();
+ List<ChangeInfo> results = gApi.changes()
+ .query("status:open " + r1.getChangeId())
+ .get();
+ assertEquals(r1.getChangeId(), Iterables.getOnlyElement(results).changeId);
+ }
+
+ @Test
+ public void queryChangesLimit() throws Exception {
+ createChange();
+ PushOneCommit.Result r2 = createChange();
+ List<ChangeInfo> results = gApi.changes().query().withLimit(1).get();
+ assertEquals(1, results.size());
+ assertEquals(r2.getChangeId(), Iterables.getOnlyElement(results).changeId);
+ }
+
+ @Test
+ public void queryChangesStart() throws Exception {
+ PushOneCommit.Result r1 = createChange();
+ createChange();
+ List<ChangeInfo> results = gApi.changes().query().withStart(1).get();
+ assertEquals(r1.getChangeId(), Iterables.getOnlyElement(results).changeId);
+ }
+
+ @Test
+ public void queryChangesNoOptions() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ChangeInfo result = Iterables.getOnlyElement(
+ gApi.changes().query(r.getChangeId()).get());
+ assertNull(result.labels);
+ assertNull(result.messages);
+ assertNull(result.revisions);
+ assertNull(result.actions);
+ }
+
+ @Test
+ public void queryChangesOptions() throws Exception {
+ PushOneCommit.Result r = createChange();
+ ChangeInfo result = Iterables.getOnlyElement(gApi.changes()
+ .query(r.getChangeId())
+ .withOptions(EnumSet.allOf(ListChangesOption.class))
+ .get());
+ assertEquals("Code-Review",
+ Iterables.getOnlyElement(result.labels.keySet()));
+ assertEquals(1, result.messages.size());
+ assertFalse(result.actions.isEmpty());
+
+ RevisionInfo rev = Iterables.getOnlyElement(result.revisions.values());
+ assertEquals(r.getPatchSetId().get(), rev._number);
+ assertFalse(rev.actions.isEmpty());
+ }
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
new file mode 100644
index 0000000..70a0a60
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
@@ -0,0 +1,231 @@
+// Copyright (C) 2014 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.server.change;
+
+import static com.google.gerrit.acceptance.GitUtil.add;
+import static com.google.gerrit.acceptance.GitUtil.amendCommit;
+import static com.google.gerrit.acceptance.GitUtil.createCommit;
+import static com.google.gerrit.acceptance.GitUtil.pushHead;
+import static com.google.gerrit.acceptance.GitUtil.rm;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.GitUtil.Commit;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
+import com.google.gerrit.reviewdb.client.Patch;
+import com.google.gerrit.reviewdb.client.Patch.ChangeType;
+import com.google.gerrit.server.patch.PatchListCache;
+import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gerrit.server.patch.PatchListKey;
+import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+public class PatchListCacheIT extends AbstractDaemonTest {
+ private static String SUBJECT_1 = "subject 1";
+ private static String SUBJECT_2 = "subject 2";
+ private static String SUBJECT_3 = "subject 3";
+ private static String FILE_A = "a.txt";
+ private static String FILE_B = "b.txt";
+ private static String FILE_C = "c.txt";
+ private static String FILE_D = "d.txt";
+
+ @Inject
+ private PatchListCache patchListCache;
+
+ @Test
+ public void listPatchesAgainstBase() throws GitAPIException, IOException,
+ PatchListNotAvailableException, OrmException, RestApiException {
+ add(git, FILE_D, "4");
+ createCommit(git, admin.getIdent(), SUBJECT_1);
+ pushHead(git, "refs/heads/master", false);
+
+ // Change 1, 1 (+FILE_A, -FILE_D)
+ add(git, FILE_A, "1");
+ rm(git, FILE_D);
+ Commit c = createCommit(git, admin.getIdent(), SUBJECT_2);
+ pushHead(git, "refs/for/master", false);
+
+ // Compare Change 1,1 with Base (+FILE_A, -FILE_D)
+ List<PatchListEntry> entries = getCurrentPatches(c.getChangeId());
+ assertEquals(3, entries.size());
+ assertAdded(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_A, entries.get(1));
+ assertDeleted(FILE_D, entries.get(2));
+
+ // Change 1,2 (+FILE_A, +FILE_B, -FILE_D)
+ add(git, FILE_B, "2");
+ c = amendCommit(git, admin.getIdent(), SUBJECT_2, c.getChangeId());
+ pushHead(git, "refs/for/master", false);
+ entries = getCurrentPatches(c.getChangeId());
+
+ // Compare Change 1,2 with Base (+FILE_A, +FILE_B, -FILE_D)
+ assertEquals(4, entries.size());
+ assertAdded(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_A, entries.get(1));
+ assertAdded(FILE_B, entries.get(2));
+ assertDeleted(FILE_D, entries.get(3));
+ }
+
+ @Test
+ public void listPatchesAgainstBaseWithRebase() throws GitAPIException,
+ IOException, PatchListNotAvailableException, OrmException,
+ RestApiException {
+ add(git, FILE_D, "4");
+ createCommit(git, admin.getIdent(), SUBJECT_1);
+ pushHead(git, "refs/heads/master", false);
+
+ // Change 1,1 (+FILE_A, -FILE_D)
+ add(git, FILE_A, "1");
+ rm(git, FILE_D);
+ Commit c = createCommit(git, admin.getIdent(), SUBJECT_2);
+ pushHead(git, "refs/for/master", false);
+ List<PatchListEntry> entries = getCurrentPatches(c.getChangeId());
+ assertEquals(3, entries.size());
+ assertAdded(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_A, entries.get(1));
+ assertDeleted(FILE_D, entries.get(2));
+
+ // Change 2,1 (+FILE_B)
+ git.reset().setMode(ResetType.HARD).setRef("HEAD~1").call();
+ add(git, FILE_B, "2");
+ createCommit(git, admin.getIdent(), SUBJECT_3);
+ pushHead(git, "refs/for/master", false);
+
+ // Change 1,2 (+FILE_A, -FILE_D))
+ git.cherryPick().include(c.getCommit()).call();
+ pushHead(git, "refs/for/master", false);
+
+ // Compare Change 1,2 with Base (+FILE_A, -FILE_D))
+ entries = getCurrentPatches(c.getChangeId());
+ assertEquals(3, entries.size());
+ assertAdded(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_A, entries.get(1));
+ assertDeleted(FILE_D, entries.get(2));
+ }
+
+ @Test
+ public void listPatchesAgainstOtherPatchSet() throws GitAPIException,
+ IOException, PatchListNotAvailableException, OrmException,
+ RestApiException {
+ add(git, FILE_D, "4");
+ createCommit(git, admin.getIdent(), SUBJECT_1);
+ pushHead(git, "refs/heads/master", false);
+
+ // Change 1,1 (+FILE_A, +FILE_C, -FILE_D)
+ add(git, FILE_A, "1");
+ add(git, FILE_C, "3");
+ rm(git, FILE_D);
+ Commit c = createCommit(git, admin.getIdent(), SUBJECT_2);
+ pushHead(git, "refs/for/master", false);
+ ObjectId a = getCurrentRevisionId(c.getChangeId());
+
+ // Change 1,2 (+FILE_A, +FILE_B, -FILE_D)
+ add(git, FILE_B, "2");
+ rm(git, FILE_C);
+ c = amendCommit(git, admin.getIdent(), SUBJECT_2, c.getChangeId());
+ pushHead(git, "refs/for/master", false);
+ ObjectId b = getCurrentRevisionId(c.getChangeId());
+
+ // Compare Change 1,1 with Change 1,2 (+FILE_B)
+ List<PatchListEntry> entries = getPatches(a, b);
+ assertEquals(2, entries.size());
+ assertModified(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_B, entries.get(1));
+ }
+
+ @Test
+ public void listPatchesAgainstOtherPatchSetWithRebase()
+ throws GitAPIException, IOException, PatchListNotAvailableException,
+ OrmException, RestApiException {
+ add(git, FILE_D, "4");
+ createCommit(git, admin.getIdent(), SUBJECT_1);
+ pushHead(git, "refs/heads/master", false);
+
+ // Change 1,1 (+FILE_A, -FILE_D)
+ add(git, FILE_A, "1");
+ rm(git, FILE_D);
+ Commit c = createCommit(git, admin.getIdent(), SUBJECT_2);
+ pushHead(git, "refs/for/master", false);
+ ObjectId a = getCurrentRevisionId(c.getChangeId());
+
+ // Change 2,1 (+FILE_B)
+ git.reset().setMode(ResetType.HARD).setRef("HEAD~1").call();
+ add(git, FILE_B, "2");
+ createCommit(git, admin.getIdent(), SUBJECT_3);
+ pushHead(git, "refs/for/master", false);
+
+ // Change 1,2 (+FILE_A, +FILE_C, -FILE_D)
+ git.cherryPick().include(c.getCommit()).call();
+ add(git, FILE_C, "2");
+ c = amendCommit(git, admin.getIdent(), SUBJECT_2, c.getChangeId());
+ pushHead(git, "refs/for/master", false);
+ ObjectId b = getCurrentRevisionId(c.getChangeId());
+
+ // Compare Change 1,1 with Change 1,2 (+FILE_C)
+ List<PatchListEntry> entries = getPatches(a, b);
+ assertEquals(2, entries.size());
+ assertModified(Patch.COMMIT_MSG, entries.get(0));
+ assertAdded(FILE_C, entries.get(1));
+ }
+
+ private static void assertAdded(String expectedNewName, PatchListEntry e) {
+ assertName(expectedNewName, e);
+ assertEquals(ChangeType.ADDED, e.getChangeType());
+ }
+
+ private static void assertModified(String expectedNewName, PatchListEntry e) {
+ assertName(expectedNewName, e);
+ assertEquals(ChangeType.MODIFIED, e.getChangeType());
+ }
+
+ private static void assertDeleted(String expectedNewName, PatchListEntry e) {
+ assertName(expectedNewName, e);
+ assertEquals(ChangeType.DELETED, e.getChangeType());
+ }
+
+ private static void assertName(String expectedNewName, PatchListEntry e) {
+ assertEquals(expectedNewName, e.getNewName());
+ assertNull(e.getOldName());
+ }
+
+ private List<PatchListEntry> getCurrentPatches(String changeId)
+ throws PatchListNotAvailableException, OrmException, RestApiException {
+ return patchListCache.get(getKey(null, getCurrentRevisionId(changeId))).getPatches();
+ }
+
+ private List<PatchListEntry> getPatches(ObjectId revisionIdA, ObjectId revisionIdB)
+ throws PatchListNotAvailableException, OrmException {
+ return patchListCache.get(getKey(revisionIdA, revisionIdB)).getPatches();
+ }
+
+ private PatchListKey getKey(ObjectId revisionIdA, ObjectId revisionIdB) throws OrmException {
+ return new PatchListKey(project, revisionIdA, revisionIdB, Whitespace.IGNORE_NONE);
+ }
+
+ private ObjectId getCurrentRevisionId(String changeId) throws RestApiException {
+ return ObjectId.fromString(gApi.changes().id(changeId).get().currentRevision);
+ }
+}
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
index ecf0d9e..201a0bd 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
@@ -30,49 +30,43 @@
throws RestApiException;
ChangeApi create(ChangeInfo in) throws RestApiException;
- /**
- * Shorthand for {@link #query(QueryParameter)} without any conditions (i.e. lists all changes).
- */
- List<ChangeInfo> query() throws RestApiException;
- List<ChangeInfo> query(QueryParameter queryParameter) throws RestApiException;
+ QueryRequest query();
+ QueryRequest query(String query);
- public class QueryParameter {
+ public abstract class QueryRequest {
private String query;
private int limit;
private int start;
private EnumSet<ListChangesOption> options = EnumSet.noneOf(ListChangesOption.class);
- public QueryParameter() {}
+ public abstract List<ChangeInfo> get() throws RestApiException;
- public QueryParameter(String query) {
- this.query = query;
- }
-
- public QueryParameter withQuery(String query) {
+ public QueryRequest withQuery(String query) {
this.query = query;
return this;
}
- public QueryParameter withLimit(int limit) {
+ public QueryRequest withLimit(int limit) {
this.limit = limit;
return this;
}
- public QueryParameter withStart(int start) {
+ public QueryRequest withStart(int start) {
this.start = start;
return this;
}
- public QueryParameter withOption(ListChangesOption options) {
+ public QueryRequest withOption(ListChangesOption options) {
this.options.add(options);
return this;
}
- public QueryParameter withOptions(ListChangesOption... options) {
+
+ public QueryRequest withOptions(ListChangesOption... options) {
this.options.addAll(Arrays.asList(options));
return this;
}
- public QueryParameter withOptions(EnumSet<ListChangesOption> options) {
+ public QueryRequest withOptions(EnumSet<ListChangesOption> options) {
this.options = options;
return this;
}
@@ -120,12 +114,12 @@
}
@Override
- public List<ChangeInfo> query() throws RestApiException {
+ public QueryRequest query() {
throw new NotImplementedException();
}
@Override
- public List<ChangeInfo> query(QueryParameter queryParameter) throws RestApiException {
+ public QueryRequest query(String query) {
throw new NotImplementedException();
}
}
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
index 02351cd..9c0cfd8 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
@@ -23,37 +23,32 @@
public interface Projects {
ProjectApi name(String name) throws RestApiException;
- List<ProjectInfo> list() throws RestApiException;
- List<ProjectInfo> list(ListParameter listParameter) throws RestApiException;
+ ListRequest list();
- public class ListParameter {
+ public abstract class ListRequest {
private boolean description;
private String prefix;
private int limit;
private int start;
- public ListParameter() {}
+ public abstract List<ProjectInfo> get() throws RestApiException;
- public ListParameter(String prefix) {
- this.prefix = prefix;
- }
-
- public ListParameter withDescription(boolean description) {
+ public ListRequest withDescription(boolean description) {
this.description = description;
return this;
}
- public ListParameter withPrefix(String prefix) {
+ public ListRequest withPrefix(String prefix) {
this.prefix = prefix;
return this;
}
- public ListParameter withLimit(int limit) {
+ public ListRequest withLimit(int limit) {
this.limit = limit;
return this;
}
- public ListParameter withStart(int start) {
+ public ListRequest withStart(int start) {
this.start = start;
return this;
}
@@ -86,12 +81,7 @@
}
@Override
- public List<ProjectInfo> list() throws RestApiException {
- throw new NotImplementedException();
- }
-
- @Override
- public List<ProjectInfo> list(ListParameter listParameter) throws RestApiException {
+ public ListRequest list() {
throw new NotImplementedException();
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java
index b8cc5c2d..053999a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java
@@ -80,27 +80,33 @@
setHeight(info.height() > 0 ? info.height() + "px" : "");
setUrl(info.url());
popup(account, addPopup);
+ } else if (account.email() != null) {
+ loadAvatar(account, size, addPopup);
}
} else if (account.email() != null) {
- // TODO Kill /accounts/*/avatar URL.
- String u = account.email();
- if (Gerrit.isSignedIn()
- && u.equals(Gerrit.getUserAccount().getPreferredEmail())) {
- u = "self";
- }
- RestApi api = new RestApi("/accounts/").id(u).view("avatar");
- if (size > 0) {
- api.addParameter("s", size);
- setSize("", size + "px");
- }
- setVisible(false);
- setUrl(api.url());
- popup(account, addPopup);
+ loadAvatar(account, size, addPopup);
} else {
setVisible(false);
}
}
+ private void loadAvatar(AccountInfo account, int size, boolean addPopup) {
+ // TODO Kill /accounts/*/avatar URL.
+ String u = account.email();
+ if (Gerrit.isSignedIn()
+ && u.equals(Gerrit.getUserAccount().getPreferredEmail())) {
+ u = "self";
+ }
+ RestApi api = new RestApi("/accounts/").id(u).view("avatar");
+ if (size > 0) {
+ api.addParameter("s", size);
+ setSize("", size + "px");
+ }
+ setVisible(false);
+ setUrl(api.url());
+ popup(account, addPopup);
+ }
+
private void popup(AccountInfo account, boolean addPopup) {
if (addPopup) {
PopupHandler popupHandler = new PopupHandler(account, this);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java
index 1fab60a..2b78fa4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritResources.java
@@ -79,6 +79,6 @@
@Source("listAdd.png")
public ImageResource listAdd();
- @Source("important.png")
- public ImageResource important();
+ @Source("merge.png")
+ public ImageResource merge();
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java
index 915cbfb..162c19e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.java
@@ -46,7 +46,7 @@
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ScrollPanel;
-import com.google.gwt.user.client.ui.VerticalPanel;
+import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
@@ -67,7 +67,7 @@
@UiField TableCellElement webLinkCell;
@UiField Element parents;
@UiField FlowPanel parentCommits;
- @UiField VerticalPanel parentWebLinks;
+ @UiField FlowPanel parentWebLinks;
@UiField InlineHyperlink authorNameEmail;
@UiField Element authorDate;
@UiField InlineHyperlink committerNameEmail;
@@ -154,7 +154,7 @@
GitwebLink gw = Gerrit.getGitwebLink();
if (gw != null) {
Anchor a =
- new Anchor(gw.toRevision(project, c.commit()), gw.getLinkName());
+ new Anchor(gw.getLinkName(), gw.toRevision(project, c.commit()));
a.setStyleName(style.parentWebLink());
parentWebLinks.add(a);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml
index 456fa13..7fb43c4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CommitBox.ui.xml
@@ -86,9 +86,10 @@
}
.parentWebLink {
margin-left:16px;
+ display: block;
}
- .mergeCommit {
+ .commit {
margin-right: 3px;
float: left;
}
@@ -126,12 +127,12 @@
</tr>
<tr>
<th>
- <div class='{style.mergeCommit}'>
+ <div class='{style.commit}'>
<ui:msg>Commit</ui:msg>
</div>
<g:Image
ui:field='mergeCommit'
- resource='{ico.important}'
+ resource='{ico.merge}'
visible='false'
title='Merge Commit'>
<ui:attribute name='title'/>
@@ -146,7 +147,7 @@
<g:FlowPanel ui:field='parentCommits'/>
</td>
<td>
- <g:VerticalPanel ui:field='parentWebLinks'/>
+ <g:FlowPanel ui:field='parentWebLinks'/>
</td>
</tr>
<tr>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/important.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/important.png
deleted file mode 100644
index 81e9ed2..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/important.png
+++ /dev/null
Binary files differ
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/merge.png b/gerrit-gwtui/src/main/java/com/google/gerrit/client/merge.png
new file mode 100644
index 0000000..9c892db
--- /dev/null
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/merge.png
Binary files differ
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
index 11383ca..74dc56f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/DirectChangeByCommit.java
@@ -3,25 +3,20 @@
package com.google.gerrit.httpd;
import com.google.common.base.CharMatcher;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.PageLinks;
+import com.google.gerrit.extensions.api.changes.Changes;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.query.Predicate;
-import com.google.gerrit.server.query.QueryParseException;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.ChangeDataSource;
-import com.google.gerrit.server.query.change.ChangeQueryBuilder;
-import com.google.gerrit.server.query.change.ChangeQueryRewriter;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.util.HashSet;
+import java.util.List;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -33,53 +28,30 @@
private static final Logger log =
LoggerFactory.getLogger(DirectChangeByCommit.class);
- private final ChangeQueryBuilder.Factory queryBuilder;
- private final Provider<ChangeQueryRewriter> queryRewriter;
- private final Provider<CurrentUser> currentUser;
+ private final Changes changes;
@Inject
- DirectChangeByCommit(ChangeQueryBuilder.Factory queryBuilder,
- Provider<ChangeQueryRewriter> queryRewriter,
- Provider<CurrentUser> currentUser) {
- this.queryBuilder = queryBuilder;
- this.queryRewriter = queryRewriter;
- this.currentUser = currentUser;
+ DirectChangeByCommit(Changes changes) {
+ this.changes = changes;
}
@Override
protected void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
String query = CharMatcher.is('/').trimTrailingFrom(req.getPathInfo());
- HashSet<Change.Id> ids = new HashSet<>();
+ List<ChangeInfo> results;
try {
- ChangeQueryBuilder builder = queryBuilder.create(currentUser.get());
- Predicate<ChangeData> visibleToMe = builder.is_visible();
- Predicate<ChangeData> q = builder.parse(query);
- q = Predicate.and(q, builder.sortkey_before("z"), builder.limit(2), visibleToMe);
-
- ChangeQueryRewriter rewriter = queryRewriter.get();
- Predicate<ChangeData> s = rewriter.rewrite(q, 0);
- if (!(s instanceof ChangeDataSource)) {
- s = rewriter.rewrite(Predicate.and(builder.status_open(), q), 0);
- }
-
- if (s instanceof ChangeDataSource) {
- for (ChangeData d : ((ChangeDataSource) s).read()) {
- ids.add(d.getId());
- }
- }
- } catch (QueryParseException e) {
- log.info("Received invalid query by URL: /r/" + query);
- } catch (OrmException e) {
+ results = changes.query(query).withLimit(2).get();
+ } catch (RestApiException e) {
log.warn("Cannot process query by URL: /r/" + query, e);
+ results = ImmutableList.of();
}
-
String token;
- if (ids.size() == 1) {
+ if (results.size() == 1) {
// If exactly one change matches, link to that change.
// TODO Link to a specific patch set, if one matched.
- token = PageLinks.toChange(ids.iterator().next());
-
+ token = PageLinks.toChange(
+ new Change.Id(results.iterator().next()._number));
} else {
// Otherwise, link to the query page.
token = PageLinks.toChangeQuery(query);
diff --git a/gerrit-plugin-archetype/pom.xml b/gerrit-plugin-archetype/pom.xml
index 8c7e261..404f0d9 100644
--- a/gerrit-plugin-archetype/pom.xml
+++ b/gerrit-plugin-archetype/pom.xml
@@ -22,6 +22,8 @@
<artifactId>gerrit-plugin-archetype</artifactId>
<version>2.10-SNAPSHOT</version>
<name>Gerrit Code Review - Plugin Archetype</name>
+ <description>Maven Archetype for Gerrit Plugins</description>
+ <url>http://code.google.com/p/gerrit/</url>
<properties>
<defaultGerritApiVersion>${project.version}</defaultGerritApiVersion>
@@ -46,4 +48,52 @@
</resources>
</build>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <scm>
+ <url>https://gerrit.googlesource.com/gerrit</url>
+ <connection>https://gerrit.googlesource.com/gerrit</connection>
+ </scm>
+
+ <developers>
+ <developer>
+ <name>Dave Borowitz</name>
+ </developer>
+ <developer>
+ <name>David Pursehouse</name>
+ </developer>
+ <developer>
+ <name>Edwin Kempin</name>
+ </developer>
+ <developer>
+ <name>Martin Fick</name>
+ </developer>
+ <developer>
+ <name>Saša Živkov</name>
+ </developer>
+ <developer>
+ <name>Shawn Pearce</name>
+ </developer>
+ </developers>
+
+ <mailingLists>
+ <mailingList>
+ <name>Repo and Gerrit Discussion</name>
+ <post>repo-discuss@googlegroups.com</post>
+ <subscribe>https://groups.google.com/forum/#!forum/repo-discuss</subscribe>
+ <unsubscribe>https://groups.google.com/forum/#!forum/repo-discuss</unsubscribe>
+ <archive>https://groups.google.com/forum/#!forum/repo-discuss</archive>
+ </mailingList>
+ </mailingLists>
+
+ <issueManagement>
+ <url>http://code.google.com/p/gerrit/issues/list</url>
+ <system>Google Code Issue Tracker</system>
+ </issueManagement>
</project>
diff --git a/gerrit-plugin-gwt-archetype/pom.xml b/gerrit-plugin-gwt-archetype/pom.xml
index 09f70e8..38b223a 100644
--- a/gerrit-plugin-gwt-archetype/pom.xml
+++ b/gerrit-plugin-gwt-archetype/pom.xml
@@ -21,7 +21,9 @@
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-plugin-gwt-archetype</artifactId>
<version>2.10-SNAPSHOT</version>
- <name>Gerrit Code Review - Web Ui GWT Plugin Archetype</name>
+ <name>Gerrit Code Review - Web UI GWT Plugin Archetype</name>
+ <description>Maven Archetype for Gerrit Web UI GWT Plugins</description>
+ <url>http://code.google.com/p/gerrit/</url>
<properties>
<defaultGerritApiVersion>${project.version}</defaultGerritApiVersion>
@@ -46,4 +48,52 @@
</resources>
</build>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <scm>
+ <url>https://gerrit.googlesource.com/gerrit</url>
+ <connection>https://gerrit.googlesource.com/gerrit</connection>
+ </scm>
+
+ <developers>
+ <developer>
+ <name>Dave Borowitz</name>
+ </developer>
+ <developer>
+ <name>David Pursehouse</name>
+ </developer>
+ <developer>
+ <name>Edwin Kempin</name>
+ </developer>
+ <developer>
+ <name>Martin Fick</name>
+ </developer>
+ <developer>
+ <name>Saša Živkov</name>
+ </developer>
+ <developer>
+ <name>Shawn Pearce</name>
+ </developer>
+ </developers>
+
+ <mailingLists>
+ <mailingList>
+ <name>Repo and Gerrit Discussion</name>
+ <post>repo-discuss@googlegroups.com</post>
+ <subscribe>https://groups.google.com/forum/#!forum/repo-discuss</subscribe>
+ <unsubscribe>https://groups.google.com/forum/#!forum/repo-discuss</unsubscribe>
+ <archive>https://groups.google.com/forum/#!forum/repo-discuss</archive>
+ </mailingList>
+ </mailingLists>
+
+ <issueManagement>
+ <url>http://code.google.com/p/gerrit/issues/list</url>
+ <system>Google Code Issue Tracker</system>
+ </issueManagement>
</project>
diff --git a/gerrit-plugin-js-archetype/pom.xml b/gerrit-plugin-js-archetype/pom.xml
index b99130e..9da4e89 100644
--- a/gerrit-plugin-js-archetype/pom.xml
+++ b/gerrit-plugin-js-archetype/pom.xml
@@ -22,6 +22,8 @@
<artifactId>gerrit-plugin-js-archetype</artifactId>
<version>2.10-SNAPSHOT</version>
<name>Gerrit Code Review - Web UI JavaScript Plugin Archetype</name>
+ <description>Maven Archetype for Gerrit Web UI JavaScript Plugins</description>
+ <url>http://code.google.com/p/gerrit/</url>
<properties>
<defaultGerritApiVersion>${project.version}</defaultGerritApiVersion>
@@ -46,4 +48,52 @@
</resources>
</build>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <scm>
+ <url>https://gerrit.googlesource.com/gerrit</url>
+ <connection>https://gerrit.googlesource.com/gerrit</connection>
+ </scm>
+
+ <developers>
+ <developer>
+ <name>Dave Borowitz</name>
+ </developer>
+ <developer>
+ <name>David Pursehouse</name>
+ </developer>
+ <developer>
+ <name>Edwin Kempin</name>
+ </developer>
+ <developer>
+ <name>Martin Fick</name>
+ </developer>
+ <developer>
+ <name>Saša Živkov</name>
+ </developer>
+ <developer>
+ <name>Shawn Pearce</name>
+ </developer>
+ </developers>
+
+ <mailingLists>
+ <mailingList>
+ <name>Repo and Gerrit Discussion</name>
+ <post>repo-discuss@googlegroups.com</post>
+ <subscribe>https://groups.google.com/forum/#!forum/repo-discuss</subscribe>
+ <unsubscribe>https://groups.google.com/forum/#!forum/repo-discuss</unsubscribe>
+ <archive>https://groups.google.com/forum/#!forum/repo-discuss</archive>
+ </mailingList>
+ </mailingLists>
+
+ <issueManagement>
+ <url>http://code.google.com/p/gerrit/issues/list</url>
+ <system>Google Code Issue Tracker</system>
+ </issueManagement>
</project>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index 8d4a0c9..5c5c569 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -164,7 +164,7 @@
public ChangeInfo get(EnumSet<ListChangesOption> s)
throws RestApiException {
try {
- return new ChangeInfoMapper(s).map(
+ return ChangeInfoMapper.INSTANCE.apply(
changeJson.addOptions(s).format(change));
} catch (OrmException e) {
throw new RestApiException("Cannot retrieve change", e);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
index 6aab89c..8e6c20b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeInfoMapper.java
@@ -14,13 +14,7 @@
package com.google.gerrit.server.api.changes;
-import static com.google.gerrit.extensions.common.ListChangesOption.ALL_REVISIONS;
-import static com.google.gerrit.extensions.common.ListChangesOption.CURRENT_ACTIONS;
-import static com.google.gerrit.extensions.common.ListChangesOption.CURRENT_REVISION;
-import static com.google.gerrit.extensions.common.ListChangesOption.DETAILED_LABELS;
-import static com.google.gerrit.extensions.common.ListChangesOption.LABELS;
-import static com.google.gerrit.extensions.common.ListChangesOption.MESSAGES;
-
+import com.google.common.base.Function;
import com.google.common.collect.EnumBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -29,48 +23,46 @@
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.ChangeStatus;
import com.google.gerrit.extensions.common.LabelInfo;
-import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.server.api.accounts.AccountInfoMapper;
import com.google.gerrit.server.change.ChangeJson;
-import java.util.EnumSet;
import java.util.List;
import java.util.Map;
-public class ChangeInfoMapper {
- private final static EnumBiMap<Change.Status, ChangeStatus> MAP =
+public class ChangeInfoMapper
+ implements Function<ChangeJson.ChangeInfo, ChangeInfo> {
+ public static final ChangeInfoMapper INSTANCE = new ChangeInfoMapper();
+
+ private final static EnumBiMap<Change.Status, ChangeStatus> STATUS_MAP =
EnumBiMap.create(Change.Status.class, ChangeStatus.class);
static {
- MAP.put(Status.DRAFT, ChangeStatus.DRAFT);
- MAP.put(Status.NEW, ChangeStatus.NEW);
- MAP.put(Status.SUBMITTED, ChangeStatus.SUBMITTED);
- MAP.put(Status.MERGED, ChangeStatus.MERGED);
- MAP.put(Status.ABANDONED, ChangeStatus.ABANDONED);
+ STATUS_MAP.put(Status.DRAFT, ChangeStatus.DRAFT);
+ STATUS_MAP.put(Status.NEW, ChangeStatus.NEW);
+ STATUS_MAP.put(Status.SUBMITTED, ChangeStatus.SUBMITTED);
+ STATUS_MAP.put(Status.MERGED, ChangeStatus.MERGED);
+ STATUS_MAP.put(Status.ABANDONED, ChangeStatus.ABANDONED);
}
- private final EnumSet<ListChangesOption> s;
-
- ChangeInfoMapper(EnumSet<ListChangesOption> s) {
- this.s = s;
+ public static Status changeStatus2Status(ChangeStatus status) {
+ if (status != null) {
+ return STATUS_MAP.inverse().get(status);
+ }
+ return Change.Status.NEW;
}
- ChangeInfo map(ChangeJson.ChangeInfo i) {
+ private ChangeInfoMapper() {
+ }
+
+ @Override
+ public ChangeInfo apply(ChangeJson.ChangeInfo i) {
ChangeInfo o = new ChangeInfo();
mapCommon(i, o);
- if (has(LABELS) || has(DETAILED_LABELS)) {
- mapLabels(i, o);
- }
- if (has(MESSAGES)) {
- mapMessages(i, o);
- }
- if (has(ALL_REVISIONS) || has(CURRENT_REVISION)) {
- o.revisions = i.revisions;
- }
- if (has(CURRENT_ACTIONS)) {
- o.actions = i.actions;
- }
+ mapLabels(i, o);
+ mapMessages(i, o);
+ o.revisions = i.revisions;
+ o.actions = i.actions;
return o;
}
@@ -81,7 +73,7 @@
o.topic = i.topic;
o.changeId = i.changeId;
o.subject = i.subject;
- o.status = MAP.get(i.status);
+ o.status = STATUS_MAP.get(i.status);
o.created = i.created;
o.updated = i.updated;
o.starred = i.starred;
@@ -95,6 +87,9 @@
}
private void mapMessages(ChangeJson.ChangeInfo i, ChangeInfo o) {
+ if (i.messages == null) {
+ return;
+ }
List<ChangeMessageInfo> r =
Lists.newArrayListWithCapacity(i.messages.size());
for (ChangeJson.ChangeMessageInfo m : i.messages) {
@@ -110,6 +105,9 @@
}
private void mapLabels(ChangeJson.ChangeInfo i, ChangeInfo o) {
+ if (i.labels == null) {
+ return;
+ }
Map<String, LabelInfo> r = Maps.newLinkedHashMap();
for (Map.Entry<String, ChangeJson.LabelInfo> e : i.labels.entrySet()) {
ChangeJson.LabelInfo li = e.getValue();
@@ -134,17 +132,6 @@
o.labels = r;
}
- private boolean has(ListChangesOption o) {
- return s.contains(o);
- }
-
- public static Status changeStatus2Status(ChangeStatus status) {
- if (status != null) {
- return MAP.inverse().get(status);
- }
- return Change.Status.NEW;
- }
-
private static ApprovalInfo fromApprovalInfo(ChangeJson.ApprovalInfo ai) {
ApprovalInfo ao = new ApprovalInfo();
ao.value = ai.value;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
index 976228f..0718810 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangesImpl.java
@@ -14,11 +14,18 @@
package com.google.gerrit.server.api.changes;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.ListChangesOption;
+import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
@@ -27,23 +34,29 @@
import com.google.gerrit.server.change.ChangesCollection;
import com.google.gerrit.server.change.CreateChange;
import com.google.gerrit.server.project.InvalidChangeOperationException;
+import com.google.gerrit.server.query.change.QueryChanges;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import java.io.IOException;
+import java.util.List;
-class ChangesImpl extends Changes.NotImplemented implements Changes {
+class ChangesImpl implements Changes {
private final ChangesCollection changes;
private final ChangeApiImpl.Factory api;
private final CreateChange.Factory createChangeFactory;
+ private final Provider<QueryChanges> queryProvider;
@Inject
ChangesImpl(ChangesCollection changes,
ChangeApiImpl.Factory api,
- CreateChange.Factory createChangeFactory) {
+ CreateChange.Factory createChangeFactory,
+ Provider<QueryChanges> queryProvider) {
this.changes = changes;
this.api = api;
this.createChangeFactory = createChangeFactory;
+ this.queryProvider = queryProvider;
}
@Override
@@ -82,4 +95,50 @@
throw new RestApiException("Cannot create change", e);
}
}
+
+ @Override
+ public QueryRequest query() {
+ return new QueryRequest() {
+ @Override
+ public List<ChangeInfo> get() throws RestApiException {
+ return ChangesImpl.this.get(this);
+ }
+ };
+ }
+
+ @Override
+ public QueryRequest query(String query) {
+ return query().withQuery(query);
+ }
+
+ private List<ChangeInfo> get(final QueryRequest q) throws RestApiException {
+ QueryChanges qc = queryProvider.get();
+ if (q.getQuery() != null) {
+ qc.addQuery(q.getQuery());
+ }
+ qc.setLimit(q.getLimit());
+ qc.setStart(q.getStart());
+ for (ListChangesOption option : q.getOptions()) {
+ qc.addOption(option);
+ }
+
+ try {
+ List<?> result = qc.apply(TopLevelResource.INSTANCE);
+ if (result.isEmpty()) {
+ return ImmutableList.of();
+ }
+
+ // Check type safety of result; the extension API should be safer than the
+ // REST API in this case, since it's intended to be used in Java.
+ Object first = checkNotNull(result.iterator().next());
+ checkState(first instanceof ChangeJson.ChangeInfo);
+ @SuppressWarnings("unchecked")
+ List<ChangeJson.ChangeInfo> infos = (List<ChangeJson.ChangeInfo>) result;
+
+ return ImmutableList.copyOf(
+ Lists.transform(infos, ChangeInfoMapper.INSTANCE));
+ } catch (BadRequestException | AuthException | OrmException e) {
+ throw new RestApiException("Cannot query changes", e);
+ }
+ }
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
index 66ea1e0..ebf5ac7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java
@@ -42,7 +42,7 @@
import java.util.List;
-class EmailArguments {
+public class EmailArguments {
final GitRepositoryManager server;
final ProjectCache projectCache;
final GroupBackend groupBackend;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
index c36fbc0..ff03840 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListKey.java
@@ -34,7 +34,7 @@
import java.io.Serializable;
public class PatchListKey implements Serializable {
- static final long serialVersionUID = 16L;
+ static final long serialVersionUID = 17L;
private transient ObjectId oldId;
private transient ObjectId newId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
index f704ea2..d4131b0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchListLoader.java
@@ -15,7 +15,9 @@
package com.google.gerrit.server.patch;
+import com.google.common.base.Function;
import com.google.common.cache.CacheLoader;
+import com.google.common.collect.FluentIterable;
import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -51,8 +53,6 @@
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.treewalk.TreeWalk;
-import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.io.DisabledOutputStream;
import org.slf4j.Logger;
@@ -60,23 +60,28 @@
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
public class PatchListLoader extends CacheLoader<PatchListKey, PatchList> {
static final Logger log = LoggerFactory.getLogger(PatchListLoader.class);
private final GitRepositoryManager repoManager;
+ private final PatchListCache patchListCache;
@Inject
- PatchListLoader(GitRepositoryManager mgr) {
+ PatchListLoader(GitRepositoryManager mgr, PatchListCache plc) {
repoManager = mgr;
+ patchListCache = plc;
}
@Override
- public PatchList load(final PatchListKey key) throws Exception {
+ public PatchList load(final PatchListKey key) throws IOException,
+ PatchListNotAvailableException {
final Repository repo = repoManager.openRepository(key.projectKey);
try {
return readPatchList(key, repo);
@@ -102,8 +107,8 @@
}
}
- private PatchList readPatchList(final PatchListKey key,
- final Repository repo) throws IOException {
+ private PatchList readPatchList(final PatchListKey key, final Repository repo)
+ throws IOException, PatchListNotAvailableException {
final RawTextComparator cmp = comparatorFor(key.getWhitespace());
final ObjectReader reader = repo.newObjectReader();
try {
@@ -123,42 +128,42 @@
final boolean againstParent =
b.getParentCount() > 0 && b.getParent(0) == a;
- RevCommit aCommit;
- RevTree aTree;
- if (a instanceof RevCommit) {
- aCommit = (RevCommit) a;
- aTree = aCommit.getTree();
- } else if (a instanceof RevTree) {
- aCommit = null;
- aTree = (RevTree) a;
- } else {
- throw new IOException("Unexpected type: " + a.getClass());
- }
-
+ RevCommit aCommit = a instanceof RevCommit ? (RevCommit) a : null;
+ RevTree aTree = rw.parseTree(a);
RevTree bTree = b.getTree();
- final TreeWalk walk = new TreeWalk(reader);
- walk.reset();
- walk.setRecursive(true);
- walk.addTree(aTree);
- walk.addTree(bTree);
- walk.setFilter(TreeFilter.ANY_DIFF);
-
DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
df.setRepository(repo);
df.setDiffComparator(cmp);
df.setDetectRenames(true);
List<DiffEntry> diffEntries = df.scan(aTree, bTree);
- final int cnt = diffEntries.size();
- final PatchListEntry[] entries = new PatchListEntry[1 + cnt];
- entries[0] = newCommitMessage(cmp, repo, reader, //
- againstParent ? null : aCommit, b);
+ Set<String> paths = key.getOldId() != null
+ ? FluentIterable.from(patchListCache.get(
+ new PatchListKey(key.projectKey, null, key.getNewId(),
+ key.getWhitespace())).getPatches())
+ .transform(new Function<PatchListEntry, String>() {
+ @Override
+ public String apply(PatchListEntry entry) {
+ return entry.getNewName();
+ }
+ })
+ .toSet()
+ : null;
+ int cnt = diffEntries.size();
+ List<PatchListEntry> entries = new ArrayList<>();
+ entries.add(newCommitMessage(cmp, repo, reader, //
+ againstParent ? null : aCommit, b));
for (int i = 0; i < cnt; i++) {
- FileHeader fh = df.toFileHeader(diffEntries.get(i));
- entries[1 + i] = newEntry(aTree, fh);
+ DiffEntry diffEntry = diffEntries.get(i);
+ if (paths == null || paths.contains(diffEntry.getNewPath())
+ || paths.contains(diffEntry.getOldPath())) {
+ FileHeader fh = df.toFileHeader(diffEntry);
+ entries.add(newEntry(aTree, fh));
+ }
}
- return new PatchList(a, b, againstParent, entries);
+ return new PatchList(a, b, againstParent,
+ entries.toArray(new PatchListEntry[entries.size()]));
} finally {
reader.release();
}
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 41c2e23..fb55b49 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
@@ -106,7 +106,7 @@
}
@Override
- public Object apply(TopLevelResource rsrc)
+ public List<?> apply(TopLevelResource rsrc)
throws BadRequestException, AuthException, OrmException {
List<List<ChangeInfo>> out;
try {
diff --git a/tools/maven/package.defs b/tools/maven/package.defs
index 9e5a144..a9dc60c 100644
--- a/tools/maven/package.defs
+++ b/tools/maven/package.defs
@@ -21,27 +21,51 @@
doc = {},
war = {}):
cmd = ['$(exe //tools/maven:mvn)', '-v', version, '-o', '$OUT']
- dep = []
-
- for type,d in [('jar', jar), ('java-source', src), ('javadoc', doc), ('war', war)]:
+ api_cmd = []
+ api_deps = []
+ for type,d in [('jar', jar), ('java-source', src), ('javadoc', doc)]:
for a,t in d.iteritems():
- cmd.append('-s %s:%s:$(location %s)' % (a,type,t))
- dep.append(t)
+ api_cmd.append('-s %s:%s:$(location %s)' % (a,type,t))
+ api_deps.append(t)
genrule(
- name = 'install',
- cmd = ' '.join(cmd + ['-a', 'install']),
- deps = dep + ['//tools/maven:mvn'],
- out = 'install.info',
+ name = 'api_install',
+ cmd = ' '.join(cmd + api_cmd + ['-a', 'install']),
+ deps = api_deps + ['//tools/maven:mvn'],
+ out = 'api_install.info',
)
if repository and url:
genrule(
- name = 'deploy',
- cmd = ' '.join(cmd + [
+ name = 'api_deploy',
+ cmd = ' '.join(cmd + api_cmd + [
'-a', 'deploy',
'--repository', repository,
'--url', url]),
- deps = dep + ['//tools/maven:mvn'],
- out = 'deploy.info',
+ deps = api_deps + ['//tools/maven:mvn'],
+ out = 'api_deploy.info',
+ )
+
+ war_cmd = []
+ war_deps = []
+ for a,t in war.iteritems():
+ war_cmd.append('-s %s:war:$(location %s)' % (a,t))
+ war_deps.append(t)
+
+ genrule(
+ name = 'war_install',
+ cmd = ' '.join(cmd + war_cmd + ['-a', 'install']),
+ deps = war_deps + ['//tools/maven:mvn'],
+ out = 'war_install.info',
+ )
+
+ if repository and url:
+ genrule(
+ name = 'war_deploy',
+ cmd = ' '.join(cmd + war_cmd + [
+ '-a', 'deploy',
+ '--repository', repository,
+ '--url', url]),
+ deps = war_deps + ['//tools/maven:mvn'],
+ out = 'war_deploy.info',
)