diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java index 6e592840b5..3a14be7089 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java @@ -22,6 +22,8 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gwtorm.client.KeyUtil; public class PageLinks { + public static final String PROJECT_CHANGE_DELIMITER = "/+/"; + public static final String SETTINGS = "/settings/"; public static final String SETTINGS_PREFERENCES = "/settings/preferences"; public static final String SETTINGS_DIFF_PREFERENCES = "/settings/diff-preferences"; @@ -51,20 +53,21 @@ public class PageLinks { public static final String MY_GROUPS = "/groups/self"; public static final String DOCUMENTATION = "/Documentation/"; - public static String toChangeInEditMode(Change.Id c) { - return "/c/" + c + ",edit/"; + public static String toChangeInEditMode(@Nullable Project.NameKey project, Change.Id c) { + return toChangeNoSlash(project, c) + ",edit/"; } - public static String toChange(Change.Id c) { - return "/c/" + c + "/"; + public static String toChange(@Nullable Project.NameKey project, Change.Id c) { + return toChangeNoSlash(project, c) + "/"; } - public static String toChange(Change.Id c, String p) { - return "/c/" + c + "/" + p; + public static String toChange(@Nullable Project.NameKey project, Change.Id c, String p) { + return toChange(project, c) + p; } - public static String toChange(Change.Id c, String b, String p) { - String u = "/c/" + c + "/"; + public static String toChange( + @Nullable Project.NameKey project, Change.Id c, String b, String p) { + String u = toChange(project, c); if (b != null) { u += b + ".."; } @@ -72,8 +75,15 @@ public class PageLinks { return u; } - public static String toChange(PatchSet.Id ps) { - return "/c/" + ps.getParentKey() + "/" + ps.getId(); + public static String toChangeId(@Nullable Project.NameKey project, Change.Id c) { + if (project == null) { + return String.valueOf(c.get()); + } + return project.get() + PROJECT_CHANGE_DELIMITER + c.get(); + } + + public static String toChange(@Nullable Project.NameKey project, PatchSet.Id ps) { + return toChange(project, ps.getParentKey()) + ps.getId(); } public static String toProject(Project.NameKey p) { @@ -166,6 +176,13 @@ public class PageLinks { } } + private static String toChangeNoSlash(@Nullable Project.NameKey project, Change.Id c) { + if (project != null) { + return "/c/" + project.get() + PROJECT_CHANGE_DELIMITER + c; + } + return "/c/" + c; + } + public static String op(String op, int value) { return op + ":" + value; } diff --git a/gerrit-gwtui/BUILD b/gerrit-gwtui/BUILD index 721b64609e..ff1b86226d 100644 --- a/gerrit-gwtui/BUILD +++ b/gerrit-gwtui/BUILD @@ -34,6 +34,7 @@ junit_tests( "//gerrit-common:client", "//gerrit-extension-api:client", "//lib:junit", + "//lib:truth", "//lib/gwt:dev", "//lib/gwt:user", ], diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java index 0081783a18..a48ab13171 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java @@ -40,7 +40,6 @@ import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES; import static com.google.gerrit.common.PageLinks.SETTINGS_PROJECTS; import static com.google.gerrit.common.PageLinks.SETTINGS_SSHKEYS; import static com.google.gerrit.common.PageLinks.SETTINGS_WEBIDENT; -import static com.google.gerrit.common.PageLinks.toChangeQuery; import com.google.gerrit.client.account.MyAgreementsScreen; import com.google.gerrit.client.account.MyContactInformationScreen; @@ -77,6 +76,7 @@ import com.google.gerrit.client.api.ExtensionScreen; import com.google.gerrit.client.api.ExtensionSettingsScreen; import com.google.gerrit.client.change.ChangeScreen; import com.google.gerrit.client.change.FileTable; +import com.google.gerrit.client.change.ProjectChangeId; import com.google.gerrit.client.changes.AccountDashboardScreen; import com.google.gerrit.client.changes.CustomDashboardScreen; import com.google.gerrit.client.changes.ProjectDashboardScreen; @@ -93,6 +93,7 @@ import com.google.gerrit.client.info.GroupInfo; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.ui.Screen; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView; import com.google.gerrit.reviewdb.client.Account; @@ -108,53 +109,65 @@ import com.google.gwtexpui.user.client.UserAgent; import com.google.gwtorm.client.KeyUtil; public class Dispatcher { - public static String toPatch(DiffObject diffBase, PatchSet.Id revision, String fileName) { - return toPatch("", diffBase, revision, fileName, null, 0); + public static String toPatch( + @Nullable Project.NameKey project, + DiffObject diffBase, + PatchSet.Id revision, + String fileName) { + return toPatch("", project, diffBase, revision, fileName, null, 0); } public static String toPatch( - DiffObject diffBase, PatchSet.Id revision, String fileName, DisplaySide side, int line) { - return toPatch("", diffBase, revision, fileName, side, line); + @Nullable Project.NameKey project, + DiffObject diffBase, + PatchSet.Id revision, + String fileName, + DisplaySide side, + int line) { + return toPatch("", project, diffBase, revision, fileName, side, line); } - public static String toSideBySide(DiffObject diffBase, Patch.Key id) { - return toPatch("sidebyside", diffBase, id); + public static String toSideBySide( + @Nullable Project.NameKey project, + DiffObject diffBase, + PatchSet.Id revision, + String fileName) { + return toPatch("sidebyside", project, diffBase, revision, fileName, null, 0); } - public static String toSideBySide(DiffObject diffBase, PatchSet.Id revision, String fileName) { - return toPatch("sidebyside", diffBase, revision, fileName, null, 0); + public static String toUnified( + @Nullable Project.NameKey project, + DiffObject diffBase, + PatchSet.Id revision, + String fileName) { + return toPatch("unified", project, diffBase, revision, fileName, null, 0); } - public static String toUnified(DiffObject diffBase, PatchSet.Id revision, String fileName) { - return toPatch("unified", diffBase, revision, fileName, null, 0); + public static String toPatch( + @Nullable Project.NameKey project, String type, DiffObject diffBase, Patch.Key id) { + return toPatch(type, project, diffBase, id.getParentKey(), id.get(), null, 0); } - public static String toUnified(DiffObject diffBase, Patch.Key id) { - return toPatch("unified", diffBase, id); + public static String toEditScreen( + @Nullable Project.NameKey project, PatchSet.Id revision, String fileName) { + return toEditScreen(project, revision, fileName, 0); } - public static String toPatch(String type, DiffObject diffBase, Patch.Key id) { - return toPatch(type, diffBase, id.getParentKey(), id.get(), null, 0); - } - - public static String toEditScreen(PatchSet.Id revision, String fileName) { - return toEditScreen(revision, fileName, 0); - } - - public static String toEditScreen(PatchSet.Id revision, String fileName, int line) { - return toPatch("edit", DiffObject.base(), revision, fileName, null, line); + public static String toEditScreen( + @Nullable Project.NameKey project, PatchSet.Id revision, String fileName, int line) { + return toPatch("edit", project, DiffObject.base(), revision, fileName, null, line); } private static String toPatch( String type, + @Nullable Project.NameKey project, DiffObject diffBase, PatchSet.Id revision, String fileName, DisplaySide side, int line) { Change.Id c = revision.getParentKey(); - StringBuilder p = new StringBuilder(); - p.append("/c/").append(c).append("/"); + StringBuilder p = new StringBuilder(PageLinks.toChange(project, c)); if (diffBase != null && diffBase.asString() != null) { p.append(diffBase.asString()).append(".."); } @@ -343,7 +356,8 @@ public class Dispatcher { public void onFailure(Throwable caught) { if ("default".equals(dashboardId) && RestApi.isNotFound(caught)) { Gerrit.display( - toChangeQuery(PageLinks.projectQuery(new Project.NameKey(project)))); + PageLinks.toChangeQuery( + PageLinks.projectQuery(new Project.NameKey(project)))); } else { super.onFailure(caught); } @@ -380,15 +394,8 @@ public class Dispatcher { } } - Change.Id id; - int s = rest.indexOf('/'); - if (0 <= s) { - id = Change.Id.parse(rest.substring(0, s)); - rest = rest.substring(s + 1); - } else { - id = Change.Id.parse(rest); - rest = ""; - } + ProjectChangeId id = ProjectChangeId.create(rest); + rest = rest.length() > id.identifierLength() ? rest.substring(id.identifierLength() + 1) : ""; if (rest.isEmpty()) { FileTable.Mode mode = FileTable.Mode.REVIEW; @@ -399,13 +406,14 @@ public class Dispatcher { Gerrit.display( token, panel == null - ? new ChangeScreen(id, DiffObject.base(), null, false, mode) + ? new ChangeScreen( + id.getProject(), id.getChangeId(), DiffObject.base(), null, false, mode) : new NotFoundScreen()); return; } String psIdStr; - s = rest.indexOf('/'); + int s = rest.indexOf('/'); if (0 <= s) { psIdStr = rest.substring(0, s); rest = rest.substring(s + 1); @@ -418,13 +426,13 @@ public class Dispatcher { PatchSet.Id ps; int dotdot = psIdStr.indexOf(".."); if (1 <= dotdot) { - base = DiffObject.parse(id, psIdStr.substring(0, dotdot)); + base = DiffObject.parse(id.getChangeId(), psIdStr.substring(0, dotdot)); if (base == null) { Gerrit.display(token, new NotFoundScreen()); } psIdStr = psIdStr.substring(dotdot + 2); } - ps = toPsId(id, psIdStr); + ps = toPsId(id.getChangeId(), psIdStr); if (!rest.isEmpty()) { DisplaySide side = DisplaySide.B; @@ -440,12 +448,18 @@ public class Dispatcher { rest = rest.substring(0, at); } Patch.Key p = new Patch.Key(ps, KeyUtil.decode(rest)); - patch(token, base, p, side, line, panel); + patch(token, id.getProject(), base, p, side, line, panel); } else { if (panel == null) { Gerrit.display( token, - new ChangeScreen(id, base, String.valueOf(ps.get()), false, FileTable.Mode.REVIEW)); + new ChangeScreen( + id.getProject(), + id.getChangeId(), + base, + String.valueOf(ps.get()), + false, + FileTable.Mode.REVIEW)); } else { Gerrit.display(token, new NotFoundScreen()); } @@ -466,7 +480,13 @@ public class Dispatcher { } private static void patch( - String token, DiffObject base, Patch.Key id, DisplaySide side, int line, String panelType) { + String token, + @Nullable Project.NameKey project, + DiffObject base, + Patch.Key id, + DisplaySide side, + int line, + String panelType) { String panel = panelType; if (panel == null) { int c = token.lastIndexOf(','); @@ -475,17 +495,17 @@ public class Dispatcher { if ("".equals(panel) || /* DEPRECATED URL */ "cm".equals(panel)) { if (preferUnified()) { - unified(token, base, id, side, line); + unified(token, project, base, id, side, line); } else { - codemirror(token, base, id, side, line); + codemirror(token, base, project, id, side, line); } } else if ("sidebyside".equals(panel)) { - codemirror(token, base, id, side, line); + codemirror(token, base, project, id, side, line); } else if ("unified".equals(panel)) { - unified(token, base, id, side, line); + unified(token, project, base, id, side, line); } else if ("edit".equals(panel)) { if (!Patch.isMagic(id.get()) || Patch.COMMIT_MSG.equals(id.get())) { - codemirrorForEdit(token, id, line); + codemirrorForEdit(token, project, id, line); } else { Gerrit.display(token, new NotFoundScreen()); } @@ -501,6 +521,7 @@ public class Dispatcher { private static void unified( final String token, + final Project.NameKey project, final DiffObject base, final Patch.Key id, final DisplaySide side, @@ -511,7 +532,8 @@ public class Dispatcher { public void onSuccess() { Gerrit.display( token, - new Unified(base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line)); + new Unified( + project, base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line)); } }); } @@ -519,6 +541,7 @@ public class Dispatcher { private static void codemirror( final String token, final DiffObject base, + @Nullable final Project.NameKey project, final Patch.Key id, final DisplaySide side, final int line) { @@ -528,17 +551,22 @@ public class Dispatcher { public void onSuccess() { Gerrit.display( token, - new SideBySide(base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line)); + new SideBySide( + project, base, DiffObject.patchSet(id.getParentKey()), id.get(), side, line)); } }); } - private static void codemirrorForEdit(String token, Patch.Key id, int line) { + private static void codemirrorForEdit( + final String token, + @Nullable final Project.NameKey project, + final Patch.Key id, + final int line) { GWT.runAsync( new AsyncSplit(token) { @Override public void onSuccess() { - Gerrit.display(token, new EditScreen(id, line)); + Gerrit.display(token, new EditScreen(project, id, line)); } }); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java index dc3c043cb9..406ab4ef18 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java @@ -136,7 +136,8 @@ class SearchPanel extends Composite { } else { // changes if (query.matches("^[1-9][0-9]*$")) { - Gerrit.display(PageLinks.toChange(Change.Id.parse(query))); + // Query is a change number. Project can't be supplied. + Gerrit.display(PageLinks.toChange(null, Change.Id.parse(query))); } else { Gerrit.display(PageLinks.toChangeQuery(query), QueryScreen.forQuery(query)); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java index eeacd97a70..611db856f6 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateChangeAction.java @@ -48,7 +48,7 @@ class CreateChangeAction { public void onSuccess(ChangeInfo result) { sent = true; hide(); - Gerrit.display(PageLinks.toChange(result.legacyId())); + Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId())); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java index 47842f5e75..cb2ca0f3d4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/EditConfigAction.java @@ -20,15 +20,17 @@ import com.google.gerrit.client.changes.ChangeApi; import com.google.gerrit.client.info.ChangeInfo; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RefNames; import com.google.gwt.user.client.ui.Button; public class EditConfigAction { - static void call(Button b, String project) { + + static void call(Button b, Project.NameKey project) { b.setEnabled(false); ChangeApi.createChange( - project, + project.get(), RefNames.REFS_CONFIG, null, AdminConstants.I.editConfigMessage(), @@ -37,7 +39,8 @@ public class EditConfigAction { @Override public void onSuccess(ChangeInfo result) { Gerrit.display( - Dispatcher.toEditScreen(new PatchSet.Id(result.legacyId(), 1), "project.config")); + Dispatcher.toEditScreen( + project, new PatchSet.Id(result.legacyId(), 1), "project.config")); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java index 8f83e2f710..eb44bda356 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java @@ -287,7 +287,7 @@ public class ProjectAccessScreen extends ProjectScreen { commitMessage.setText(""); error.clear(); if (changeId != null) { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(getProjectKey(), changeId)); } else { displayReadOnly(access); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java index 37ecec8bfc..0ef8893237 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java @@ -657,7 +657,7 @@ public class ProjectInfoScreen extends ProjectScreen { new ClickHandler() { @Override public void onClick(ClickEvent event) { - EditConfigAction.call(editConfig, getProjectKey().get()); + EditConfigAction.call(editConfig, getProjectKey()); } }); return editConfig; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java index 6bba95813e..c7f005174e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ChangeGlue.java @@ -39,7 +39,7 @@ public class ChangeGlue { } public static void onAction(ChangeInfo change, ActionInfo action, ActionButton button) { - RestApi api = ChangeApi.change(change.legacyId().get()).view(action.id()); + RestApi api = ChangeApi.change(change.project(), change.legacyId().get()).view(action.id()); JavaScriptObject f = get(action.id()); if (f != null) { ActionContext c = ActionContext.create(api); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java index da14412d60..0c4aacd4b3 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java @@ -29,7 +29,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; class DefaultActions { static void invoke(ChangeInfo change, ActionInfo action, RestApi api) { - invoke(action, api, callback(PageLinks.toChange(change.legacyId()))); + invoke(action, api, callback(PageLinks.toChange(change.projectNameKey(), change.legacyId()))); } static void invoke(Project.NameKey project, ActionInfo action, RestApi api) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java index 2d9a76a056..85cfde66de 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/EditGlue.java @@ -25,7 +25,7 @@ import com.google.gwt.core.client.JavaScriptObject; public class EditGlue { public static void onAction( ChangeInfo change, EditInfo edit, ActionInfo action, ActionButton button) { - RestApi api = ChangeApi.edit(change.legacyId().get()).view(action.id()); + RestApi api = ChangeApi.edit(change.project(), change.legacyId().get()).view(action.id()); JavaScriptObject f = get(action.id()); if (f != null) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java index 2d3b39360f..d1029b2971 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/RevisionGlue.java @@ -25,7 +25,9 @@ import com.google.gwt.core.client.JavaScriptObject; public class RevisionGlue { public static void onAction( ChangeInfo change, RevisionInfo revision, ActionInfo action, ActionButton button) { - RestApi api = ChangeApi.revision(change.legacyId().get(), revision.name()).view(action.id()); + RestApi api = + ChangeApi.revision(change.project(), change.legacyId().get(), revision.name()) + .view(action.id()); JavaScriptObject f = get(action.id()); if (f != null) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java index b445b75b22..fd58959c5a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AbandonAction.java @@ -20,25 +20,29 @@ import com.google.gerrit.client.info.ChangeInfo; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.user.client.ui.Button; class AbandonAction extends ActionMessageBox { + private final Project.NameKey project; private final Change.Id id; - AbandonAction(Button b, Change.Id id) { + AbandonAction(Button b, Project.NameKey project, Change.Id id) { super(b); + this.project = project; this.id = id; } @Override void send(String message) { ChangeApi.abandon( + project.get(), id.get(), message, new GerritCallback() { @Override public void onSuccess(ChangeInfo result) { - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); hide(); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java index b22b79f18f..b0b1e35319 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Actions.java @@ -22,6 +22,7 @@ import com.google.gerrit.client.info.ChangeInfo.CommitInfo; import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.uibinder.client.UiBinder; @@ -78,7 +79,7 @@ class Actions extends Composite { private Change.Id changeId; private ChangeInfo changeInfo; private String revision; - private String project; + private Project.NameKey project; private String topic; private String subject; private String message; @@ -99,7 +100,7 @@ class Actions extends Composite { RevisionInfo revInfo = info.revision(revision); CommitInfo commit = revInfo.commit(); changeId = info.legacyId(); - project = info.project(); + project = info.projectNameKey(); topic = info.topic(); subject = commit.subject(); message = commit.message(); @@ -181,7 +182,7 @@ class Actions extends Composite { @UiHandler("followUp") void onFollowUp(@SuppressWarnings("unused") ClickEvent e) { if (followUpAction == null) { - followUpAction = new FollowUpAction(followUp, project, branch, topic, key); + followUpAction = new FollowUpAction(followUp, project.get(), branch, topic, key); } followUpAction.show(); } @@ -189,7 +190,7 @@ class Actions extends Composite { @UiHandler("abandon") void onAbandon(@SuppressWarnings("unused") ClickEvent e) { if (abandonAction == null) { - abandonAction = new AbandonAction(abandon, changeId); + abandonAction = new AbandonAction(abandon, project, changeId); } abandonAction.show(); } @@ -197,24 +198,24 @@ class Actions extends Composite { @UiHandler("deleteChange") void onDeleteChange(@SuppressWarnings("unused") ClickEvent e) { if (Window.confirm(Resources.C.deleteChange())) { - ChangeActions.delete(changeId, deleteChange); + ChangeActions.delete(project, changeId, deleteChange); } } @UiHandler("markPrivate") void onMarkPrivate(@SuppressWarnings("unused") ClickEvent e) { - ChangeActions.markPrivate(changeId, markPrivate); + ChangeActions.markPrivate(project, changeId, markPrivate); } @UiHandler("unmarkPrivate") void onUnmarkPrivate(@SuppressWarnings("unused") ClickEvent e) { - ChangeActions.unmarkPrivate(changeId, unmarkPrivate); + ChangeActions.unmarkPrivate(project, changeId, unmarkPrivate); } @UiHandler("restore") void onRestore(@SuppressWarnings("unused") ClickEvent e) { if (restoreAction == null) { - restoreAction = new RestoreAction(restore, changeId); + restoreAction = new RestoreAction(restore, project, changeId); } restoreAction.show(); } @@ -237,7 +238,7 @@ class Actions extends Composite { @UiHandler("revert") void onRevert(@SuppressWarnings("unused") ClickEvent e) { - RevertAction.call(revert, changeId, revision, subject); + RevertAction.call(revert, changeId, project, revision, subject); } private static void a2b(NativeMap actions, String a, Button b) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java index 514b4adcc0..2080a0e7d0 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileAction.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.ui.PopupPanel; @@ -23,6 +24,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.globalkey.client.GlobalKey; class AddFileAction { + private final Project.NameKey project; private final Change.Id changeId; private final RevisionInfo revision; private final ChangeScreen.Style style; @@ -33,11 +35,13 @@ class AddFileAction { private PopupPanel popup; AddFileAction( + Project.NameKey project, Change.Id changeId, RevisionInfo revision, ChangeScreen.Style style, Widget addButton, FileTable files) { + this.project = project; this.changeId = changeId; this.revision = revision; this.style = style; @@ -53,7 +57,7 @@ class AddFileAction { files.unregisterKeys(); if (addBox == null) { - addBox = new AddFileBox(changeId, revision, files); + addBox = new AddFileBox(project, changeId, revision, files); } addBox.clearPath(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java index 21bb590ff1..cd862d2a30 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/AddFileBox.java @@ -20,6 +20,7 @@ import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.ui.RemoteSuggestBox; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.CloseEvent; @@ -40,6 +41,7 @@ class AddFileBox extends Composite { private static final Binder uiBinder = GWT.create(Binder.class); + private final Project.NameKey project; private final Change.Id changeId; private final RevisionInfo revision; private final FileTable fileTable; @@ -50,12 +52,13 @@ class AddFileBox extends Composite { @UiField(provided = true) RemoteSuggestBox path; - AddFileBox(Change.Id changeId, RevisionInfo revision, FileTable files) { + AddFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision, FileTable files) { + this.project = project; this.changeId = changeId; this.revision = revision; this.fileTable = files; - path = new RemoteSuggestBox(new PathSuggestOracle(changeId, revision)); + path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision)); path.addSelectionHandler( new SelectionHandler() { @Override @@ -90,7 +93,8 @@ class AddFileBox extends Composite { private void open(String path) { hide(); - Gerrit.display(Dispatcher.toEditScreen(new PatchSet.Id(changeId, revision._number()), path)); + Gerrit.display( + Dispatcher.toEditScreen(project, new PatchSet.Id(changeId, revision._number()), path)); } @UiHandler("cancel") diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java index 9050303a8b..0fd85f1e64 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Assignee.java @@ -26,6 +26,7 @@ import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.RemoteSuggestBox; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; @@ -62,6 +63,7 @@ public class Assignee extends Composite { private AssigneeSuggestOracle assigneeSuggestOracle; private Change.Id changeId; + private Project.NameKey project; private boolean canEdit; private AccountInfo currentAssignee; @@ -98,6 +100,7 @@ public class Assignee extends Composite { void set(ChangeInfo info) { this.changeId = info.legacyId(); + this.project = info.projectNameKey(); this.canEdit = info.hasActions() && info.actions().containsKey("assignee"); setAssignee(info.assignee()); editAssigneeIcon.setVisible(canEdit); @@ -143,6 +146,7 @@ public class Assignee extends Composite { private void editAssignee(String assignee) { if (assignee.trim().isEmpty()) { ChangeApi.deleteAssignee( + project.get(), changeId.get(), new GerritCallback() { @Override @@ -166,6 +170,7 @@ public class Assignee extends Composite { }); } else { ChangeApi.setAssignee( + project.get(), changeId.get(), assignee, new GerritCallback() { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java index d6f67a6c89..cf9d18599d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeActions.java @@ -19,38 +19,42 @@ import com.google.gerrit.client.changes.ChangeApi; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; public class ChangeActions { - static void publish(Change.Id id, String revision, Button... draftButtons) { - ChangeApi.publish(id.get(), revision, cs(id, draftButtons)); + static void publish( + Project.NameKey project, Change.Id id, String revision, Button... draftButtons) { + ChangeApi.publish(project.get(), id.get(), revision, cs(project, id, draftButtons)); } - static void delete(Change.Id id, String revision, Button... draftButtons) { - ChangeApi.deleteRevision(id.get(), revision, cs(id, draftButtons)); + static void delete( + Project.NameKey project, Change.Id id, String revision, Button... draftButtons) { + ChangeApi.deleteRevision(project.get(), id.get(), revision, cs(project, id, draftButtons)); } - static void delete(Change.Id id, Button... draftButtons) { - ChangeApi.deleteChange(id.get(), mine(draftButtons)); + static void delete(Project.NameKey project, Change.Id id, Button... draftButtons) { + ChangeApi.deleteChange(project.get(), id.get(), mine(draftButtons)); } - static void markPrivate(Change.Id id, Button... draftButtons) { - ChangeApi.markPrivate(id.get(), cs(id, draftButtons)); + static void markPrivate(Project.NameKey project, Change.Id id, Button... draftButtons) { + ChangeApi.markPrivate(project.get(), id.get(), cs(project, id, draftButtons)); } - static void unmarkPrivate(Change.Id id, Button... draftButtons) { - ChangeApi.unmarkPrivate(id.get(), cs(id, draftButtons)); + static void unmarkPrivate(Project.NameKey project, Change.Id id, Button... draftButtons) { + ChangeApi.unmarkPrivate(project.get(), id.get(), cs(project, id, draftButtons)); } - public static GerritCallback cs(final Change.Id id, Button... draftButtons) { + public static GerritCallback cs( + Project.NameKey project, final Change.Id id, Button... draftButtons) { setEnabled(false, draftButtons); return new GerritCallback() { @Override public void onSuccess(JavaScriptObject result) { - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); } @Override @@ -58,7 +62,7 @@ public class ChangeActions { setEnabled(true, draftButtons); if (SubmitFailureDialog.isConflict(err)) { new SubmitFailureDialog(err.getMessage()).center(); - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); } else { super.onFailure(err); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java index f3a07570c3..b7cd7288d1 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ChangeScreen.java @@ -57,12 +57,14 @@ import com.google.gerrit.client.ui.Hyperlink; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.Screen; import com.google.gerrit.client.ui.UserActivityMonitor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.extensions.client.SubmitType; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change.Status; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; @@ -159,6 +161,7 @@ public class ChangeScreen extends Screen { } private final Change.Id changeId; + @Nullable private Project.NameKey project; private DiffObject base; private String revision; private ChangeInfo changeInfo; @@ -254,20 +257,27 @@ public class ChangeScreen extends Screen { private RenameFileAction renameFileAction; public ChangeScreen( + @Nullable Project.NameKey project, Change.Id changeId, DiffObject base, String revision, boolean openReplyBox, FileTable.Mode mode) { + this.project = project; this.changeId = changeId; this.base = base; this.revision = normalize(revision); this.openReplyBox = openReplyBox; this.fileTableMode = mode; - this.lc = new LocalComments(changeId); + this.lc = new LocalComments(project, changeId); add(uiBinder.createAndBindUi(this)); } + @SuppressWarnings("null") + public Project.NameKey getProject() { + return project; + } + PatchSet.Id getPatchSetId() { return new PatchSet.Id(changeInfo.legacyId(), changeInfo.revisions().get(revision)._number()); } @@ -291,6 +301,7 @@ public class ChangeScreen extends Screen { public void onFailure(Throwable caught) {} })); ChangeApi.editWithFiles( + Project.NameKey.asStringOrNull(project), changeId.get(), group.add( new AsyncCallback() { @@ -310,6 +321,15 @@ public class ChangeScreen extends Screen { @Override public void onSuccess(ChangeInfo info) { info.init(); + if (project == null) { + // Update Project when the first API call succeeded if it wasn't already present. + // This is the case when the user used a URL that doesn't include the project. + // Setting it here will rewrite the URL token to include the project (visible to + // the user) and all future API calls made from the change screen will use + // project/+/changeId to identify the change. + project = info.projectNameKey(); + } + initCurrentRevision(info); final RevisionInfo rev = info.revision(revision); CallbackGroup group = new CallbackGroup(); @@ -434,7 +454,7 @@ public class ChangeScreen extends Screen { } void loadChangeInfo(boolean fg, AsyncCallback cb) { - RestApi call = ChangeApi.detail(changeId.get()); + RestApi call = ChangeApi.detail(Project.NameKey.asStringOrNull(project), changeId.get()); EnumSet opts = EnumSet.of(ListChangesOption.ALL_REVISIONS, ListChangesOption.CHANGE_ACTIONS); if (enableSignedPush()) { @@ -448,7 +468,7 @@ public class ChangeScreen extends Screen { } void loadRevisionInfo() { - RestApi call = ChangeApi.actions(changeId.get(), revision); + RestApi call = ChangeApi.actions(getProject().get(), changeId.get(), revision); call.background(); call.get( new GerritCallback>() { @@ -517,6 +537,7 @@ public class ChangeScreen extends Screen { if (0 <= i + offset && i + offset < revisions.length()) { Gerrit.display( PageLinks.toChange( + project, new PatchSet.Id(changeInfo.legacyId(), revisions.get(i + offset)._number()))); return; } @@ -527,7 +548,9 @@ public class ChangeScreen extends Screen { private void initIncludedInAction(ChangeInfo info) { if (info.status() == Status.MERGED) { - includedInAction = new IncludedInAction(info.legacyId(), style, headerLine, includedIn); + includedInAction = + new IncludedInAction( + info.projectNameKey(), info.legacyId(), style, headerLine, includedIn); includedIn.setVisible(true); } } @@ -567,7 +590,8 @@ public class ChangeScreen extends Screen { patchSetsText.setInnerText(Resources.M.patchSets(currentlyViewedPatchSet, currentPatchSet)); updatePatchSetsTextStyle(isPatchSetCurrent); patchSetsAction = - new PatchSetsAction(info.legacyId(), revision, edit, style, headerLine, patchSets); + new PatchSetsAction( + info.projectNameKey(), info.legacyId(), revision, edit, style, headerLine, patchSets); RevisionInfo revInfo = info.revision(revision); if (revInfo.draft()) { @@ -623,11 +647,14 @@ public class ChangeScreen extends Screen { renameFile.setVisible(!editMode.isVisible()); reviewMode.setVisible(!editMode.isVisible()); addFileAction = - new AddFileAction(changeId, info.revision(revision), style, addFile, files); + new AddFileAction( + info.projectNameKey(), changeId, info.revision(revision), style, addFile, files); deleteFileAction = - new DeleteFileAction(changeId, info.revision(revision), style, addFile); + new DeleteFileAction( + info.projectNameKey(), changeId, info.revision(revision), style, addFile); renameFileAction = - new RenameFileAction(changeId, info.revision(revision), style, addFile); + new RenameFileAction( + info.projectNameKey(), changeId, info.revision(revision), style, addFile); } else { editMode.setVisible(false); addFile.setVisible(false); @@ -661,30 +688,30 @@ public class ChangeScreen extends Screen { @UiHandler("publishEdit") void onPublishEdit(@SuppressWarnings("unused") ClickEvent e) { - EditActions.publishEdit(changeId, publishEdit, rebaseEdit, deleteEdit); + EditActions.publishEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit); } @UiHandler("rebaseEdit") void onRebaseEdit(@SuppressWarnings("unused") ClickEvent e) { - EditActions.rebaseEdit(changeId, publishEdit, rebaseEdit, deleteEdit); + EditActions.rebaseEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit); } @UiHandler("deleteEdit") void onDeleteEdit(@SuppressWarnings("unused") ClickEvent e) { if (Window.confirm(Resources.C.deleteChangeEdit())) { - EditActions.deleteEdit(changeId, publishEdit, rebaseEdit, deleteEdit); + EditActions.deleteEdit(getProject(), changeId, publishEdit, rebaseEdit, deleteEdit); } } @UiHandler("publish") void onPublish(@SuppressWarnings("unused") ClickEvent e) { - ChangeActions.publish(changeId, revision, publish, deleteRevision); + ChangeActions.publish(getProject(), changeId, revision, publish, deleteRevision); } @UiHandler("deleteRevision") void onDeleteRevision(@SuppressWarnings("unused") ClickEvent e) { if (Window.confirm(Resources.C.deleteDraftRevision())) { - ChangeActions.delete(changeId, revision, publish, deleteRevision); + ChangeActions.delete(getProject(), changeId, revision, publish, deleteRevision); } } @@ -704,7 +731,7 @@ public class ChangeScreen extends Screen { new KeyCommand(0, 'R', Util.C.keyReloadChange()) { @Override public void onKeyPress(KeyPressEvent event) { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(project, changeId)); } }); keysNavigation.add( @@ -814,21 +841,20 @@ public class ChangeScreen extends Screen { } private void scrollToPath(String token) { - int s = token.indexOf('/'); + ProjectChangeId cId; try { - String c = token.substring(0, s); - int editIndex = c.indexOf(",edit"); - if (editIndex > 0) { - c = c.substring(0, editIndex); - } - if (s < 0 || !changeId.equals(Change.Id.parse(c))) { - return; // Unrelated URL, do not scroll. - } + cId = ProjectChangeId.create(token); } catch (IllegalArgumentException e) { + // Scrolling is best-effort. return; } + if (!changeId.equals(cId.getChangeId())) { + return; // Unrelated URL, do not scroll. + } - s = token.indexOf('/', s + 1); + // Extract the start of a file path. The patch set is always contained in the URL and separated + // by from the changeId by a forward slash. Example: /c/project/+/123/1/folder/file.txt + int s = token.indexOf('/', cId.identifierLength() + 1); if (s < 0) { return; // URL does not name a file. } @@ -873,7 +899,7 @@ public class ChangeScreen extends Screen { @UiHandler("permalink") void onReload(ClickEvent e) { e.preventDefault(); - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(project, changeId)); } private void onReply() { @@ -1056,7 +1082,10 @@ public class ChangeScreen extends Screen { } private void updateToken(ChangeInfo info, DiffObject base, RevisionInfo rev) { - StringBuilder token = new StringBuilder("/c/").append(info._number()).append("/"); + StringBuilder token = + new StringBuilder("/c/") + .append(PageLinks.toChangeId(info.projectNameKey(), info.legacyId())) + .append("/"); if (base.asString() != null) { token.append(base.asString()).append(".."); } @@ -1090,7 +1119,7 @@ public class ChangeScreen extends Screen { loadFileList(base, baseRev, rev, myLastReply, group, comments, drafts); if (Gerrit.isSignedIn() && fileTableMode == FileTable.Mode.REVIEW) { - ChangeApi.revision(changeId.get(), rev.name()) + ChangeApi.revision(getProject().get(), changeId.get(), rev.name()) .view("files") .addParameterTrue("reviewed") .get( @@ -1116,6 +1145,7 @@ public class ChangeScreen extends Screen { final List>> comments, final List>> drafts) { DiffApi.list( + getProject().get(), changeId.get(), rev.name(), baseRev, @@ -1126,6 +1156,7 @@ public class ChangeScreen extends Screen { files.set( base, new PatchSet.Id(changeId, rev._number()), + getProject(), style, reply, fileTableMode, @@ -1149,7 +1180,7 @@ public class ChangeScreen extends Screen { final List>> r = new ArrayList<>(1); // TODO(dborowitz): Could eliminate this call by adding an option to include // inline comments in the change detail. - ChangeApi.comments(changeId.get()) + ChangeApi.comments(getProject().get(), changeId.get()) .get( group.add( new AsyncCallback>>() { @@ -1188,7 +1219,7 @@ public class ChangeScreen extends Screen { private List>> loadDrafts(RevisionInfo rev, CallbackGroup group) { final List>> r = new ArrayList<>(1); if (Gerrit.isSignedIn()) { - ChangeApi.revision(changeId.get(), rev.name()) + ChangeApi.revision(getProject().get(), changeId.get(), rev.name()) .view("drafts") .get( group.add( @@ -1213,6 +1244,7 @@ public class ChangeScreen extends Screen { } ChangeApi.commitWithLinks( + getProject().get(), changeId.get(), rev.name(), group.add( @@ -1578,7 +1610,7 @@ public class ChangeScreen extends Screen { new UpdateAvailableBar() { @Override void onShow() { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(project, changeId)); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java index 5fb0e7b48d..be011d29a2 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/CherryPickAction.java @@ -32,11 +32,11 @@ class CherryPickAction { final Button b, final ChangeInfo info, final String revision, - String project, + final Project.NameKey project, final String commitMessage) { // TODO Replace CherryPickDialog with a nicer looking display. b.setEnabled(false); - new CherryPickDialog(new Project.NameKey(project)) { + new CherryPickDialog(project) { { sendButton.setText(Util.C.buttonCherryPickChangeSend()); if (info.status() == Change.Status.MERGED) { @@ -49,6 +49,7 @@ class CherryPickAction { @Override public void onSend() { ChangeApi.cherrypick( + info.project(), info.legacyId().get(), revision, getDestinationBranch(), @@ -58,7 +59,7 @@ class CherryPickAction { public void onSuccess(ChangeInfo result) { sent = true; hide(); - Gerrit.display(PageLinks.toChange(result.legacyId())); + Gerrit.display(PageLinks.toChange(project, result.legacyId())); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java index 4dcdc6e664..9369c18e4f 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileAction.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.ui.PopupPanel; @@ -23,6 +24,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.globalkey.client.GlobalKey; class DeleteFileAction { + private final Project.NameKey project; private final Change.Id changeId; private final RevisionInfo revision; private final ChangeScreen.Style style; @@ -32,7 +34,12 @@ class DeleteFileAction { private PopupPanel popup; DeleteFileAction( - Change.Id changeId, RevisionInfo revision, ChangeScreen.Style style, Widget deleteButton) { + Project.NameKey project, + Change.Id changeId, + RevisionInfo revision, + ChangeScreen.Style style, + Widget deleteButton) { + this.project = project; this.changeId = changeId; this.revision = revision; this.style = style; @@ -46,7 +53,7 @@ class DeleteFileAction { } if (deleteBox == null) { - deleteBox = new DeleteFileBox(changeId, revision); + deleteBox = new DeleteFileBox(project, changeId, revision); } deleteBox.clearPath(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java index 3edfca2a23..1885293d4e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DeleteFileBox.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.ui.RemoteSuggestBox; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.CloseEvent; @@ -42,6 +43,7 @@ class DeleteFileBox extends Composite { private static final Binder uiBinder = GWT.create(Binder.class); + private final Project.NameKey project; private final Change.Id changeId; @UiField Button delete; @@ -50,10 +52,11 @@ class DeleteFileBox extends Composite { @UiField(provided = true) RemoteSuggestBox path; - DeleteFileBox(Change.Id changeId, RevisionInfo revision) { + DeleteFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision) { + this.project = project; this.changeId = changeId; - path = new RemoteSuggestBox(new PathSuggestOracle(changeId, revision)); + path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision)); path.addSelectionHandler( new SelectionHandler() { @Override @@ -88,12 +91,13 @@ class DeleteFileBox extends Composite { private void delete(String path) { hide(); ChangeEditApi.delete( + project.get(), changeId.get(), path, new AsyncCallback() { @Override public void onSuccess(VoidResult result) { - Gerrit.display(PageLinks.toChangeInEditMode(changeId)); + Gerrit.display(PageLinks.toChangeInEditMode(project, changeId)); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java index 6c2964d97e..547f3d563e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/DownloadBox.java @@ -78,7 +78,7 @@ class DownloadBox extends VerticalPanel { protected void onLoad() { if (fetch == null) { if (psId.get() == 0) { - ChangeApi.editWithCommands(change.legacyId().get()) + ChangeApi.editWithCommands(change.project(), change.legacyId().get()) .get( new AsyncCallback() { @Override @@ -91,7 +91,7 @@ class DownloadBox extends VerticalPanel { public void onFailure(Throwable caught) {} }); } else { - RestApi call = ChangeApi.detail(change.legacyId().get()); + RestApi call = ChangeApi.detail(change.project(), change.legacyId().get()); ChangeList.addOptions( call, EnumSet.of( diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java index 907691ee0b..f075c166d6 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/EditActions.java @@ -19,29 +19,31 @@ import com.google.gerrit.client.changes.ChangeApi; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.user.client.ui.Button; public class EditActions { - static void deleteEdit(Change.Id id, Button... editButtons) { - ChangeApi.deleteEdit(id.get(), cs(id, editButtons)); + static void deleteEdit(Project.NameKey project, Change.Id id, Button... editButtons) { + ChangeApi.deleteEdit(project.get(), id.get(), cs(project, id, editButtons)); } - static void publishEdit(Change.Id id, Button... editButtons) { - ChangeApi.publishEdit(id.get(), cs(id, editButtons)); + static void publishEdit(Project.NameKey project, Change.Id id, Button... editButtons) { + ChangeApi.publishEdit(project.get(), id.get(), cs(project, id, editButtons)); } - static void rebaseEdit(Change.Id id, Button... editButtons) { - ChangeApi.rebaseEdit(id.get(), cs(id, editButtons)); + static void rebaseEdit(Project.NameKey project, Change.Id id, Button... editButtons) { + ChangeApi.rebaseEdit(project.get(), id.get(), cs(project, id, editButtons)); } - public static GerritCallback cs(final Change.Id id, Button... editButtons) { + public static GerritCallback cs( + Project.NameKey project, final Change.Id id, Button... editButtons) { setEnabled(false, editButtons); return new GerritCallback() { @Override public void onSuccess(JavaScriptObject result) { - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); } @Override @@ -49,7 +51,7 @@ public class EditActions { setEnabled(true, editButtons); if (SubmitFailureDialog.isConflict(err)) { new SubmitFailureDialog(err.getMessage()).center(); - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); } else { super.onFailure(err); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java index 0e30a8c216..083c824911 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileComments.java @@ -19,6 +19,7 @@ import com.google.gerrit.client.changes.CommentInfo; import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -36,17 +37,21 @@ class FileComments extends Composite { @UiField FlowPanel comments; FileComments( - CommentLinkProcessor clp, PatchSet.Id defaultPs, String title, List list) { + CommentLinkProcessor clp, + Project.NameKey project, + PatchSet.Id defaultPs, + String title, + List list) { initWidget(uiBinder.createAndBindUi(this)); - path.setTargetHistoryToken(url(defaultPs, list.get(0))); + path.setTargetHistoryToken(url(project, defaultPs, list.get(0))); path.setText(title); for (CommentInfo c : list) { - comments.add(new LineComment(clp, defaultPs, c)); + comments.add(new LineComment(clp, project, defaultPs, c)); } } - private static String url(PatchSet.Id ps, CommentInfo info) { - return Dispatcher.toPatch(null, ps, info.path()); + private static String url(Project.NameKey project, PatchSet.Id ps, CommentInfo info) { + return Dispatcher.toPatch(project, null, ps, info.path()); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java index 65e3dc0aab..30554b694b 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FileTable.java @@ -41,6 +41,7 @@ import com.google.gerrit.extensions.client.Side; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.Patch.ChangeType; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; @@ -199,6 +200,7 @@ public class FileTable extends FlowPanel { private DiffObject base; private PatchSet.Id curr; + private Project.NameKey project; private MyTable table; private boolean register; private JsArrayString reviewed; @@ -217,12 +219,14 @@ public class FileTable extends FlowPanel { public void set( DiffObject base, PatchSet.Id curr, + Project.NameKey project, ChangeScreen.Style style, Widget replyButton, Mode mode, boolean editExists) { this.base = base; this.curr = curr; + this.project = project; this.style = style; this.replyButton = replyButton; this.mode = mode; @@ -318,10 +322,10 @@ public class FileTable extends FlowPanel { private String url(FileInfo info) { return info.binary() - ? Dispatcher.toUnified(base, curr, info.path()) + ? Dispatcher.toUnified(project, base, curr, info.path()) : mode == Mode.REVIEW - ? Dispatcher.toPatch(base, curr, info.path()) - : Dispatcher.toEditScreen(curr, info.path()); + ? Dispatcher.toPatch(project, base, curr, info.path()) + : Dispatcher.toEditScreen(project, curr, info.path()); } private final class MyTable extends NavigationTable { @@ -364,12 +368,13 @@ public class FileTable extends FlowPanel { void onDelete(int idx) { String path = list.get(idx).path(); ChangeEditApi.delete( + project.get(), curr.getParentKey().get(), path, new AsyncCallback() { @Override public void onSuccess(VoidResult result) { - Gerrit.display(PageLinks.toChangeInEditMode(curr.getParentKey())); + Gerrit.display(PageLinks.toChangeInEditMode(project, curr.getParentKey())); } @Override @@ -380,12 +385,13 @@ public class FileTable extends FlowPanel { void onRestore(int idx) { String path = list.get(idx).path(); ChangeEditApi.restore( + project.get(), curr.getParentKey().get(), path, new AsyncCallback() { @Override public void onSuccess(VoidResult result) { - Gerrit.display(PageLinks.toChangeInEditMode(curr.getParentKey())); + Gerrit.display(PageLinks.toChangeInEditMode(project, curr.getParentKey())); } @Override @@ -398,7 +404,8 @@ public class FileTable extends FlowPanel { } private void setReviewed(FileInfo info, boolean r) { - RestApi api = ChangeApi.revision(curr).view("files").id(info.path()).view("reviewed"); + RestApi api = + ChangeApi.revision(project.get(), curr).view("files").id(info.path()).view("reviewed"); if (r) { api.put(CallbackGroup.emptyCallback()); } else { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java index 5c7472c225..a4c90b8fdc 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/FollowUpAction.java @@ -46,7 +46,7 @@ class FollowUpAction extends ActionMessageBox { new GerritCallback() { @Override public void onSuccess(ChangeInfo result) { - Gerrit.display(PageLinks.toChange(result.legacyId())); + Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId())); hide(); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java index c0c8037c17..1044828e5e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Hashtags.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayString; @@ -73,14 +74,14 @@ public class Hashtags extends Composite { if (hashtags != null) { final ChangeScreen screen = ChangeScreen.get(event); final PatchSet.Id psId = screen.getPatchSetId(); - ChangeApi.hashtags(psId.getParentKey().get()) + ChangeApi.hashtags(screen.getProject().get(), psId.getParentKey().get()) .post( PostInput.create(null, hashtags), new GerritCallback() { @Override public void onSuccess(JavaScriptObject result) { if (screen.isCurrentView()) { - Gerrit.display(PageLinks.toChange(psId)); + Gerrit.display(PageLinks.toChange(screen.getProject(), psId)); } } }); @@ -107,6 +108,7 @@ public class Hashtags extends Composite { private ChangeScreen.Style style; private Change.Id changeId; + private Project.NameKey project; public Hashtags() { @@ -141,6 +143,7 @@ public class Hashtags extends Composite { void set(ChangeInfo info, String revision) { psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number()); + project = info.projectNameKey(); canEdit = info.hasActions() && info.actions().containsKey("hashtags"); this.changeId = info.legacyId(); @@ -219,13 +222,14 @@ public class Hashtags extends Composite { } private void addHashtag(String hashtags) { - ChangeApi.hashtags(changeId.get()) + ChangeApi.hashtags(project.get(), changeId.get()) .post( PostInput.create(hashtags, null), new GerritCallback() { @Override public void onSuccess(JsArrayString result) { - Gerrit.display(PageLinks.toChange(psId.getParentKey(), String.valueOf(psId.get()))); + Gerrit.display( + PageLinks.toChange(project, psId.getParentKey(), String.valueOf(psId.get()))); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java index e221f5479d..55e021f68d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/History.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArray; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; @@ -35,6 +36,7 @@ class History extends FlowPanel { private CommentLinkProcessor clp; private ReplyAction replyAction; private Change.Id changeId; + private Project.NameKey project; private final Map> byAuthor = new HashMap<>(); @@ -42,6 +44,7 @@ class History extends FlowPanel { this.clp = clp; this.replyAction = ra; this.changeId = id; + this.project = info.projectNameKey(); JsArray messages = info.messages(); if (messages != null) { @@ -80,6 +83,10 @@ class History extends FlowPanel { return changeId; } + Project.NameKey getProject() { + return project; + } + void replyTo(MessageInfo info) { replyAction.onReply(info); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java index 00b6c3ca4e..5557f909b0 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInAction.java @@ -15,6 +15,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; @@ -22,9 +23,13 @@ class IncludedInAction extends RightSidePopdownAction { private final IncludedInBox includedInBox; IncludedInAction( - Change.Id changeId, ChangeScreen.Style style, UIObject relativeTo, Widget includedInButton) { + Project.NameKey project, + Change.Id changeId, + ChangeScreen.Style style, + UIObject relativeTo, + Widget includedInButton) { super(style, relativeTo, includedInButton); - this.includedInBox = new IncludedInBox(changeId); + this.includedInBox = new IncludedInBox(project, changeId); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java index 0f121cc9ba..9751f54717 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/IncludedInBox.java @@ -17,6 +17,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.changes.ChangeApi; import com.google.gerrit.client.info.ChangeInfo.IncludedInInfo; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.dom.client.Document; @@ -42,6 +43,7 @@ class IncludedInBox extends Composite { String includedInElement(); } + private final Project.NameKey project; private final Change.Id changeId; private boolean loaded; @@ -50,7 +52,8 @@ class IncludedInBox extends Composite { @UiField Element branches; @UiField Element tags; - IncludedInBox(Change.Id changeId) { + IncludedInBox(Project.NameKey project, Change.Id changeId) { + this.project = project; this.changeId = changeId; initWidget(uiBinder.createAndBindUi(this)); } @@ -59,6 +62,7 @@ class IncludedInBox extends Composite { protected void onLoad() { if (!loaded) { ChangeApi.includedIn( + project.get(), changeId.get(), new AsyncCallback() { @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java index fc34aeb178..1f4820f22a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Labels.java @@ -72,13 +72,13 @@ class Labels extends Grid { if (user != null) { final ChangeScreen screen = ChangeScreen.get(event); final Change.Id changeId = screen.getPatchSetId().getParentKey(); - ChangeApi.reviewer(changeId.get(), user) + ChangeApi.reviewer(screen.getProject().get(), changeId.get(), user) .delete( new GerritCallback() { @Override public void onSuccess(JavaScriptObject result) { if (screen.isCurrentView()) { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(screen.getProject(), changeId)); } } }); @@ -91,13 +91,13 @@ class Labels extends Grid { if (user != null && vote != null) { final ChangeScreen screen = ChangeScreen.get(event); final Change.Id changeId = screen.getPatchSetId().getParentKey(); - ChangeApi.vote(changeId.get(), user, vote) + ChangeApi.vote(screen.getProject().get(), changeId.get(), user, vote) .delete( new GerritCallback() { @Override public void onSuccess(JavaScriptObject result) { if (screen.isCurrentView()) { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(screen.getProject(), changeId)); } } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java index a1ad7c24e5..5a0cc59dda 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LineComment.java @@ -22,6 +22,7 @@ import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.extensions.client.Side; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.uibinder.client.UiBinder; @@ -43,7 +44,8 @@ class LineComment extends Composite { @UiField InlineHyperlink line; @UiField Element message; - LineComment(CommentLinkProcessor clp, PatchSet.Id defaultPs, CommentInfo info) { + LineComment( + CommentLinkProcessor clp, Project.NameKey project, PatchSet.Id defaultPs, CommentInfo info) { initWidget(uiBinder.createAndBindUi(this)); PatchSet.Id ps; @@ -70,7 +72,7 @@ class LineComment extends Composite { fileLoc.removeFromParent(); fileLoc = null; - line.setTargetHistoryToken(url(ps, info)); + line.setTargetHistoryToken(url(project, ps, info)); line.setText(Integer.toString(info.line())); } else { @@ -86,8 +88,9 @@ class LineComment extends Composite { } } - private static String url(PatchSet.Id ps, CommentInfo info) { + private static String url(Project.NameKey project, PatchSet.Id ps, CommentInfo info) { return Dispatcher.toPatch( + project, null, ps, info.path(), diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java index 1d6ad3d229..392dc011b5 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/LocalComments.java @@ -19,24 +19,30 @@ import com.google.gerrit.client.changes.CommentInfo; import com.google.gerrit.client.diff.CommentRange; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.common.Nullable; +import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.Side; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.Cookies; import java.util.ArrayList; import java.util.Collection; public class LocalComments { + @Nullable private final Project.NameKey project; private final Change.Id changeId; private final PatchSet.Id psId; private final StorageBackend storage; private static class InlineComment { + @Nullable final Project.NameKey project; final PatchSet.Id psId; final CommentInfo commentInfo; - InlineComment(PatchSet.Id psId, CommentInfo commentInfo) { + InlineComment(@Nullable Project.NameKey project, PatchSet.Id psId, CommentInfo commentInfo) { + this.project = project; this.psId = psId; this.commentInfo = commentInfo; } @@ -87,13 +93,15 @@ public class LocalComments { } } - public LocalComments(Change.Id changeId) { + public LocalComments(@Nullable Project.NameKey project, Change.Id changeId) { + this.project = project; this.changeId = changeId; this.psId = null; this.storage = new StorageBackend(); } - public LocalComments(PatchSet.Id psId) { + public LocalComments(@Nullable Project.NameKey project, PatchSet.Id psId) { + this.project = project; this.changeId = psId.getParentKey(); this.psId = psId; this.storage = new StorageBackend(); @@ -120,7 +128,7 @@ public class LocalComments { } private String getReplyCommentName() { - return "savedReplyComment-" + changeId.toString(); + return "savedReplyComment-" + PageLinks.toChangeId(project, changeId); } public static void saveInlineComments() { @@ -130,6 +138,7 @@ public class LocalComments { InlineComment input = getInlineComment(cookie); if (input.commentInfo.id() == null) { CommentApi.createDraft( + Project.NameKey.asStringOrNull(input.project), input.psId, input.commentInfo, new GerritCallback() { @@ -140,6 +149,7 @@ public class LocalComments { }); } else { CommentApi.updateDraft( + Project.NameKey.asStringOrNull(input.project), input.psId, input.commentInfo.id(), input.commentInfo, @@ -201,8 +211,8 @@ public class LocalComments { if (key.startsWith("patchReply-") || key.startsWith("patchCommentEdit-")) { offset = 2; } - Change.Id changeId = new Change.Id(Integer.parseInt(elements[offset + 0])); - PatchSet.Id psId = new PatchSet.Id(changeId, Integer.parseInt(elements[offset + 1])); + ProjectChangeId id = ProjectChangeId.create(elements[offset + 0]); + PatchSet.Id psId = new PatchSet.Id(id.getChangeId(), Integer.parseInt(elements[offset + 1])); path = atob(elements[offset + 2]); side = (Side.PARENT.toString().equals(elements[offset + 3])) ? Side.PARENT : Side.REVISION; range = null; @@ -227,7 +237,7 @@ public class LocalComments { } else if (key.startsWith("patchCommentEdit-")) { info.id(elements[1]); } - InlineComment inlineComment = new InlineComment(psId, info); + InlineComment inlineComment = new InlineComment(id.getProject(), psId, info); return inlineComment; } @@ -241,8 +251,9 @@ public class LocalComments { } else if (comment.inReplyTo() != null) { result = "patchReply-" + comment.inReplyTo() + "-"; } - result += - changeId + "-" + psId.getId() + "-" + btoa(comment.path()) + "-" + comment.side() + "-"; + + result += PageLinks.toChangeId(project, changeId); + result += "-" + psId.getId() + "-" + btoa(comment.path()) + "-" + comment.side() + "-"; if (comment.hasRange()) { result += "R" diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java index a8fe2f0590..cadaf97955 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Message.java @@ -173,14 +173,14 @@ class Message extends Composite { TreeMap> m = byPath(list); List l = m.remove(Patch.COMMIT_MSG); if (l != null) { - comments.add(new FileComments(clp, ps, Util.C.commitMessage(), l)); + comments.add(new FileComments(clp, history.getProject(), ps, Util.C.commitMessage(), l)); } l = m.remove(Patch.MERGE_LIST); if (l != null) { - comments.add(new FileComments(clp, ps, Util.C.mergeList(), l)); + comments.add(new FileComments(clp, history.getProject(), ps, Util.C.mergeList(), l)); } for (Map.Entry> e : m.entrySet()) { - comments.add(new FileComments(clp, ps, e.getKey(), e.getValue())); + comments.add(new FileComments(clp, history.getProject(), ps, e.getKey(), e.getValue())); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java index 5e2b8e367e..faf2516294 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsAction.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.info.ChangeInfo.EditInfo; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; @@ -23,6 +24,7 @@ class PatchSetsAction extends RightSidePopdownAction { private final PatchSetsBox revisionBox; PatchSetsAction( + Project.NameKey project, Change.Id changeId, String revision, EditInfo edit, @@ -30,7 +32,7 @@ class PatchSetsAction extends RightSidePopdownAction { UIObject relativeTo, Widget downloadButton) { super(style, relativeTo, downloadButton); - this.revisionBox = new PatchSetsBox(changeId, revision, edit); + this.revisionBox = new PatchSetsBox(project, changeId, revision, edit); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java index 189df08127..e75fe7a795 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PatchSetsBox.java @@ -29,6 +29,7 @@ import com.google.gerrit.client.ui.FancyFlexTableImpl; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Element; @@ -103,6 +104,7 @@ class PatchSetsBox extends Composite { } private final Change.Id changeId; + private final Project.NameKey project; private final String revision; private final EditInfo edit; private boolean loaded; @@ -111,7 +113,8 @@ class PatchSetsBox extends Composite { @UiField FlexTable table; @UiField Style style; - PatchSetsBox(Change.Id changeId, String revision, EditInfo edit) { + PatchSetsBox(Project.NameKey project, Change.Id changeId, String revision, EditInfo edit) { + this.project = project; this.changeId = changeId; this.revision = revision; this.edit = edit; @@ -121,7 +124,7 @@ class PatchSetsBox extends Composite { @Override protected void onLoad() { if (!loaded) { - RestApi call = ChangeApi.detail(changeId.get()); + RestApi call = ChangeApi.detail(project.get(), changeId.get()); ChangeList.addOptions( call, EnumSet.of(ListChangesOption.ALL_COMMITS, ListChangesOption.ALL_REVISIONS)); call.get( @@ -219,7 +222,7 @@ class PatchSetsBox extends Composite { } private String url(RevisionInfo r) { - return PageLinks.toChange(changeId, r.id()); + return PageLinks.toChange(project, changeId, r.id()); } private void closeParent() { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java index cfed9dba6f..7668f0f982 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/PathSuggestOracle.java @@ -19,6 +19,7 @@ import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle; @@ -28,17 +29,19 @@ import java.util.List; class PathSuggestOracle extends HighlightSuggestOracle { + private final Project.NameKey project; private final Change.Id changeId; private final RevisionInfo revision; - PathSuggestOracle(Change.Id changeId, RevisionInfo revision) { + PathSuggestOracle(Project.NameKey project, Change.Id changeId, RevisionInfo revision) { + this.project = project; this.changeId = changeId; this.revision = revision; } @Override protected void onRequestSuggestions(Request req, Callback cb) { - RestApi api = ChangeApi.revision(changeId.get(), revision.name()).view("files"); + RestApi api = ChangeApi.revision(project.get(), changeId.get(), revision.name()).view("files"); if (req.getQuery() != null) { api.addParameter("q", req.getQuery() == null ? "" : req.getQuery()); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java new file mode 100644 index 0000000000..7ba02b41ad --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ProjectChangeId.java @@ -0,0 +1,115 @@ +// 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.client.change; + +import com.google.common.annotations.VisibleForTesting; +import com.google.gerrit.common.Nullable; +import com.google.gerrit.common.PageLinks; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; +import java.util.Objects; + +/** Provides logic for parsing a numeric change id and project from a URL. */ +public class ProjectChangeId { + + /** Parses a {@link ProjectChangeId} from it's string representation. */ + public static ProjectChangeId create(String token) { + String mutableToken = token; + // Try parsing /c/project/+/numericChangeId where token is project/+/numericChangeId + int delimiter = mutableToken.indexOf(PageLinks.PROJECT_CHANGE_DELIMITER); + Project.NameKey project = null; + if (delimiter > 0) { + project = new Project.NameKey(token.substring(0, delimiter)); + mutableToken = + mutableToken.substring(delimiter + PageLinks.PROJECT_CHANGE_DELIMITER.length()); + } + + // Try parsing /c/numericChangeId where token is numericChangeId + int s = mutableToken.indexOf('/'); + if (s > 0) { + mutableToken = mutableToken.substring(0, s); + } + // Special case: project/+/1233,edit/ + s = mutableToken.indexOf(",edit"); + if (s > 0) { + mutableToken = mutableToken.substring(0, s); + } + Integer cId = tryParse(mutableToken); + if (cId != null) { + return new ProjectChangeId(project, new Change.Id(cId)); + } + + throw new IllegalArgumentException(token + " is not a valid change identifier"); + } + + @Nullable private final Project.NameKey project; + private final Change.Id changeId; + + @VisibleForTesting + ProjectChangeId(@Nullable Project.NameKey project, Change.Id changeId) { + this.project = project; + this.changeId = changeId; + } + + @Nullable + public Project.NameKey getProject() { + return project; + } + + public Change.Id getChangeId() { + return changeId; + } + + /** + * Calculate the length of the string representation of the change ID that was parsed from the + * token. + * + * @return the length of the {@link Change.Id} if no project was parsed from the token. The length + * of {@link Project.NameKey} + the delimiter + the length of {@link Change.Id} otherwise. + */ + public int identifierLength() { + if (project == null) { + return String.valueOf(changeId).length(); + } + return PageLinks.toChangeId(project, changeId).length(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ProjectChangeId) { + ProjectChangeId other = (ProjectChangeId) obj; + return Objects.equals(changeId, other.changeId) && Objects.equals(project, other.project); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(changeId, project); + } + + @Override + public String toString() { + return "ProjectChangeId.Result{changeId: " + changeId + ", project: " + project + "}"; + } + + private static Integer tryParse(String s) { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + return null; + } + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java index c4a74f545a..0dcba2e3c8 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/QuickApprove.java @@ -24,6 +24,7 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -33,6 +34,7 @@ import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; /** Applies a label with one mouse click. */ class QuickApprove extends Button implements ClickHandler { private Change.Id changeId; + private Project.NameKey project; private String revision; private ReviewInput input; private ReplyAction replyAction; @@ -71,6 +73,7 @@ class QuickApprove extends Button implements ClickHandler { if (qName != null) { changeId = info.legacyId(); + project = info.projectNameKey(); revision = commit; input = ReviewInput.create(); input.drafts(DraftHandling.PUBLISH_ALL_REVISIONS); @@ -93,14 +96,14 @@ class QuickApprove extends Button implements ClickHandler { if (replyAction != null && replyAction.isVisible()) { replyAction.quickApprove(input); } else { - ChangeApi.revision(changeId.get(), revision) + ChangeApi.revision(project.get(), changeId.get(), revision) .view("review") .post( input, new GerritCallback() { @Override public void onSuccess(ReviewInput result) { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(project, changeId)); } }); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java index 147f2bc949..0e3e8358dc 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RebaseAction.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.ui.RebaseDialog; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.PopupPanel; @@ -28,7 +29,7 @@ import com.google.gwt.user.client.ui.PopupPanel; class RebaseAction { static void call( final Button b, - final String project, + final Project.NameKey project, final String branch, final Change.Id id, final String revision, @@ -39,6 +40,7 @@ class RebaseAction { @Override public void onSend() { ChangeApi.rebase( + project.get(), id.get(), revision, getBase(), @@ -47,7 +49,7 @@ class RebaseAction { public void onSuccess(ChangeInfo result) { sent = true; hide(); - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java index 32284b0890..f65f0ac56d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChanges.java @@ -203,7 +203,7 @@ public class RelatedChanges extends TabPanel { setForOpenChange(info, revision); } - ChangeApi.revision(info.legacyId().get(), revision) + ChangeApi.revision(info.project(), info.legacyId().get(), revision) .view("related") .get( new TabCallback(Tab.RELATED_CHANGES, info.project(), revision) { @@ -224,7 +224,7 @@ public class RelatedChanges extends TabPanel { new TabChangeListCallback(Tab.CHERRY_PICKS, info.project(), revision)); if (info.currentRevision() != null && info.currentRevision().equals(revision)) { - ChangeApi.change(info.legacyId().get()) + ChangeApi.change(info.project(), info.legacyId().get()) .view("submitted_together") .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER, info.project(), revision)); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java index 9ffbad8a8d..aa049cab51 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RelatedChangesTab.java @@ -20,6 +20,7 @@ import com.google.gerrit.client.changes.Util; import com.google.gerrit.client.info.ChangeInfo.CommitInfo; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.Scheduler; @@ -332,7 +333,7 @@ class RelatedChangesTab implements IsWidget { private String url() { if (info.hasChangeNumber() && info.hasRevisionNumber()) { - return "#" + PageLinks.toChange(info.patchSetId()); + return "#" + PageLinks.toChange(new Project.NameKey(info.project()), info.patchSetId()); } return null; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java index cc24fe623d..1e7063ab62 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileAction.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.change; import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.ui.PopupPanel; @@ -23,6 +24,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.globalkey.client.GlobalKey; class RenameFileAction { + private final Project.NameKey project; private final Change.Id changeId; private final RevisionInfo revision; private final ChangeScreen.Style style; @@ -32,7 +34,12 @@ class RenameFileAction { private PopupPanel popup; RenameFileAction( - Change.Id changeId, RevisionInfo revision, ChangeScreen.Style style, Widget renameButton) { + Project.NameKey project, + Change.Id changeId, + RevisionInfo revision, + ChangeScreen.Style style, + Widget renameButton) { + this.project = project; this.changeId = changeId; this.revision = revision; this.style = style; @@ -46,7 +53,7 @@ class RenameFileAction { } if (renameBox == null) { - renameBox = new RenameFileBox(changeId, revision); + renameBox = new RenameFileBox(project, changeId, revision); } renameBox.clearPath(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java index a36b8effb8..f288dbe4e6 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RenameFileBox.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.ui.RemoteSuggestBox; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.CloseEvent; @@ -41,6 +42,7 @@ class RenameFileBox extends Composite { private static final Binder uiBinder = GWT.create(Binder.class); + private final Project.NameKey project; private final Change.Id changeId; @UiField Button rename; @@ -51,10 +53,11 @@ class RenameFileBox extends Composite { @UiField NpTextBox newPath; - RenameFileBox(Change.Id changeId, RevisionInfo revision) { + RenameFileBox(Project.NameKey project, Change.Id changeId, RevisionInfo revision) { + this.project = project; this.changeId = changeId; - path = new RemoteSuggestBox(new PathSuggestOracle(changeId, revision)); + path = new RemoteSuggestBox(new PathSuggestOracle(project, changeId, revision)); path.addCloseHandler( new CloseHandler() { @Override @@ -82,13 +85,14 @@ class RenameFileBox extends Composite { private void rename(String path, String newPath) { hide(); ChangeEditApi.rename( + project.get(), changeId.get(), path, newPath, new AsyncCallback() { @Override public void onSuccess(VoidResult result) { - Gerrit.display(PageLinks.toChangeInEditMode(changeId)); + Gerrit.display(PageLinks.toChangeInEditMode(project, changeId)); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java index 1c21cbf782..ff09ff5c35 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyAction.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.info.ChangeInfo.MessageInfo; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; @@ -31,6 +32,7 @@ import com.google.gwtexpui.globalkey.client.GlobalKey; class ReplyAction { private final PatchSet.Id psId; + private final Project.NameKey project; private final String revision; private final boolean hasDraftComments; private final ChangeScreen.Style style; @@ -53,6 +55,7 @@ class ReplyAction { Widget replyButton, Widget quickApproveButton) { this.psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number()); + this.project = info.projectNameKey(); this.revision = revision; this.hasDraftComments = hasDraftComments; this.style = style; @@ -90,7 +93,7 @@ class ReplyAction { } if (replyBox == null) { - replyBox = new ReplyBox(clp, psId, revision, allLabels, permittedLabels); + replyBox = new ReplyBox(clp, project, psId, revision, allLabels, permittedLabels); allLabels = null; permittedLabels = null; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java index 00a543f285..80b179605c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java @@ -35,6 +35,7 @@ import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.data.LabelValue; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; @@ -92,6 +93,7 @@ public class ReplyBox extends Composite { } private final CommentLinkProcessor clp; + private final Project.NameKey project; private final PatchSet.Id psId; private final String revision; private ReviewInput in = ReviewInput.create(); @@ -109,14 +111,16 @@ public class ReplyBox extends Composite { ReplyBox( CommentLinkProcessor clp, + Project.NameKey project, PatchSet.Id psId, String revision, NativeMap all, NativeMap permitted) { this.clp = clp; + this.project = project; this.psId = psId; this.revision = revision; - this.lc = new LocalComments(psId.getParentKey()); + this.lc = new LocalComments(project, psId.getParentKey()); initWidget(uiBinder.createAndBindUi(this)); List names = new ArrayList<>(permitted.keySet()); @@ -160,7 +164,7 @@ public class ReplyBox extends Composite { message.setText(lc.getReplyComment()); lc.removeReplyComment(); } - ChangeApi.drafts(psId.getParentKey().get()) + ChangeApi.drafts(project.get(), psId.getParentKey().get()) .get( new AsyncCallback>>() { @Override @@ -218,14 +222,14 @@ public class ReplyBox extends Composite { // e.g. a draft was modified in another tab since we last looked it up. in.drafts(DraftHandling.PUBLISH_ALL_REVISIONS); in.prePost(); - ChangeApi.revision(psId.getParentKey().get(), revision) + ChangeApi.revision(project.get(), psId.getParentKey().get(), revision) .view("review") .post( in, new GerritCallback() { @Override public void onSuccess(ReviewInput result) { - Gerrit.display(PageLinks.toChange(psId)); + Gerrit.display(PageLinks.toChange(project, psId)); } @Override @@ -425,12 +429,14 @@ public class ReplyBox extends Composite { JsArray l = m.get(Patch.COMMIT_MSG); if (l != null) { comments.add( - new FileComments(clp, psId, Util.C.commitMessage(), copyPath(Patch.COMMIT_MSG, l))); + new FileComments( + clp, project, psId, Util.C.commitMessage(), copyPath(Patch.COMMIT_MSG, l))); } l = m.get(Patch.MERGE_LIST); if (l != null) { comments.add( - new FileComments(clp, psId, Util.C.commitMessage(), copyPath(Patch.MERGE_LIST, l))); + new FileComments( + clp, project, psId, Util.C.commitMessage(), copyPath(Patch.MERGE_LIST, l))); } List paths = new ArrayList<>(m.keySet()); @@ -438,7 +444,7 @@ public class ReplyBox extends Composite { for (String path : paths) { if (!Patch.isMagic(path)) { - comments.add(new FileComments(clp, psId, path, copyPath(path, m.get(path)))); + comments.add(new FileComments(clp, project, psId, path, copyPath(path, m.get(path)))); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java index ebc3d6823b..aa3a9ef544 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RestoreAction.java @@ -20,25 +20,29 @@ import com.google.gerrit.client.info.ChangeInfo; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.user.client.ui.Button; class RestoreAction extends ActionMessageBox { + private final Project.NameKey project; private final Change.Id id; - RestoreAction(Button b, Change.Id id) { + RestoreAction(Button b, Project.NameKey project, Change.Id id) { super(b); + this.project = project; this.id = id; } @Override void send(String message) { ChangeApi.restore( + project.get(), id.get(), message, new GerritCallback() { @Override public void onSuccess(ChangeInfo result) { - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(project, id)); hide(); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java index 1747352177..3fba125e77 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/RevertAction.java @@ -22,12 +22,19 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.ui.TextAreaActionDialog; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.PopupPanel; class RevertAction { - static void call(final Button b, Change.Id id, String revision, String commitSubject) { + + static void call( + final Button b, + Change.Id id, + Project.NameKey project, + String revision, + String commitSubject) { // TODO Replace ActionDialog with a nicer looking display. b.setEnabled(false); new TextAreaActionDialog(Util.C.revertChangeTitle(), Util.C.headingRevertMessage()) { @@ -39,6 +46,7 @@ class RevertAction { @Override public void onSend() { ChangeApi.revert( + project.get(), id.get(), getMessageText(), new GerritCallback() { @@ -46,7 +54,7 @@ class RevertAction { public void onSuccess(ChangeInfo result) { sent = true; hide(); - Gerrit.display(PageLinks.toChange(result.legacyId())); + Gerrit.display(PageLinks.toChange(result.projectNameKey(), result.legacyId())); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java index 1ff751eec3..4e464dfafb 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReviewerSuggestOracle.java @@ -22,6 +22,7 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.ui.AccountSuggestOracle; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwtexpui.safehtml.client.HighlightSuggestOracle; @@ -31,11 +32,12 @@ import java.util.List; /** REST API based suggestion Oracle for reviewers. */ public class ReviewerSuggestOracle extends HighlightSuggestOracle { + private Project.NameKey project; private Change.Id changeId; @Override protected void onRequestSuggestions(Request req, Callback cb) { - ChangeApi.suggestReviewers(changeId.get(), req.getQuery(), req.getLimit(), false) + ChangeApi.suggestReviewers(project.get(), changeId.get(), req.getQuery(), req.getLimit(), false) .get( new GerritCallback>() { @Override @@ -60,7 +62,8 @@ public class ReviewerSuggestOracle extends HighlightSuggestOracle { requestSuggestions(req, cb); } - public void setChange(Change.Id changeId) { + public void setChange(Project.NameKey project, Change.Id changeId) { + this.project = project; this.changeId = changeId; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java index 166029dec9..859af19b4c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Reviewers.java @@ -31,6 +31,7 @@ import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.ui.RemoteSuggestBox; import com.google.gerrit.extensions.client.ReviewerState; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; @@ -78,6 +79,7 @@ public class Reviewers extends Composite { private ReviewerSuggestOracle reviewerSuggestOracle; private Change.Id changeId; + private Project.NameKey project; Reviewers() { reviewerSuggestOracle = new ReviewerSuggestOracle(); @@ -118,8 +120,9 @@ public class Reviewers extends Composite { void set(ChangeInfo info) { this.changeId = info.legacyId(); + this.project = info.projectNameKey(); display(info); - reviewerSuggestOracle.setChange(changeId); + reviewerSuggestOracle.setChange(project, changeId); addReviewerIcon.setVisible(Gerrit.isSignedIn()); } @@ -156,7 +159,7 @@ public class Reviewers extends Composite { return; } - ChangeApi.reviewers(changeId.get()) + ChangeApi.reviewers(project.get(), changeId.get()) .post( PostInput.create(reviewer, confirmed), new GerritCallback() { @@ -208,6 +211,7 @@ public class Reviewers extends Composite { void updateReviewerList() { ChangeApi.detail( + project.get(), changeId.get(), new GerritCallback() { @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java index 69a7ca56db..4446e65000 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/SubmitAction.java @@ -29,6 +29,7 @@ class SubmitAction { if (ChangeGlue.onSubmitChange(changeInfo, revisionInfo)) { final Change.Id changeId = changeInfo.legacyId(); ChangeApi.submit( + changeInfo.project(), changeId.get(), revisionInfo.name(), new GerritCallback() { @@ -48,7 +49,7 @@ class SubmitAction { } private void redisplay() { - Gerrit.display(PageLinks.toChange(changeId)); + Gerrit.display(PageLinks.toChange(changeInfo.projectNameKey(), changeId)); } }); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java index f08414a685..f5c921ba1c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/Topic.java @@ -21,6 +21,7 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; @@ -45,6 +46,7 @@ class Topic extends Composite { private static final Binder uiBinder = GWT.create(Binder.class); private PatchSet.Id psId; + private Project.NameKey project; private boolean canEdit; @UiField Element show; @@ -72,6 +74,7 @@ class Topic extends Composite { canEdit = info.hasActions() && info.actions().containsKey("topic"); psId = new PatchSet.Id(info.legacyId(), info.revisions().get(revision)._number()); + project = info.projectNameKey(); initTopicLink(info); editIcon.setVisible(canEdit); @@ -124,12 +127,13 @@ class Topic extends Composite { @UiHandler("save") void onSave(@SuppressWarnings("unused") ClickEvent e) { ChangeApi.topic( + project.get(), psId.getParentKey().get(), input.getValue().trim(), new GerritCallback() { @Override public void onSuccess(String result) { - Gerrit.display(PageLinks.toChange(psId)); + Gerrit.display(PageLinks.toChange(project, psId)); } }); onCancel(null); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java index 915867d0f3..76d3919892 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeApi.java @@ -23,6 +23,7 @@ import com.google.gerrit.client.info.ChangeInfo.IncludedInInfo; import com.google.gerrit.client.rpc.CallbackGroup.Callback; import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gwt.core.client.JavaScriptObject; @@ -31,10 +32,11 @@ import com.google.gwt.user.client.rpc.AsyncCallback; /** A collection of static methods which work on the Gerrit REST API for specific changes. */ public class ChangeApi { /** Abandon the change, ending its review. */ - public static void abandon(int id, String msg, AsyncCallback cb) { + public static void abandon( + @Nullable String project, int id, String msg, AsyncCallback cb) { MessageInput input = MessageInput.create(); input.message(emptyToNull(msg)); - call(id, "abandon").post(input, cb); + call(project, id, "abandon").post(input, cb); } /** @@ -66,22 +68,25 @@ public class ChangeApi { } /** Restore a previously abandoned change to be open again. */ - public static void restore(int id, String msg, AsyncCallback cb) { + public static void restore( + @Nullable String project, int id, String msg, AsyncCallback cb) { MessageInput input = MessageInput.create(); input.message(emptyToNull(msg)); - call(id, "restore").post(input, cb); + call(project, id, "restore").post(input, cb); } /** Create a new change that reverts the delta caused by this change. */ - public static void revert(int id, String msg, AsyncCallback cb) { + public static void revert( + @Nullable String project, int id, String msg, AsyncCallback cb) { MessageInput input = MessageInput.create(); input.message(emptyToNull(msg)); - call(id, "revert").post(input, cb); + call(project, id, "revert").post(input, cb); } /** Update the topic of a change. */ - public static void topic(int id, String topic, AsyncCallback cb) { - RestApi call = call(id, "topic"); + public static void topic( + @Nullable String project, int id, String topic, AsyncCallback cb) { + RestApi call = call(project, id, "topic"); topic = emptyToNull(topic); if (topic != null) { TopicInput input = TopicInput.create(); @@ -92,177 +97,201 @@ public class ChangeApi { } } - public static void detail(int id, AsyncCallback cb) { - detail(id).get(cb); + public static void detail(@Nullable String project, int id, AsyncCallback cb) { + detail(project, id).get(cb); } - public static RestApi detail(int id) { - return call(id, "detail"); + public static RestApi detail(@Nullable String project, int id) { + return call(project, id, "detail"); } - public static RestApi blame(PatchSet.Id id, String path, boolean base) { - return revision(id).view("files").id(path).view("blame").addParameter("base", base); + public static RestApi blame(@Nullable String project, PatchSet.Id id, String path, boolean base) { + return revision(project, id).view("files").id(path).view("blame").addParameter("base", base); } - public static RestApi actions(int id, String revision) { + public static RestApi actions(@Nullable String project, int id, String revision) { if (revision == null || revision.equals("")) { revision = "current"; } - return call(id, revision, "actions"); + return call(project, id, revision, "actions"); } - public static void deleteAssignee(int id, AsyncCallback cb) { - change(id).view("assignee").delete(cb); + public static void deleteAssignee( + @Nullable String project, int id, AsyncCallback cb) { + change(project, id).view("assignee").delete(cb); } - public static void setAssignee(int id, String user, AsyncCallback cb) { + public static void setAssignee( + @Nullable String project, int id, String user, AsyncCallback cb) { AssigneeInput input = AssigneeInput.create(); input.assignee(user); - change(id).view("assignee").put(input, cb); + change(project, id).view("assignee").put(input, cb); } - public static void markPrivate(int id, AsyncCallback cb) { - change(id).view("private").post(PrivateInput.create(), cb); + public static void markPrivate( + @Nullable String project, int id, AsyncCallback cb) { + change(project, id).view("private").post(PrivateInput.create(), cb); } - public static void unmarkPrivate(int id, AsyncCallback cb) { - change(id).view("private.delete").post(PrivateInput.create(), cb); + public static void unmarkPrivate( + @Nullable String project, int id, AsyncCallback cb) { + change(project, id).view("private.delete").post(PrivateInput.create(), cb); } - public static RestApi comments(int id) { - return call(id, "comments"); + public static RestApi comments(@Nullable String project, int id) { + return call(project, id, "comments"); } - public static RestApi drafts(int id) { - return call(id, "drafts"); + public static RestApi drafts(@Nullable String project, int id) { + return call(project, id, "drafts"); } - public static void edit(int id, AsyncCallback cb) { - edit(id).get(cb); + public static void edit(@Nullable String project, int id, AsyncCallback cb) { + edit(project, id).get(cb); } - public static void editWithFiles(int id, AsyncCallback cb) { - edit(id).addParameterTrue("list").get(cb); + public static void editWithFiles(@Nullable String project, int id, AsyncCallback cb) { + edit(project, id).addParameterTrue("list").get(cb); } - public static RestApi edit(int id) { - return change(id).view("edit"); + public static RestApi edit(@Nullable String project, int id) { + return change(project, id).view("edit"); } - public static RestApi editWithCommands(int id) { - return edit(id).addParameterTrue("download-commands"); + public static RestApi editWithCommands(@Nullable String project, int id) { + return edit(project, id).addParameterTrue("download-commands"); } - public static void includedIn(int id, AsyncCallback cb) { - call(id, "in").get(cb); + public static void includedIn( + @Nullable String project, int id, AsyncCallback cb) { + call(project, id, "in").get(cb); } - public static RestApi revision(int id, String revision) { - return change(id).view("revisions").id(revision); + public static RestApi revision(@Nullable String project, int id, String revision) { + return change(project, id).view("revisions").id(revision); } - public static RestApi revision(PatchSet.Id id) { + public static RestApi revision(@Nullable String project, PatchSet.Id id) { int cn = id.getParentKey().get(); String revision = RevisionInfoCache.get(id); if (revision != null) { - return revision(cn, revision); + return revision(project, cn, revision); } - return change(cn).view("revisions").id(id.get()); + return change(project, cn).view("revisions").id(id.get()); } - public static RestApi reviewers(int id) { - return change(id).view("reviewers"); + public static RestApi reviewers(@Nullable String project, int id) { + return change(project, id).view("reviewers"); } - public static RestApi suggestReviewers(int id, String q, int n, boolean e) { - RestApi api = change(id).view("suggest_reviewers").addParameter("n", n).addParameter("e", e); + public static RestApi suggestReviewers( + @Nullable String project, int id, String q, int n, boolean e) { + RestApi api = + change(project, id).view("suggest_reviewers").addParameter("n", n).addParameter("e", e); if (q != null) { api.addParameter("q", q); } return api; } - public static RestApi vote(int id, int reviewer, String vote) { - return reviewer(id, reviewer).view("votes").id(vote); + public static RestApi vote(@Nullable String project, int id, int reviewer, String vote) { + return reviewer(project, id, reviewer).view("votes").id(vote); } - public static RestApi reviewer(int id, int reviewer) { - return change(id).view("reviewers").id(reviewer); + public static RestApi reviewer(@Nullable String project, int id, int reviewer) { + return change(project, id).view("reviewers").id(reviewer); } - public static RestApi reviewer(int id, String reviewer) { - return change(id).view("reviewers").id(reviewer); + public static RestApi reviewer(@Nullable String project, int id, String reviewer) { + return change(project, id).view("reviewers").id(reviewer); } - public static RestApi hashtags(int changeId) { - return change(changeId).view("hashtags"); + public static RestApi hashtags(@Nullable String project, int changeId) { + return change(project, changeId).view("hashtags"); } - public static RestApi hashtag(int changeId, String hashtag) { - return change(changeId).view("hashtags").id(hashtag); + public static RestApi hashtag(@Nullable String project, int changeId, String hashtag) { + return change(project, changeId).view("hashtags").id(hashtag); } /** Submit a specific revision of a change. */ public static void cherrypick( - int id, String commit, String destination, String message, AsyncCallback cb) { + String project, + int id, + String commit, + String destination, + String message, + AsyncCallback cb) { CherryPickInput cherryPickInput = CherryPickInput.create(); cherryPickInput.setMessage(message); cherryPickInput.setDestination(destination); - call(id, commit, "cherrypick").post(cherryPickInput, cb); + call(project, id, commit, "cherrypick").post(cherryPickInput, cb); } /** Edit commit message for specific revision of a change. */ public static void message( - int id, String commit, String message, AsyncCallback cb) { + @Nullable String project, + int id, + String commit, + String message, + AsyncCallback cb) { CherryPickInput input = CherryPickInput.create(); input.setMessage(message); - call(id, commit, "message").post(input, cb); + call(project, id, commit, "message").post(input, cb); } /** Submit a specific revision of a change. */ - public static void submit(int id, String commit, AsyncCallback cb) { + public static void submit( + @Nullable String project, int id, String commit, AsyncCallback cb) { JavaScriptObject in = JavaScriptObject.createObject(); - call(id, commit, "submit").post(in, cb); + call(project, id, commit, "submit").post(in, cb); } /** Publish a specific revision of a draft change. */ - public static void publish(int id, String commit, AsyncCallback cb) { + public static void publish( + @Nullable String project, int id, String commit, AsyncCallback cb) { JavaScriptObject in = JavaScriptObject.createObject(); - call(id, commit, "publish").post(in, cb); + call(project, id, commit, "publish").post(in, cb); } /** Delete a specific draft change. */ - public static void deleteChange(int id, AsyncCallback cb) { - change(id).delete(cb); + public static void deleteChange( + @Nullable String project, int id, AsyncCallback cb) { + change(project, id).delete(cb); } /** Delete a specific draft patch set. */ - public static void deleteRevision(int id, String commit, AsyncCallback cb) { - revision(id, commit).delete(cb); + public static void deleteRevision( + @Nullable String project, int id, String commit, AsyncCallback cb) { + revision(project, id, commit).delete(cb); } /** Delete change edit. */ - public static void deleteEdit(int id, AsyncCallback cb) { - edit(id).delete(cb); + public static void deleteEdit( + @Nullable String project, int id, AsyncCallback cb) { + edit(project, id).delete(cb); } /** Publish change edit. */ - public static void publishEdit(int id, AsyncCallback cb) { + public static void publishEdit( + @Nullable String project, int id, AsyncCallback cb) { JavaScriptObject in = JavaScriptObject.createObject(); - change(id).view("edit:publish").post(in, cb); + change(project, id).view("edit:publish").post(in, cb); } /** Rebase change edit on latest patch set. */ - public static void rebaseEdit(int id, AsyncCallback cb) { + public static void rebaseEdit( + @Nullable String project, int id, AsyncCallback cb) { JavaScriptObject in = JavaScriptObject.createObject(); - change(id).view("edit:rebase").post(in, cb); + change(project, id).view("edit:rebase").post(in, cb); } /** Rebase a revision onto the branch tip or another change. */ - public static void rebase(int id, String commit, String base, AsyncCallback cb) { + public static void rebase( + @Nullable String project, int id, String commit, String base, AsyncCallback cb) { RebaseInput rebaseInput = RebaseInput.create(); rebaseInput.setBase(base); - call(id, commit, "rebase").post(rebaseInput, cb); + call(project, id, commit, "rebase").post(rebaseInput, cb); } private static class MessageInput extends JavaScriptObject { @@ -347,24 +376,28 @@ public class ChangeApi { protected RebaseInput() {} } - private static RestApi call(int id, String action) { - return change(id).view(action); + private static RestApi call(@Nullable String project, int id, String action) { + return change(project, id).view(action); } - private static RestApi call(int id, String commit, String action) { - return change(id).view("revisions").id(commit).view(action); + private static RestApi call(@Nullable String project, int id, String commit, String action) { + return change(project, id).view("revisions").id(commit).view(action); } - public static RestApi change(int id) { - // TODO Switch to triplet project~branch~id format in URI. - return new RestApi("/changes/").id(String.valueOf(id)); + public static RestApi change(@Nullable String project, int id) { + if (project == null) { + return new RestApi("/changes/").id(String.valueOf(id)); + } else { + return new RestApi("/changes/").id(project, id); + } } public static String emptyToNull(String str) { return str == null || str.isEmpty() ? null : str; } - public static void commitWithLinks(int changeId, String revision, Callback callback) { - revision(changeId, revision).view("commit").addParameterTrue("links").get(callback); + public static void commitWithLinks( + @Nullable String project, int changeId, String revision, Callback callback) { + revision(project, changeId, revision).view("commit").addParameterTrue("links").get(callback); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java index 0a7fd084a2..71b54f7d56 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeEditApi.java @@ -20,81 +20,110 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.HttpCallback; import com.google.gerrit.client.rpc.NativeString; import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.user.client.rpc.AsyncCallback; /** REST API helpers to remotely edit a change. */ public class ChangeEditApi { /** Get file (or commit message) contents. */ - public static void get(PatchSet.Id id, String path, boolean base, HttpCallback cb) { + public static void get( + @Nullable Project.NameKey project, + PatchSet.Id id, + String path, + boolean base, + HttpCallback cb) { RestApi api; if (id.get() != 0) { // Read from a published revision, when change edit doesn't // exist for the caller, or is not currently active. - api = ChangeApi.revision(id).view("files").id(path).view("content"); + api = + ChangeApi.revision(Project.NameKey.asStringOrNull(project), id) + .view("files") + .id(path) + .view("content"); } else if (Patch.COMMIT_MSG.equals(path)) { - api = editMessage(id.getParentKey().get()).addParameter("base", base); + api = + editMessage(Project.NameKey.asStringOrNull(project), id.getParentKey().get()) + .addParameter("base", base); } else { - api = editFile(id.getParentKey().get(), path).addParameter("base", base); + api = + editFile(Project.NameKey.asStringOrNull(project), id.getParentKey().get(), path) + .addParameter("base", base); } api.get(cb); } /** Get file (or commit message) contents of the edit. */ - public static void get(PatchSet.Id id, String path, HttpCallback cb) { - get(id, path, false, cb); + public static void get( + @Nullable Project.NameKey project, + PatchSet.Id id, + String path, + HttpCallback cb) { + get(project, id, path, false, cb); } /** Get meta info for change edit. */ - public static void getMeta(PatchSet.Id id, String path, AsyncCallback cb) { + public static void getMeta( + @Nullable String project, PatchSet.Id id, String path, AsyncCallback cb) { if (id.get() != 0) { throw new IllegalStateException("only supported for edits"); } - editFile(id.getParentKey().get(), path).view("meta").get(cb); + editFile(project, id.getParentKey().get(), path).view("meta").get(cb); } /** Put message into a change edit. */ - public static void putMessage(int id, String m, GerritCallback cb) { - editMessage(id).put(m, cb); + public static void putMessage( + @Nullable String project, int id, String m, GerritCallback cb) { + editMessage(project, id).put(m, cb); } /** Put contents into a file or commit message in a change edit. */ - public static void put(int id, String path, String content, GerritCallback cb) { + public static void put( + @Nullable String project, + int id, + String path, + String content, + GerritCallback cb) { if (Patch.COMMIT_MSG.equals(path)) { - putMessage(id, content, cb); + putMessage(project, id, content, cb); } else { - editFile(id, path).put(content, cb); + editFile(project, id, path).put(content, cb); } } /** Delete a file in the pending edit. */ - public static void delete(int id, String path, AsyncCallback cb) { - editFile(id, path).delete(cb); + public static void delete( + @Nullable String project, int id, String path, AsyncCallback cb) { + editFile(project, id, path).delete(cb); } /** Rename a file in the pending edit. */ - public static void rename(int id, String path, String newPath, AsyncCallback cb) { + public static void rename( + @Nullable String project, int id, String path, String newPath, AsyncCallback cb) { Input in = Input.create(); in.oldPath(path); in.newPath(newPath); - ChangeApi.edit(id).post(in, cb); + ChangeApi.edit(project, id).post(in, cb); } /** Restore (undo delete/modify) a file in the pending edit. */ - public static void restore(int id, String path, AsyncCallback cb) { + public static void restore( + @Nullable String project, int id, String path, AsyncCallback cb) { Input in = Input.create(); in.restorePath(path); - ChangeApi.edit(id).post(in, cb); + ChangeApi.edit(project, id).post(in, cb); } - private static RestApi editMessage(int id) { - return ChangeApi.change(id).view("edit:message"); + private static RestApi editMessage(@Nullable String project, int id) { + return ChangeApi.change(project, id).view("edit:message"); } - private static RestApi editFile(int id, String path) { - return ChangeApi.edit(id).id(path); + private static RestApi editFile(@Nullable String project, int id, String path) { + return ChangeApi.edit(project, id).id(path); } private static class Input extends JavaScriptObject { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java index 2d6ae15b23..7243208e2f 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java @@ -140,8 +140,7 @@ public class ChangeTable extends NavigationTable { @Override protected void onOpenRow(int row) { final ChangeInfo c = getRowItem(row); - final Change.Id id = c.legacyId(); - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(c.projectNameKey(), c.legacyId())); } private void insertNoneRow(int row) { @@ -475,7 +474,7 @@ public class ChangeTable extends NavigationTable { private final class TableChangeLink extends ChangeLink { private TableChangeLink(String text, ChangeInfo c) { - super(text, c.legacyId()); + super(c.projectNameKey(), c.legacyId(), text); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java index 0950fa584b..987b3820fc 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentApi.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.changes; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; @@ -23,39 +24,53 @@ import com.google.gwt.user.client.rpc.AsyncCallback; public class CommentApi { - public static void comments(PatchSet.Id id, AsyncCallback>> cb) { - revision(id, "comments").get(cb); + public static void comments( + @Nullable String project, PatchSet.Id id, AsyncCallback>> cb) { + revision(project, id, "comments").get(cb); } - public static void comment(PatchSet.Id id, String commentId, AsyncCallback cb) { - revision(id, "comments").id(commentId).get(cb); + public static void comment( + @Nullable String project, PatchSet.Id id, String commentId, AsyncCallback cb) { + revision(project, id, "comments").id(commentId).get(cb); } - public static void drafts(PatchSet.Id id, AsyncCallback>> cb) { - revision(id, "drafts").get(cb); + public static void drafts( + @Nullable String project, PatchSet.Id id, AsyncCallback>> cb) { + revision(project, id, "drafts").get(cb); } - public static void draft(PatchSet.Id id, String draftId, AsyncCallback cb) { - revision(id, "drafts").id(draftId).get(cb); + public static void draft( + @Nullable String project, PatchSet.Id id, String draftId, AsyncCallback cb) { + revision(project, id, "drafts").id(draftId).get(cb); } public static void createDraft( - PatchSet.Id id, CommentInfo content, AsyncCallback cb) { - revision(id, "drafts").put(content, cb); + @Nullable String project, + PatchSet.Id id, + CommentInfo content, + AsyncCallback cb) { + revision(project, id, "drafts").put(content, cb); } public static void updateDraft( - PatchSet.Id id, String draftId, CommentInfo content, AsyncCallback cb) { - revision(id, "drafts").id(draftId).put(content, cb); + @Nullable String project, + PatchSet.Id id, + String draftId, + CommentInfo content, + AsyncCallback cb) { + revision(project, id, "drafts").id(draftId).put(content, cb); } public static void deleteDraft( - PatchSet.Id id, String draftId, AsyncCallback cb) { - revision(id, "drafts").id(draftId).delete(cb); + @Nullable String project, + PatchSet.Id id, + String draftId, + AsyncCallback cb) { + revision(project, id, "drafts").id(draftId).delete(cb); } - private static RestApi revision(PatchSet.Id id, String type) { - return ChangeApi.revision(id).view(type); + private static RestApi revision(@Nullable String project, PatchSet.Id id, String type) { + return ChangeApi.revision(project, id).view(type); } private CommentApi() {} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java index 696fe8b4ab..8d580a35dd 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/QueryScreen.java @@ -65,7 +65,7 @@ public class QueryScreen extends PagedSingleListScreen implements ChangeListScre if (result.length() == 1 && isSingleQuery(query)) { ChangeInfo c = result.get(0); Change.Id id = c.legacyId(); - Gerrit.display(PageLinks.toChange(id)); + Gerrit.display(PageLinks.toChange(c.projectNameKey(), id)); } else { display(result); QueryScreen.this.display(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java index 95b88ac7e4..ef1ec1e795 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentManager.java @@ -21,8 +21,10 @@ import com.google.gerrit.client.patches.SkippedLine; import com.google.gerrit.client.rpc.CallbackGroup; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.extensions.client.Side; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArray; import java.util.ArrayList; import java.util.Collection; @@ -39,6 +41,7 @@ import net.codemirror.lib.TextMarker.FromTo; /** Tracks comment widgets for {@link DiffScreen}. */ abstract class CommentManager { + @Nullable private final Project.NameKey project; private final DiffObject base; private final PatchSet.Id revision; private final String path; @@ -54,12 +57,14 @@ abstract class CommentManager { CommentManager( DiffScreen host, + @Nullable Project.NameKey project, DiffObject base, PatchSet.Id revision, String path, CommentLinkProcessor clp, boolean open) { this.host = host; + this.project = project; this.base = base; this.revision = revision; this.path = path; @@ -232,7 +237,12 @@ abstract class CommentManager { CommentGroup group = group(side, cmLinePlusOne); DraftBox box = new DraftBox( - group, getCommentLinkProcessor(), getPatchSetIdFromSide(side), info, isExpandAll()); + group, + getCommentLinkProcessor(), + project, + getPatchSetIdFromSide(side), + info, + isExpandAll()); if (info.inReplyTo() != null) { PublishedBox r = getPublished().get(info.inReplyTo()); @@ -350,6 +360,7 @@ abstract class CommentManager { new PublishedBox( group, getCommentLinkProcessor(), + project, getPatchSetIdFromSide(side), info, side, diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java index 3ed0c5082d..533b74598a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/CommentsCollections.java @@ -21,8 +21,10 @@ import com.google.gerrit.client.changes.CommentInfo; import com.google.gerrit.client.rpc.CallbackGroup; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.Natives; +import com.google.gerrit.common.Nullable; import com.google.gerrit.extensions.client.Side; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArray; import com.google.gwt.user.client.rpc.AsyncCallback; import java.util.Collections; @@ -30,6 +32,7 @@ import java.util.Comparator; /** Collection of published and draft comments loaded from the server. */ class CommentsCollections { + @Nullable private final Project.NameKey project; private final String path; private final DiffObject base; private final PatchSet.Id revision; @@ -40,7 +43,9 @@ class CommentsCollections { JsArray draftsBase; JsArray draftsRevision; - CommentsCollections(DiffObject base, PatchSet.Id revision, String path) { + CommentsCollections( + @Nullable Project.NameKey project, DiffObject base, PatchSet.Id revision, String path) { + this.project = project; this.path = path; this.base = base; this.revision = revision; @@ -48,15 +53,19 @@ class CommentsCollections { void load(CallbackGroup group) { if (base.isPatchSet()) { - CommentApi.comments(base.asPatchSetId(), group.add(publishedBase())); + CommentApi.comments( + Project.NameKey.asStringOrNull(project), base.asPatchSetId(), group.add(publishedBase())); } - CommentApi.comments(revision, group.add(publishedRevision())); + CommentApi.comments( + Project.NameKey.asStringOrNull(project), revision, group.add(publishedRevision())); if (Gerrit.isSignedIn()) { if (base.isPatchSet()) { - CommentApi.drafts(base.asPatchSetId(), group.add(draftsBase())); + CommentApi.drafts( + Project.NameKey.asStringOrNull(project), base.asPatchSetId(), group.add(draftsBase())); } - CommentApi.drafts(revision, group.add(draftsRevision())); + CommentApi.drafts( + Project.NameKey.asStringOrNull(project), revision, group.add(draftsRevision())); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java index 3f6406687d..1815920969 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffApi.java @@ -21,14 +21,19 @@ import com.google.gerrit.client.info.ChangeInfo.RevisionInfo; import com.google.gerrit.client.info.FileInfo; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.RestApi; +import com.google.gerrit.common.Nullable; import com.google.gerrit.extensions.client.DiffPreferencesInfo; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gwt.user.client.rpc.AsyncCallback; public class DiffApi { public static void list( - int id, String revision, RevisionInfo base, AsyncCallback> cb) { - RestApi api = ChangeApi.revision(id, revision).view("files"); + @Nullable String project, + int id, + String revision, + RevisionInfo base, + AsyncCallback> cb) { + RestApi api = ChangeApi.revision(project, id, revision).view("files"); if (base != null) { if (base._number() < 0) { api.addParameter("parent", -base._number()); @@ -39,8 +44,12 @@ public class DiffApi { api.get(NativeMap.copyKeysIntoChildren("path", cb)); } - public static void list(PatchSet.Id id, PatchSet.Id base, AsyncCallback> cb) { - RestApi api = ChangeApi.revision(id).view("files"); + public static void list( + @Nullable String project, + PatchSet.Id id, + PatchSet.Id base, + AsyncCallback> cb) { + RestApi api = ChangeApi.revision(project, id).view("files"); if (base != null) { if (base.get() < 0) { api.addParameter("parent", -base.get()); @@ -51,8 +60,8 @@ public class DiffApi { api.get(NativeMap.copyKeysIntoChildren("path", cb)); } - public static DiffApi diff(PatchSet.Id id, String path) { - return new DiffApi(ChangeApi.revision(id).view("files").id(path).view("diff")); + public static DiffApi diff(@Nullable String project, PatchSet.Id id, String path) { + return new DiffApi(ChangeApi.revision(project, id).view("files").id(path).view("diff")); } private final RestApi call; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java index 9ccf6eae50..1e7d92b6b0 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffScreen.java @@ -39,12 +39,14 @@ import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.Screen; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView; import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; @@ -94,6 +96,7 @@ abstract class DiffScreen extends Screen { } } + @Nullable private Project.NameKey project; private final Change.Id changeId; final DiffObject base; final PatchSet.Id revision; @@ -122,12 +125,14 @@ abstract class DiffScreen extends Screen { Header header; DiffScreen( + @Nullable Project.NameKey project, DiffObject base, DiffObject revision, String path, DisplaySide startSide, int startLine, DiffView diffScreenType) { + this.project = project; this.base = base; this.revision = revision.asPatchSetId(); this.changeId = revision.asPatchSetId().getParentKey(); @@ -138,7 +143,7 @@ abstract class DiffScreen extends Screen { prefs = DiffPreferences.create(Gerrit.getDiffPreferences()); handlers = new ArrayList<>(6); keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation()); - header = new Header(keysNavigation, base, revision, path, diffScreenType, prefs); + header = new Header(keysNavigation, project, base, revision, path, diffScreenType, prefs); skipManager = new SkipManager(this); } @@ -171,7 +176,7 @@ abstract class DiffScreen extends Screen { public void onFailure(Throwable caught) {} })); - DiffApi.diff(revision, path) + DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, path) .base(base.asPatchSetId()) .wholeFile() .intraline(prefs.intralineDifference()) @@ -200,6 +205,7 @@ abstract class DiffScreen extends Screen { if (Gerrit.isSignedIn()) { ChangeApi.edit( + Project.NameKey.asStringOrNull(project), changeId.get(), group2.add( new AsyncCallback() { @@ -213,12 +219,12 @@ abstract class DiffScreen extends Screen { })); } - final CommentsCollections comments = new CommentsCollections(base, revision, path); + final CommentsCollections comments = new CommentsCollections(project, base, revision, path); comments.load(group2); countParents(group2); - RestApi call = ChangeApi.detail(changeId.get()); + RestApi call = ChangeApi.detail(Project.NameKey.asStringOrNull(project), changeId.get()); ChangeList.addOptions(call, EnumSet.of(ListChangesOption.ALL_REVISIONS)); call.get( group2.add( @@ -226,6 +232,7 @@ abstract class DiffScreen extends Screen { @Override public void onSuccess(ChangeInfo info) { changeStatus = info.status(); + project = info.projectNameKey(); info.revisions().copyKeysIntoChildren("name"); if (edit != null) { edit.setName(edit.commit().commit()); @@ -259,7 +266,7 @@ abstract class DiffScreen extends Screen { } private void countParents(CallbackGroup cbg) { - ChangeApi.revision(changeId.get(), revision.getId()) + ChangeApi.revision(Project.NameKey.asStringOrNull(project), changeId.get(), revision.getId()) .view("commit") .get( cbg.add( @@ -443,7 +450,7 @@ abstract class DiffScreen extends Screen { public void registerKeys() { super.registerKeys(); - keysNavigation.add(new UpToChangeCommand(revision, 0, 'u')); + keysNavigation.add(new UpToChangeCommand(project, revision, 0, 'u')); keysNavigation.add( new NoOpKeyCommand(0, 'j', PatchUtil.C.lineNext()), new NoOpKeyCommand(0, 'k', PatchUtil.C.linePrev())); @@ -513,6 +520,11 @@ abstract class DiffScreen extends Screen { } } + @Nullable + public Project.NameKey getProject() { + return project; + } + void registerHandlers() { removeKeyHandlerRegistrations(); handlers.add(GlobalKey.add(this, keysAction)); @@ -632,7 +644,7 @@ abstract class DiffScreen extends Screen { if (Patch.COMMIT_MSG.equals(path)) { line = adjustCommitMessageLine(line); } - String token = Dispatcher.toEditScreen(revision, path, line); + String token = Dispatcher.toEditScreen(project, revision, path, line); if (!Gerrit.isSignedIn()) { Gerrit.doSignIn(token); } else { @@ -712,8 +724,9 @@ abstract class DiffScreen extends Screen { public void onSuccess(Void result) { String rev = String.valueOf(revision.get()); Gerrit.display( - PageLinks.toChange(changeId, base.asString(), rev), - new ChangeScreen(changeId, base, rev, openReplyBox, FileTable.Mode.REVIEW)); + PageLinks.toChange(project, changeId, base.asString(), rev), + new ChangeScreen( + project, changeId, base, rev, openReplyBox, FileTable.Mode.REVIEW)); } }); }; @@ -808,7 +821,7 @@ abstract class DiffScreen extends Screen { void prefetchNextFile() { String nextPath = header.getNextPath(); if (nextPath != null) { - DiffApi.diff(revision, nextPath) + DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, nextPath) .base(base.asPatchSetId()) .wholeFile() .intraline(prefs.intralineDifference()) @@ -831,7 +844,7 @@ abstract class DiffScreen extends Screen { void reloadDiffInfo() { int id = ++reloadVersionId; - DiffApi.diff(revision, path) + DiffApi.diff(Project.NameKey.asStringOrNull(project), revision, path) .base(base.asPatchSetId()) .wholeFile() .intraline(prefs.intralineDifference()) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java index 4650acfe7f..a91f8e653e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DiffTable.java @@ -73,10 +73,20 @@ abstract class DiffTable extends Composite { DiffTable(DiffScreen parent, DiffObject base, DiffObject revision, String path) { patchSetSelectBoxA = new PatchSetSelectBox( - parent, DisplaySide.A, revision.asPatchSetId().getParentKey(), base, path); + parent, + DisplaySide.A, + parent.getProject(), + revision.asPatchSetId().getParentKey(), + base, + path); patchSetSelectBoxB = new PatchSetSelectBox( - parent, DisplaySide.B, revision.asPatchSetId().getParentKey(), revision, path); + parent, + DisplaySide.B, + parent.getProject(), + revision.asPatchSetId().getParentKey(), + revision, + path); PatchSetSelectBox.link(patchSetSelectBoxA, patchSetSelectBoxB); this.scrollbar = new Scrollbar(this); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java index b86df0be91..33d1ac4524 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/DraftBox.java @@ -22,7 +22,9 @@ import com.google.gerrit.client.rpc.CallbackGroup; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; @@ -63,6 +65,7 @@ class DraftBox extends CommentBox { private final CommentLinkProcessor linkProcessor; private final PatchSet.Id psId; + @Nullable private final Project.NameKey project; private final boolean expandAll; private CommentInfo comment; private PublishedBox replyToBox; @@ -90,6 +93,7 @@ class DraftBox extends CommentBox { DraftBox( CommentGroup group, CommentLinkProcessor clp, + @Nullable Project.NameKey pj, PatchSet.Id id, CommentInfo info, boolean expandAllComments) { @@ -97,6 +101,7 @@ class DraftBox extends CommentBox { linkProcessor = clp; psId = id; + project = pj; expandAll = expandAllComments; initWidget(uiBinder.createAndBindUi(this)); @@ -295,7 +300,7 @@ class DraftBox extends CommentBox { enableEdit(false); pendingGroup = group; - final LocalComments lc = new LocalComments(psId); + final LocalComments lc = new LocalComments(project, psId); GerritCallback cb = new GerritCallback() { @Override @@ -323,9 +328,10 @@ class DraftBox extends CommentBox { } }; if (input.id() == null) { - CommentApi.createDraft(psId, input, group.add(cb)); + CommentApi.createDraft(Project.NameKey.asStringOrNull(project), psId, input, group.add(cb)); } else { - CommentApi.updateDraft(psId, input.id(), input, group.add(cb)); + CommentApi.updateDraft( + Project.NameKey.asStringOrNull(project), psId, input.id(), input, group.add(cb)); } CodeMirror cm = getCm(); cm.vim().handleKey(""); @@ -364,6 +370,7 @@ class DraftBox extends CommentBox { setEdit(false); pendingGroup = new CallbackGroup(); CommentApi.deleteDraft( + Project.NameKey.asStringOrNull(project), psId, comment.id(), pendingGroup.addFinal( diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java index bf9f9e3c7b..7a97df123e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Header.java @@ -32,11 +32,13 @@ import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.ui.InlineHyperlink; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.Patch.ChangeType; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; @@ -90,6 +92,7 @@ public class Header extends Composite { @UiField Image preferences; private final KeyCommandSet keys; + @Nullable private final Project.NameKey projectKey; private final DiffObject base; private final PatchSet.Id patchSetId; private final String path; @@ -104,6 +107,7 @@ public class Header extends Composite { Header( KeyCommandSet keys, + @Nullable Project.NameKey project, DiffObject base, DiffObject patchSetId, String path, @@ -111,6 +115,7 @@ public class Header extends Composite { DiffPreferences prefs) { initWidget(uiBinder.createAndBindUi(this)); this.keys = keys; + this.projectKey = project; this.base = base; this.patchSetId = patchSetId.asPatchSetId(); this.path = path; @@ -123,6 +128,7 @@ public class Header extends Composite { SafeHtml.setInnerHTML(filePath, formatPath(path)); up.setTargetHistoryToken( PageLinks.toChange( + project, patchSetId.asPatchSetId().getParentKey(), base.asString(), patchSetId.asPatchSetId().getId())); @@ -158,6 +164,7 @@ public class Header extends Composite { @Override protected void onLoad() { DiffApi.list( + Project.NameKey.asStringOrNull(projectKey), patchSetId, base.asPatchSetId(), new GerritCallback>() { @@ -172,7 +179,7 @@ public class Header extends Composite { }); if (Gerrit.isSignedIn()) { - ChangeApi.revision(patchSetId) + ChangeApi.revision(Project.NameKey.asStringOrNull(projectKey), patchSetId) .view("files") .addParameterTrue("reviewed") .get( @@ -242,7 +249,10 @@ public class Header extends Composite { } private RestApi reviewed() { - return ChangeApi.revision(patchSetId).view("files").id(path).view("reviewed"); + return ChangeApi.revision(Project.NameKey.asStringOrNull(projectKey), patchSetId) + .view("files") + .id(path) + .view("reviewed"); } @UiHandler("preferences") @@ -252,8 +262,8 @@ public class Header extends Composite { private String url(FileInfo info) { return diffScreenType == DiffView.UNIFIED_DIFF - ? Dispatcher.toUnified(base, patchSetId, info.path()) - : Dispatcher.toSideBySide(base, patchSetId, info.path()); + ? Dispatcher.toUnified(projectKey, base, patchSetId, info.path()) + : Dispatcher.toSideBySide(projectKey, base, patchSetId, info.path()); } private KeyCommand setupNav(InlineHyperlink link, char key, String help, FileInfo info) { @@ -279,7 +289,7 @@ public class Header extends Composite { return k; } link.getElement().getStyle().setVisibility(Visibility.HIDDEN); - keys.add(new UpToChangeCommand(patchSetId, 0, key)); + keys.add(new UpToChangeCommand(projectKey, patchSetId, 0, key)); return null; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java index e62a28307d..292773c7da 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PatchSetSelectBox.java @@ -26,9 +26,11 @@ import com.google.gerrit.client.patches.PatchUtil; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.Natives; import com.google.gerrit.client.ui.InlineHyperlink; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.event.dom.client.ClickEvent; @@ -61,17 +63,24 @@ class PatchSetSelectBox extends Composite { @UiField HTMLPanel linkPanel; @UiField BoxStyle style; + @Nullable private final Project.NameKey project; + private final Change.Id changeId; + private DiffScreen parent; private DisplaySide side; private boolean sideA; private String path; - private Change.Id changeId; private PatchSet.Id revision; private DiffObject idActive; private PatchSetSelectBox other; PatchSetSelectBox( - DiffScreen parent, DisplaySide side, Change.Id changeId, DiffObject diffObject, String path) { + DiffScreen parent, + DisplaySide side, + @Nullable Project.NameKey project, + Change.Id changeId, + DiffObject diffObject, + String path) { initWidget(uiBinder.createAndBindUi(this)); icon.setTitle(PatchUtil.C.addFileCommentToolTip()); icon.addStyleName(Gerrit.RESOURCES.css().link()); @@ -79,6 +88,7 @@ class PatchSetSelectBox extends Composite { this.parent = parent; this.side = side; this.sideA = side == DisplaySide.A; + this.project = project; this.changeId = changeId; this.revision = diffObject.asPatchSetId(); this.idActive = diffObject; @@ -157,7 +167,7 @@ class PatchSetSelectBox extends Composite { if (cm.extras().getBlameInfo() != null) { cm.extras().toggleAnnotation(); } else { - ChangeApi.blame(rev, path, isBase) + ChangeApi.blame(Project.NameKey.asStringOrNull(project), rev, path, isBase) .get( new GerritCallback>() { @@ -179,7 +189,7 @@ class PatchSetSelectBox extends Composite { Anchor anchor = new Anchor( new ImageResourceRenderer().render(Gerrit.RESOURCES.edit()), - "#" + Dispatcher.toEditScreen(id, path)); + "#" + Dispatcher.toEditScreen(project, id, path)); anchor.setTitle(PatchUtil.C.edit()); return anchor; } @@ -206,8 +216,8 @@ class PatchSetSelectBox extends Composite { return new InlineHyperlink( label, parent.isSideBySide() - ? Dispatcher.toSideBySide(diffBase, revision.asPatchSetId(), path) - : Dispatcher.toUnified(diffBase, revision.asPatchSetId(), path)); + ? Dispatcher.toSideBySide(project, diffBase, revision.asPatchSetId(), path) + : Dispatcher.toUnified(project, diffBase, revision.asPatchSetId(), path)); } private Anchor createDownloadLink() { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java index ce69802731..1ddf895125 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/PublishedBox.java @@ -26,7 +26,9 @@ import com.google.gerrit.client.changes.Util; import com.google.gerrit.client.patches.PatchUtil; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; @@ -52,6 +54,7 @@ class PublishedBox extends CommentBox { } private final PatchSet.Id psId; + @Nullable private final Project.NameKey project; private final CommentInfo comment; private final DisplaySide displaySide; private DraftBox replyBox; @@ -73,6 +76,7 @@ class PublishedBox extends CommentBox { PublishedBox( CommentGroup group, CommentLinkProcessor clp, + @Nullable Project.NameKey project, PatchSet.Id psId, CommentInfo info, DisplaySide displaySide, @@ -80,6 +84,7 @@ class PublishedBox extends CommentBox { super(group, info.range()); this.psId = psId; + this.project = project; this.comment = info; this.displaySide = displaySide; @@ -194,6 +199,7 @@ class PublishedBox extends CommentBox { CommentInfo input = CommentInfo.createReply(comment); input.message(PatchUtil.C.cannedReplyDone()); CommentApi.createDraft( + Project.NameKey.asStringOrNull(project), psId, input, new GerritCallback() { @@ -213,7 +219,7 @@ class PublishedBox extends CommentBox { @UiHandler("fix") void onFix(ClickEvent e) { e.stopPropagation(); - String t = Dispatcher.toEditScreen(psId, comment.path(), comment.line()); + String t = Dispatcher.toEditScreen(project, psId, comment.path(), comment.line()); if (!Gerrit.isSignedIn()) { Gerrit.doSignIn(t); } else { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java index b7f5948954..d052323037 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySide.java @@ -24,8 +24,10 @@ import com.google.gerrit.client.patches.PatchUtil; import com.google.gerrit.client.projects.ConfigInfoCache; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.InlineHyperlink; +import com.google.gerrit.common.Nullable; import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView; import com.google.gerrit.reviewdb.client.Patch; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; @@ -68,8 +70,13 @@ public class SideBySide extends DiffScreen { private SideBySideCommentManager commentManager; public SideBySide( - DiffObject base, DiffObject revision, String path, DisplaySide startSide, int startLine) { - super(base, revision, path, startSide, startLine, DiffView.SIDE_BY_SIDE); + @Nullable Project.NameKey project, + DiffObject base, + DiffObject revision, + String path, + DisplaySide startSide, + int startLine) { + super(project, base, revision, path, startSide, startLine, DiffView.SIDE_BY_SIDE); diffTable = new SideBySideTable(this, base, revision, path); add(uiBinder.createAndBindUi(this)); @@ -85,6 +92,7 @@ public class SideBySide extends DiffScreen { commentManager = new SideBySideCommentManager( SideBySide.this, + getProject(), base, revision, path, @@ -231,7 +239,8 @@ public class SideBySide extends DiffScreen { private List getUnifiedDiffLink() { InlineHyperlink toUnifiedDiffLink = new InlineHyperlink(); toUnifiedDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff())); - toUnifiedDiffLink.setTargetHistoryToken(Dispatcher.toUnified(base, revision, path)); + toUnifiedDiffLink.setTargetHistoryToken( + Dispatcher.toUnified(getProject(), base, revision, path)); toUnifiedDiffLink.setTitle(PatchUtil.C.unifiedDiff()); return Collections.singletonList(toUnifiedDiffLink); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java index 7503711da1..09c5b072b3 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SideBySideCommentManager.java @@ -18,7 +18,9 @@ import com.google.gerrit.client.DiffObject; import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.changes.CommentInfo; import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import java.util.Collection; import java.util.Map; import java.util.SortedMap; @@ -29,12 +31,13 @@ import net.codemirror.lib.TextMarker.FromTo; class SideBySideCommentManager extends CommentManager { SideBySideCommentManager( SideBySide host, + @Nullable Project.NameKey project, DiffObject base, PatchSet.Id revision, String path, CommentLinkProcessor clp, boolean open) { - super(host, base, revision, path, clp, open); + super(host, project, base, revision, path, clp, open); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java index 8647d68ae0..7bd980415e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/Unified.java @@ -24,8 +24,10 @@ import com.google.gerrit.client.patches.PatchUtil; import com.google.gerrit.client.projects.ConfigInfoCache; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.InlineHyperlink; +import com.google.gerrit.common.Nullable; import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView; import com.google.gerrit.reviewdb.client.Patch; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayString; @@ -67,8 +69,13 @@ public class Unified extends DiffScreen { private boolean autoHideDiffTableHeader; public Unified( - DiffObject base, DiffObject revision, String path, DisplaySide startSide, int startLine) { - super(base, revision, path, startSide, startLine, DiffView.UNIFIED_DIFF); + @Nullable Project.NameKey project, + DiffObject base, + DiffObject revision, + String path, + DisplaySide startSide, + int startLine) { + super(project, base, revision, path, startSide, startLine, DiffView.UNIFIED_DIFF); diffTable = new UnifiedTable(this, base, revision, path); add(uiBinder.createAndBindUi(this)); @@ -84,6 +91,7 @@ public class Unified extends DiffScreen { commentManager = new UnifiedCommentManager( Unified.this, + getProject(), base, revision, path, @@ -202,7 +210,8 @@ public class Unified extends DiffScreen { InlineHyperlink toSideBySideDiffLink = new InlineHyperlink(); toSideBySideDiffLink.setHTML( new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff())); - toSideBySideDiffLink.setTargetHistoryToken(Dispatcher.toSideBySide(base, revision, path)); + toSideBySideDiffLink.setTargetHistoryToken( + Dispatcher.toSideBySide(getProject(), base, revision, path)); toSideBySideDiffLink.setTitle(PatchUtil.C.sideBySideDiff()); return Collections.singletonList(toSideBySideDiffLink); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java index 1d9b55afc9..c92075ff89 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UnifiedCommentManager.java @@ -21,7 +21,9 @@ import com.google.gerrit.client.diff.LineMapper.LineOnOtherInfo; import com.google.gerrit.client.diff.UnifiedChunkManager.LineRegionInfo; import com.google.gerrit.client.diff.UnifiedChunkManager.RegionType; import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -43,12 +45,13 @@ class UnifiedCommentManager extends CommentManager { UnifiedCommentManager( Unified host, + @Nullable Project.NameKey project, DiffObject base, PatchSet.Id revision, String path, CommentLinkProcessor clp, boolean open) { - super(host, base, revision, path, clp, open); + super(host, project, base, revision, path, clp, open); mergedMap = new TreeMap<>(); duplicates = new HashMap<>(); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java index df9bcf9a9f..50ef0d71a2 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/UpToChangeCommand.java @@ -16,21 +16,25 @@ package com.google.gerrit.client.diff; import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.patches.PatchUtil; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwtexpui.globalkey.client.KeyCommand; class UpToChangeCommand extends KeyCommand { private final PatchSet.Id revision; + @Nullable private final Project.NameKey project; - UpToChangeCommand(PatchSet.Id revision, int mask, int key) { + UpToChangeCommand(@Nullable Project.NameKey project, PatchSet.Id revision, int mask, int key) { super(mask, key, PatchUtil.C.upToChange()); this.revision = revision; + this.project = project; } @Override public void onKeyPress(KeyPressEvent event) { - Gerrit.display(PageLinks.toChange(revision.getParentKey(), revision.getId())); + Gerrit.display(PageLinks.toChange(project, revision.getParentKey(), revision.getId())); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java index af997c13d5..cbf12a3407 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java @@ -41,11 +41,13 @@ import com.google.gerrit.client.rpc.RestApi; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.Screen; +import com.google.gerrit.common.Nullable; import com.google.gerrit.common.PageLinks; import com.google.gerrit.extensions.client.KeyMapType; import com.google.gerrit.extensions.client.Theme; import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.Scheduler; @@ -99,6 +101,7 @@ public class EditScreen extends Screen { String hideBase(); } + @Nullable private Project.NameKey projectKey; private final PatchSet.Id revision; private final String path; private final int startLine; @@ -129,7 +132,8 @@ public class EditScreen extends Screen { private HandlerRegistration closeHandler; private int generation; - public EditScreen(Patch.Key patch, int startLine) { + public EditScreen(@Nullable Project.NameKey projectKey, Patch.Key patch, int startLine) { + this.projectKey = projectKey; this.revision = patch.getParentKey(); this.path = patch.get(); this.startLine = startLine - 1; @@ -187,11 +191,13 @@ public class EditScreen extends Screen { })); ChangeApi.detail( + Project.NameKey.asStringOrNull(projectKey), revision.getParentKey().get(), group1.add( new AsyncCallback() { @Override public void onSuccess(ChangeInfo c) { + projectKey = c.projectNameKey(); project.setInnerText(c.project()); SafeHtml.setInnerHTML(filePath, Header.formatPath(path)); } @@ -202,6 +208,7 @@ public class EditScreen extends Screen { if (revision.get() == 0) { ChangeEditApi.getMeta( + Project.NameKey.asStringOrNull(projectKey), revision, path, group1.add( @@ -217,6 +224,7 @@ public class EditScreen extends Screen { if (prefs.showBase()) { ChangeEditApi.get( + projectKey, revision, path, true /* base */, @@ -237,7 +245,7 @@ public class EditScreen extends Screen { } else { // TODO(davido): We probably want to create dedicated GET EditScreenMeta // REST endpoint. Abuse GET diff for now, as it retrieves links we need. - DiffApi.diff(revision, path) + DiffApi.diff(Project.NameKey.asStringOrNull(projectKey), revision, path) .webLinksOnly() .get( group1.addFinal( @@ -253,6 +261,7 @@ public class EditScreen extends Screen { } ChangeEditApi.get( + projectKey, revision, path, group2.add( @@ -427,6 +436,7 @@ public class EditScreen extends Screen { if (shouldShow) { if (baseContent == null) { ChangeEditApi.get( + projectKey, revision, path, true /* base */, @@ -529,7 +539,7 @@ public class EditScreen extends Screen { } private void upToChange() { - Gerrit.display(PageLinks.toChangeInEditMode(revision.getParentKey())); + Gerrit.display(PageLinks.toChangeInEditMode(projectKey, revision.getParentKey())); } private void initEditor() { @@ -606,14 +616,14 @@ public class EditScreen extends Screen { InlineHyperlink sbs = new InlineHyperlink(); sbs.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff())); sbs.setTargetHistoryToken( - Dispatcher.toPatch("sidebyside", null, new Patch.Key(revision, path))); + Dispatcher.toPatch(projectKey, "sidebyside", null, new Patch.Key(revision, path))); sbs.setTitle(PatchUtil.C.sideBySideDiff()); linkPanel.add(sbs); InlineHyperlink unified = new InlineHyperlink(); unified.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff())); unified.setTargetHistoryToken( - Dispatcher.toPatch("unified", null, new Patch.Key(revision, path))); + Dispatcher.toPatch(projectKey, "unified", null, new Patch.Key(revision, path))); unified.setTitle(PatchUtil.C.unifiedDiff()); linkPanel.add(unified); } @@ -656,6 +666,7 @@ public class EditScreen extends Screen { } final int g = cmEdit.changeGeneration(false); ChangeEditApi.put( + Project.NameKey.asStringOrNull(projectKey), revision.getParentKey().get(), path, text, diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java index 7e2f2be7b6..7262b3a044 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfoCache.java @@ -122,7 +122,8 @@ public class ConfigInfoCache { getImpl(name, cb); return; } - ChangeApi.change(id) + // TODO(hiesel) Make a preflight request to get project before we deprecate the numeric changeId + ChangeApi.change(null, id) .get( new AsyncCallback() { @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java index 8b0fefb9b7..e2a9ffbe0c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java @@ -179,7 +179,7 @@ public class RestApi { } }; - // Defer handling the response if the parse took a while. + // Defer handling the response if the create took a while. if ((System.currentTimeMillis() - start) > 75) { Scheduler.get().scheduleDeferred(cmd); } else { @@ -258,6 +258,10 @@ public class RestApi { return idRaw(URL.encodePathSegment(id)); } + public RestApi id(String project, int id) { + return idRaw(URL.encodePathSegment(project) + "~" + id); + } + public RestApi id(int id) { return idRaw(Integer.toString(id)); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java index 68477bcb49..b54d752a31 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java @@ -17,6 +17,7 @@ package com.google.gerrit.client.ui; import com.google.gerrit.client.Gerrit; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; import com.google.gwt.core.client.GWT; public class ChangeLink extends InlineHyperlink { @@ -26,8 +27,8 @@ public class ChangeLink extends InlineHyperlink { protected Change.Id cid; - public ChangeLink(String text, Change.Id c) { - super(text, PageLinks.toChange(c)); + public ChangeLink(Project.NameKey project, Change.Id c, String text) { + super(text, PageLinks.toChange(project, c)); getElement().setPropertyString("href", permalink(c)); cid = c; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java index f3dc6c3b64..e03ac4673b 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RebaseDialog.java @@ -42,7 +42,7 @@ public abstract class RebaseDialog extends CommentedActionDialog { private final boolean sendEnabled; public RebaseDialog( - final String project, + final Project.NameKey project, final String branch, final Change.Id changeId, final boolean sendEnabled) { @@ -88,7 +88,7 @@ public abstract class RebaseDialog extends CommentedActionDialog { public void onClick(ClickEvent event) { if (changeParent.getValue()) { ChangeList.query( - PageLinks.projectQuery(new Project.NameKey(project)) + PageLinks.projectQuery(project) + " " + PageLinks.op("branch", branch) + " is:open -age:90d", diff --git a/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java b/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java new file mode 100644 index 0000000000..1d47a82f85 --- /dev/null +++ b/gerrit-gwtui/src/test/java/com/google/gerrit/client/change/ProjectChangeIdTest.java @@ -0,0 +1,86 @@ +// 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.client.change; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.gerrit.common.Nullable; +import com.google.gerrit.reviewdb.client.Change; +import com.google.gerrit.reviewdb.client.Project; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class ProjectChangeIdTest { + + @Rule public ExpectedException exception = ExpectedException.none(); + + @Test + public void emptyStringThrowsException() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage(" is not a valid change identifier"); + ProjectChangeId.create(""); + } + + @Test + public void noChangeIdThrowsException() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("some/path is not a valid change identifier"); + ProjectChangeId.create("some/path"); + } + + @Test + public void noChangeButProjectIdThrowsException() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("some/+/path is not a valid change identifier"); + ProjectChangeId.create("some/+/path"); + } + + @Test + public void project() { + assertThat(ProjectChangeId.create("test/+/123/some/path")).isEqualTo(result("test", 123)); + assertThat(ProjectChangeId.create("test/+/123/some/path/")).isEqualTo(result("test", 123)); + assertThat(ProjectChangeId.create("test/+/123/")).isEqualTo(result("test", 123)); + assertThat(ProjectChangeId.create("test/+/123")).isEqualTo(result("test", 123)); + // Numeric Project.NameKey + assertThat(ProjectChangeId.create("123/+/123")).isEqualTo(result("123", 123)); + // Numeric Project.NameKey with ,edit as part of the name + assertThat(ProjectChangeId.create("123,edit/+/123")).isEqualTo(result("123,edit", 123)); + } + + @Test + public void noProject() { + assertThat(ProjectChangeId.create("123/some/path")).isEqualTo(result(null, 123)); + assertThat(ProjectChangeId.create("123/some/path/")).isEqualTo(result(null, 123)); + assertThat(ProjectChangeId.create("123/")).isEqualTo(result(null, 123)); + assertThat(ProjectChangeId.create("123")).isEqualTo(result(null, 123)); + } + + @Test + public void editSuffix() { + assertThat(ProjectChangeId.create("123,edit/some/path")).isEqualTo(result(null, 123)); + assertThat(ProjectChangeId.create("123,edit/")).isEqualTo(result(null, 123)); + assertThat(ProjectChangeId.create("123,edit")).isEqualTo(result(null, 123)); + + assertThat(ProjectChangeId.create("test/+/123,edit/some/path")).isEqualTo(result("test", 123)); + assertThat(ProjectChangeId.create("test/+/123,edit/")).isEqualTo(result("test", 123)); + assertThat(ProjectChangeId.create("test/+/123,edit")).isEqualTo(result("test", 123)); + } + + private static ProjectChangeId result(@Nullable String project, int id) { + return new ProjectChangeId( + project == null ? null : new Project.NameKey(project), new Change.Id(id)); + } +} 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 be9df4c482..26e41987ab 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 @@ -9,6 +9,7 @@ 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.reviewdb.client.Project; import com.google.inject.Inject; import com.google.inject.Singleton; import java.io.IOException; @@ -45,7 +46,8 @@ class DirectChangeByCommit extends HttpServlet { 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(new Change.Id(results.iterator().next()._number)); + ChangeInfo ci = results.iterator().next(); + token = PageLinks.toChange(new Project.NameKey(ci.project), new Change.Id(ci._number)); } else { // Otherwise, link to the query page. token = PageLinks.toChangeQuery(query); diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java index b388d34782..e705fbdb70 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java @@ -178,7 +178,10 @@ class UrlModule extends ServletModule { idString = idString.substring(0, idString.length() - 1); } Change.Id id = Change.Id.parse(idString); - toGerrit(PageLinks.toChange(id), req, rsp); + // User accessed Gerrit with /1234, so we have no project yet. + // TODO(hiesel) Replace with a preflight request to obtain project before we deprecate + // the numeric change id. + toGerrit(PageLinks.toChange(null, id), req, rsp); } catch (IllegalArgumentException err) { rsp.sendError(HttpServletResponse.SC_NOT_FOUND); } diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java index 4cc868ee10..96d037fa99 100644 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java +++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java @@ -64,6 +64,10 @@ public final class Project { r.fromString(str); return r; } + + public static String asStringOrNull(NameKey key) { + return key == null ? null : key.get(); + } } protected NameKey name;