Modernize URLs to be shorter and consistent
Instead of using http://site/#change,1234 we now use a slightly more common looking http://site/#/c/1234 URL to link to a change. It is also quite a bit shorter than the old format, using up less space in the address bar. Files within a patch set are now denoted below the change, as in http://site/#/c/1234/1/src/module/foo.c making it easier to jump directly to a specific file, or to just see the structure of the current view. Whenever possible the old URLs continue to work by redirecting to the equivalent new URL. We plan to keep the old URLs alive, as many issue tracking systems have direct links based on the old URL format and these links should not be invalidated. This change also fixes the dynamic redirects of http://site/1234 and http://site/r/deadbeef to jump directly to the corresponding change if there is exactly one possible URL. This avoids the ugly interim redirect to http://site/#/q/1234,n,z when the server can compute what the correct location should be on its own. Entities that have multiple views suffix the URL with ",view-name" to indicate which view the user wants to see. For files the default view is the side-by-side view and does not have a suffix, while the unified patch view has a suffix of ",unified", for example: http://site/#/c/1234/1/src/module/foo.c,unified. Project admin panels use a similar view suffix to denote which of the tabs on the left menu is currently open, with the main info tab being the default with no suffix. Change-Id: I2bac7ef1b2638fb08df2659b8373960eadec205a
This commit is contained in:
@@ -24,38 +24,38 @@ import com.google.gerrit.reviewdb.Change.Status;
|
|||||||
import com.google.gwtorm.client.KeyUtil;
|
import com.google.gwtorm.client.KeyUtil;
|
||||||
|
|
||||||
public class PageLinks {
|
public class PageLinks {
|
||||||
public static final String SETTINGS = "settings";
|
public static final String SETTINGS = "/settings/";
|
||||||
public static final String SETTINGS_PREFERENCES = "settings,preferences";
|
public static final String SETTINGS_PREFERENCES = "/settings/preferences";
|
||||||
public static final String SETTINGS_SSHKEYS = "settings,ssh-keys";
|
public static final String SETTINGS_SSHKEYS = "/settings/ssh-keys";
|
||||||
public static final String SETTINGS_HTTP_PASSWORD = "settings,http-password";
|
public static final String SETTINGS_HTTP_PASSWORD = "/settings/http-password";
|
||||||
public static final String SETTINGS_WEBIDENT = "settings,web-identities";
|
public static final String SETTINGS_WEBIDENT = "/settings/web-identities";
|
||||||
public static final String SETTINGS_MYGROUPS = "settings,group-memberships";
|
public static final String SETTINGS_MYGROUPS = "/settings/group-memberships";
|
||||||
public static final String SETTINGS_AGREEMENTS = "settings,agreements";
|
public static final String SETTINGS_AGREEMENTS = "/settings/agreements";
|
||||||
public static final String SETTINGS_CONTACT = "settings,contact";
|
public static final String SETTINGS_CONTACT = "/settings/contact";
|
||||||
public static final String SETTINGS_PROJECTS = "settings,projects";
|
public static final String SETTINGS_PROJECTS = "/settings/projects";
|
||||||
public static final String SETTINGS_NEW_AGREEMENT = "settings,new-agreement";
|
public static final String SETTINGS_NEW_AGREEMENT = "/settings/new-agreement";
|
||||||
public static final String REGISTER = "register";
|
public static final String REGISTER = "/register";
|
||||||
|
|
||||||
public static final String TOP = "n,z";
|
public static final String TOP = "n,z";
|
||||||
|
|
||||||
public static final String MINE = "mine";
|
public static final String MINE = "/";
|
||||||
public static final String ADMIN_GROUPS = "admin,groups";
|
public static final String ADMIN_GROUPS = "/admin/groups/";
|
||||||
public static final String ADMIN_PROJECTS = "admin,projects";
|
public static final String ADMIN_PROJECTS = "/admin/projects/";
|
||||||
|
|
||||||
public static String toChange(final ChangeInfo c) {
|
public static String toChange(final ChangeInfo c) {
|
||||||
return toChange(c.getId());
|
return toChange(c.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toChange(final Change.Id c) {
|
public static String toChange(final Change.Id c) {
|
||||||
return "change," + c.toString();
|
return "/c/" + c + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toChange(final PatchSet.Id ps) {
|
public static String toChange(final PatchSet.Id ps) {
|
||||||
return "change," + ps.getParentKey().toString() + ",patchset=" + ps.get();
|
return "/c/" + ps.getParentKey() + "/" + ps.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toProjectAcceess(final Project.NameKey p) {
|
public static String toProjectAcceess(final Project.NameKey p) {
|
||||||
return "admin,project," + p.get() + ",access";
|
return "/admin/projects/" + p.get() + ",access";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toAccountDashboard(final AccountInfo acct) {
|
public static String toAccountDashboard(final AccountInfo acct) {
|
||||||
@@ -63,11 +63,16 @@ public class PageLinks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String toAccountDashboard(final Account.Id acct) {
|
public static String toAccountDashboard(final Account.Id acct) {
|
||||||
return "dashboard," + acct.toString();
|
return "/dashboard/" + acct.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toChangeQuery(final String query) {
|
public static String toChangeQuery(final String query) {
|
||||||
return "q," + KeyUtil.encode(query) + "," + TOP;
|
return toChangeQuery(query, TOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toChangeQuery(String query, String page) {
|
||||||
|
query = KeyUtil.encode(query).replaceAll("%3[Aa]", ":");
|
||||||
|
return "/q/" + query + "," + page;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String projectQuery(Project.NameKey proj, Status status) {
|
public static String projectQuery(Project.NameKey proj, Status status) {
|
||||||
|
@@ -58,6 +58,7 @@ import com.google.gerrit.client.changes.PublishCommentScreen;
|
|||||||
import com.google.gerrit.client.changes.QueryScreen;
|
import com.google.gerrit.client.changes.QueryScreen;
|
||||||
import com.google.gerrit.client.patches.PatchScreen;
|
import com.google.gerrit.client.patches.PatchScreen;
|
||||||
import com.google.gerrit.client.ui.Screen;
|
import com.google.gerrit.client.ui.Screen;
|
||||||
|
import com.google.gerrit.common.PageLinks;
|
||||||
import com.google.gerrit.common.auth.SignInMode;
|
import com.google.gerrit.common.auth.SignInMode;
|
||||||
import com.google.gerrit.common.data.PatchSetDetail;
|
import com.google.gerrit.common.data.PatchSetDetail;
|
||||||
import com.google.gerrit.reviewdb.Account;
|
import com.google.gerrit.reviewdb.Account;
|
||||||
@@ -68,19 +69,25 @@ import com.google.gerrit.reviewdb.PatchSet;
|
|||||||
import com.google.gerrit.reviewdb.Project;
|
import com.google.gerrit.reviewdb.Project;
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.core.client.RunAsyncCallback;
|
import com.google.gwt.core.client.RunAsyncCallback;
|
||||||
|
import com.google.gwt.user.client.Window;
|
||||||
import com.google.gwtorm.client.KeyUtil;
|
import com.google.gwtorm.client.KeyUtil;
|
||||||
|
|
||||||
public class Dispatcher {
|
public class Dispatcher {
|
||||||
public static String toPatchSideBySide(final Patch.Key id) {
|
public static String toPatchSideBySide(final Patch.Key id) {
|
||||||
return toPatch("sidebyside", id);
|
return toPatch("", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toPatchUnified(final Patch.Key id) {
|
public static String toPatchUnified(final Patch.Key id) {
|
||||||
return toPatch("unified", id);
|
return toPatch("unified", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toPatch(final String type, final Patch.Key id) {
|
private static String toPatch(String type, final Patch.Key id) {
|
||||||
return "patch," + type + "," + id.toString();
|
PatchSet.Id ps = id.getParentKey();
|
||||||
|
Change.Id c = ps.getParentKey();
|
||||||
|
if (type != null && !type.isEmpty()) {
|
||||||
|
type = "," + type;
|
||||||
|
}
|
||||||
|
return "/c/" + c + "/" + ps.get() + "/" + KeyUtil.encode(id.get()) + type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toPatch(final PatchScreen.Type type, final Patch.Key id) {
|
public static String toPatch(final PatchScreen.Type type, final Patch.Key id) {
|
||||||
@@ -91,28 +98,36 @@ public class Dispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String toPublish(PatchSet.Id ps) {
|
||||||
|
Change.Id c = ps.getParentKey();
|
||||||
|
return "/c/" + c + "/" + ps.get() + ",publish";
|
||||||
|
}
|
||||||
|
|
||||||
public static String toAccountGroup(final AccountGroup.Id id) {
|
public static String toAccountGroup(final AccountGroup.Id id) {
|
||||||
return "admin,group," + id.toString();
|
return "/admin/groups/" + id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toGroup(final AccountGroup.UUID uuid) {
|
public static String toGroup(final AccountGroup.UUID uuid) {
|
||||||
return "admin,group,uuid-" + uuid.toString();
|
return "/admin/groups/uuid-" + uuid.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toProjectAdmin(final Project.NameKey n, final String tab) {
|
public static String toProjectAdmin(Project.NameKey n, String panel) {
|
||||||
return "admin,project," + n.toString() + "," + tab;
|
if (ProjectScreen.INFO.equals(panel)) {
|
||||||
|
return "/admin/projects/" + n.toString();
|
||||||
|
}
|
||||||
|
return "/admin/projects/" + n.toString() + "," + panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String RELOAD_UI = "reload-ui,";
|
static final String RELOAD_UI = "/reload-ui/";
|
||||||
private static boolean wasStartedByReloadUI;
|
private static boolean wasStartedByReloadUI;
|
||||||
|
|
||||||
void display(String token) {
|
void display(String token) {
|
||||||
assert token != null;
|
assert token != null;
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if (token.startsWith(RELOAD_UI)) {
|
if (matchPrefix(RELOAD_UI, token)) {
|
||||||
wasStartedByReloadUI = true;
|
wasStartedByReloadUI = true;
|
||||||
token = skip(RELOAD_UI, token);
|
token = skip(token);
|
||||||
}
|
}
|
||||||
select(token);
|
select(token);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -125,160 +140,262 @@ public class Dispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void select(final String token) {
|
private static void select(final String token) {
|
||||||
if (token.startsWith("patch,")) {
|
if (matchPrefix("/q/", token)) {
|
||||||
patch(token, null, 0, null, null);
|
query(token);
|
||||||
|
|
||||||
} else if (token.startsWith("change,publish,")) {
|
} else if (matchPrefix("/c/", token)) {
|
||||||
publish(token);
|
change(token);
|
||||||
|
|
||||||
} else if (MINE.equals(token) || token.startsWith("mine,")) {
|
} else if (matchExact(MINE, token)) {
|
||||||
Gerrit.display(token, mine(token));
|
Gerrit.display(token, mine(token));
|
||||||
|
|
||||||
} else if (token.startsWith("all,")) {
|
} else if (matchPrefix("/dashboard/", token)) {
|
||||||
Gerrit.display(token, all(token));
|
dashboard(token);
|
||||||
|
|
||||||
} else if (token.startsWith("project,")) {
|
} else if (matchExact(SETTINGS, token) //
|
||||||
Gerrit.display(token, project(token));
|
|| matchPrefix("/settings/", token) //
|
||||||
|
|| matchExact("register", token) //
|
||||||
} else if (SETTINGS.equals(token) //
|
|| matchExact(REGISTER, token) //
|
||||||
|| REGISTER.equals(token) //
|
|| matchPrefix("/register/", token) //
|
||||||
|| token.startsWith("settings,") //
|
|| matchPrefix("/VE/", token) || matchPrefix("VE,", token) //
|
||||||
|| token.startsWith("register,") //
|
|| matchPrefix("/SignInFailure,", token)) {
|
||||||
|| token.startsWith("VE,") //
|
|
||||||
|| token.startsWith("SignInFailure,")) {
|
|
||||||
settings(token);
|
settings(token);
|
||||||
|
|
||||||
} else if (token.startsWith("admin,")) {
|
} else if (matchPrefix("/admin/", token)) {
|
||||||
admin(token);
|
admin(token);
|
||||||
|
|
||||||
} else {
|
} else if (/* LEGACY URL */matchPrefix("all,", token)) {
|
||||||
Gerrit.display(token, core(token));
|
redirectFromLegacyToken(token, legacyAll(token));
|
||||||
}
|
} else if (/* LEGACY URL */matchPrefix("mine,", token)
|
||||||
}
|
|| matchExact("mine", token)) {
|
||||||
|
redirectFromLegacyToken(token, legacyMine(token));
|
||||||
private static Screen mine(final String token) {
|
} else if (/* LEGACY URL */matchPrefix("project,", token)) {
|
||||||
if (MINE.equals(token)) {
|
redirectFromLegacyToken(token, legacyProject(token));
|
||||||
if (Gerrit.isSignedIn()) {
|
} else if (/* LEGACY URL */matchPrefix("change,", token)) {
|
||||||
return new AccountDashboardScreen(Gerrit.getUserAccount().getId());
|
redirectFromLegacyToken(token, legacyChange(token));
|
||||||
|
} else if (/* LEGACY URL */matchPrefix("patch,", token)) {
|
||||||
} else {
|
redirectFromLegacyToken(token, legacyPatch(token));
|
||||||
final Screen r = new AccountDashboardScreen(null);
|
} else if (/* LEGACY URL */matchPrefix("admin,", token)) {
|
||||||
r.setRequiresSignIn(true);
|
redirectFromLegacyToken(token, legacyAdmin(token));
|
||||||
return r;
|
} else if (/* LEGACY URL */matchPrefix("settings,", token)
|
||||||
}
|
|| matchPrefix("register,", token)) {
|
||||||
|
redirectFromLegacyToken(token, legacySettings(token));
|
||||||
} else if ("mine,starred".equals(token)) {
|
|
||||||
return QueryScreen.forQuery("is:starred");
|
|
||||||
|
|
||||||
} else if ("mine,drafts".equals(token)) {
|
|
||||||
return QueryScreen.forQuery("has:draft");
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
String p = "mine,watched,";
|
Gerrit.display(token, new NotFoundScreen());
|
||||||
if (token.startsWith(p)) {
|
|
||||||
return QueryScreen.forQuery("is:watched status:open", skip(p, token));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NotFoundScreen();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Screen all(final String token) {
|
private static void redirectFromLegacyToken(String oldToken, String newToken) {
|
||||||
String p;
|
if (newToken != null) {
|
||||||
|
Window.Location.replace(Window.Location.getPath() + "#" + newToken);
|
||||||
p = "all,abandoned,";
|
} else {
|
||||||
if (token.startsWith(p)) {
|
Gerrit.display(oldToken, new NotFoundScreen());
|
||||||
return QueryScreen.forQuery("status:abandoned", skip(p, token));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "all,merged,";
|
|
||||||
if (token.startsWith(p)) {
|
|
||||||
return QueryScreen.forQuery("status:merged", skip(p, token));
|
|
||||||
}
|
|
||||||
|
|
||||||
p = "all,open,";
|
|
||||||
if (token.startsWith(p)) {
|
|
||||||
return QueryScreen.forQuery("status:open", skip(p, token));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NotFoundScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Screen project(final String token) {
|
private static String legacyMine(final String token) {
|
||||||
String p;
|
if (matchExact("mine", token)) {
|
||||||
|
return MINE;
|
||||||
|
}
|
||||||
|
|
||||||
p = "project,open,";
|
if (matchExact("mine,starred", token)) {
|
||||||
if (token.startsWith(p)) {
|
return PageLinks.toChangeQuery("is:starred");
|
||||||
final String s = skip(p, token);
|
}
|
||||||
|
|
||||||
|
if (matchExact("mine,drafts", token)) {
|
||||||
|
return PageLinks.toChangeQuery("has:draft");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchPrefix("mine,watched,", token)) {
|
||||||
|
return PageLinks.toChangeQuery("is:watched status:open", skip(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String legacyAll(final String token) {
|
||||||
|
if (matchPrefix("all,abandoned,", token)) {
|
||||||
|
return PageLinks.toChangeQuery("status:abandoned", skip(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchPrefix("all,merged,", token)) {
|
||||||
|
return PageLinks.toChangeQuery("status:merged", skip(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchPrefix("all,open,", token)) {
|
||||||
|
return PageLinks.toChangeQuery("status:open", skip(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String legacyProject(final String token) {
|
||||||
|
if (matchPrefix("project,open,", token)) {
|
||||||
|
final String s = skip(token);
|
||||||
final int c = s.indexOf(',');
|
final int c = s.indexOf(',');
|
||||||
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
||||||
return QueryScreen.forQuery( //
|
return PageLinks.toChangeQuery( //
|
||||||
"status:open " + op("project", proj.get()), //
|
"status:open " + op("project", proj.get()), //
|
||||||
s.substring(c + 1));
|
s.substring(c + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "project,merged,";
|
if (matchPrefix("project,merged,", token)) {
|
||||||
if (token.startsWith(p)) {
|
final String s = skip(token);
|
||||||
final String s = skip(p, token);
|
|
||||||
final int c = s.indexOf(',');
|
final int c = s.indexOf(',');
|
||||||
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
||||||
return QueryScreen.forQuery( //
|
return PageLinks.toChangeQuery( //
|
||||||
"status:merged " + op("project", proj.get()), //
|
"status:merged " + op("project", proj.get()), //
|
||||||
s.substring(c + 1));
|
s.substring(c + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "project,abandoned,";
|
if (matchPrefix("project,abandoned,", token)) {
|
||||||
if (token.startsWith(p)) {
|
final String s = skip(token);
|
||||||
final String s = skip(p, token);
|
|
||||||
final int c = s.indexOf(',');
|
final int c = s.indexOf(',');
|
||||||
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
Project.NameKey proj = Project.NameKey.parse(s.substring(0, c));
|
||||||
return QueryScreen.forQuery( //
|
return PageLinks.toChangeQuery( //
|
||||||
"status:abandoned " + op("project", proj.get()), //
|
"status:abandoned " + op("project", proj.get()), //
|
||||||
s.substring(c + 1));
|
s.substring(c + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotFoundScreen();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Screen core(final String token) {
|
private static String legacyChange(final String token) {
|
||||||
String p;
|
final String s = skip(token);
|
||||||
|
final String q = "patchset=";
|
||||||
|
final String t[] = s.split(",", 2);
|
||||||
|
if (t.length > 1 && matchPrefix("patchset=", t[1])) {
|
||||||
|
return PageLinks.toChange(PatchSet.Id.parse(t[0] + "," + skip(t[1])));
|
||||||
|
}
|
||||||
|
return PageLinks.toChange(Change.Id.parse(t[0]));
|
||||||
|
}
|
||||||
|
|
||||||
p = "change,";
|
private static String legacyPatch(String token) {
|
||||||
if (token.startsWith(p)) {
|
if (/* LEGACY URL */matchPrefix("patch,sidebyside,", token)) {
|
||||||
final String s = skip(p, token);
|
return toPatchSideBySide(Patch.Key.parse(skip(token)));
|
||||||
final String q = "patchset=";
|
}
|
||||||
final String t[] = s.split(",", 2);
|
|
||||||
if (t.length > 1 && t[1].startsWith(q)) {
|
if (/* LEGACY URL */matchPrefix("patch,unified,", token)) {
|
||||||
return new ChangeScreen(PatchSet.Id.parse(t[0] + "," + skip(q, t[1])));
|
return toPatchUnified(Patch.Key.parse(skip(token)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String legacyAdmin(String token) {
|
||||||
|
if (matchPrefix("admin,group,", token)) {
|
||||||
|
return "/admin/groups/" + skip(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchPrefix("admin,project,", token)) {
|
||||||
|
String rest = skip(token);
|
||||||
|
int c = rest.indexOf(',');
|
||||||
|
String panel;
|
||||||
|
Project.NameKey k;
|
||||||
|
if (0 < c) {
|
||||||
|
panel = rest.substring(c + 1);
|
||||||
|
k = Project.NameKey.parse(rest.substring(0, c));
|
||||||
|
} else {
|
||||||
|
panel = ProjectScreen.INFO;
|
||||||
|
k = Project.NameKey.parse(rest);
|
||||||
}
|
}
|
||||||
return new ChangeScreen(Change.Id.parse(t[0]));
|
return toProjectAdmin(k, panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "dashboard,";
|
return null;
|
||||||
if (token.startsWith(p))
|
|
||||||
return new AccountDashboardScreen(Account.Id.parse(skip(p, token)));
|
|
||||||
|
|
||||||
p = "q,";
|
|
||||||
if (token.startsWith(p)) {
|
|
||||||
final String s = skip(p, token);
|
|
||||||
final int c = s.indexOf(',');
|
|
||||||
return new QueryScreen(s.substring(0, c), s.substring(c + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NotFoundScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void publish(String token) {
|
private static String legacySettings(String token) {
|
||||||
|
int c = token.indexOf(',');
|
||||||
|
if (0 < c) {
|
||||||
|
return "/" + token.substring(0, c) + "/" + token.substring(c + 1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void query(final String token) {
|
||||||
|
final String s = skip(token);
|
||||||
|
final int c = s.indexOf(',');
|
||||||
|
Gerrit.display(token, new QueryScreen(s.substring(0, c), s.substring(c + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Screen mine(final String token) {
|
||||||
|
if (Gerrit.isSignedIn()) {
|
||||||
|
return new AccountDashboardScreen(Gerrit.getUserAccount().getId());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Screen r = new AccountDashboardScreen(null);
|
||||||
|
r.setRequiresSignIn(true);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void dashboard(final String token) {
|
||||||
|
Gerrit.display(token, //
|
||||||
|
new AccountDashboardScreen(Account.Id.parse(skip(token))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void change(final String token) {
|
||||||
|
String rest = skip(token);
|
||||||
|
int c = rest.lastIndexOf(',');
|
||||||
|
String panel = null;
|
||||||
|
if (0 <= c) {
|
||||||
|
panel = rest.substring(c + 1);
|
||||||
|
rest = rest.substring(0, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rest.isEmpty()) {
|
||||||
|
Gerrit.display(token, panel== null //
|
||||||
|
? new ChangeScreen(id) //
|
||||||
|
: new NotFoundScreen());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String psIdStr;
|
||||||
|
s = rest.indexOf('/');
|
||||||
|
if (0 <= s) {
|
||||||
|
psIdStr = rest.substring(0, s);
|
||||||
|
rest = rest.substring(s + 1);
|
||||||
|
} else {
|
||||||
|
psIdStr = rest;
|
||||||
|
rest = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
PatchSet.Id ps = new PatchSet.Id(id, Integer.parseInt(psIdStr));
|
||||||
|
if (!rest.isEmpty()) {
|
||||||
|
Patch.Key p = new Patch.Key(ps, rest);
|
||||||
|
patch(token, p, 0, null, null, panel);
|
||||||
|
} else {
|
||||||
|
if (panel == null) {
|
||||||
|
Gerrit.display(token, new ChangeScreen(ps));
|
||||||
|
} else if ("publish".equals(panel)) {
|
||||||
|
publish(ps);
|
||||||
|
} else {
|
||||||
|
Gerrit.display(token, new NotFoundScreen());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void publish(final PatchSet.Id ps) {
|
||||||
|
String token = toPublish(ps);
|
||||||
new AsyncSplit(token) {
|
new AsyncSplit(token) {
|
||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
Gerrit.display(token, select());
|
Gerrit.display(token, select());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Screen select() {
|
private Screen select() {
|
||||||
String p = "change,publish,";
|
return new PublishCommentScreen(ps);
|
||||||
if (token.startsWith(p))
|
|
||||||
return new PublishCommentScreen(PatchSet.Id.parse(skip(p, token)));
|
|
||||||
return new NotFoundScreen();
|
|
||||||
}
|
}
|
||||||
}.onSuccess();
|
}.onSuccess();
|
||||||
}
|
}
|
||||||
@@ -286,32 +403,41 @@ public class Dispatcher {
|
|||||||
public static void patch(String token, final Patch.Key id,
|
public static void patch(String token, final Patch.Key id,
|
||||||
final int patchIndex, final PatchSetDetail patchSetDetail,
|
final int patchIndex, final PatchSetDetail patchSetDetail,
|
||||||
final PatchTable patchTable) {
|
final PatchTable patchTable) {
|
||||||
|
patch(token, id, patchIndex, patchSetDetail, patchTable, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void patch(String token, final Patch.Key id,
|
||||||
|
final int patchIndex, final PatchSetDetail patchSetDetail,
|
||||||
|
final PatchTable patchTable,
|
||||||
|
final String panelType) {
|
||||||
GWT.runAsync(new AsyncSplit(token) {
|
GWT.runAsync(new AsyncSplit(token) {
|
||||||
public void onSuccess() {
|
public void onSuccess() {
|
||||||
Gerrit.display(token, select());
|
Gerrit.display(token, select());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Screen select() {
|
private Screen select() {
|
||||||
String p;
|
if (id != null) {
|
||||||
|
String panel = panelType;
|
||||||
|
if (panel == null) {
|
||||||
|
int c = token.lastIndexOf(',');
|
||||||
|
panel = 0 <= c ? token.substring(c + 1) : "";
|
||||||
|
}
|
||||||
|
|
||||||
p = "patch,sidebyside,";
|
if ("".equals(panel)) {
|
||||||
if (token.startsWith(p)) {
|
return new PatchScreen.SideBySide( //
|
||||||
return new PatchScreen.SideBySide( //
|
id, //
|
||||||
id != null ? id : Patch.Key.parse(skip(p, token)), //
|
patchIndex, //
|
||||||
patchIndex, //
|
patchSetDetail, //
|
||||||
patchSetDetail, //
|
patchTable //
|
||||||
patchTable //
|
);
|
||||||
);
|
} else if ("unified".equals(panel)) {
|
||||||
}
|
return new PatchScreen.Unified( //
|
||||||
|
id, //
|
||||||
p = "patch,unified,";
|
patchIndex, //
|
||||||
if (token.startsWith(p)) {
|
patchSetDetail, //
|
||||||
return new PatchScreen.Unified( //
|
patchTable //
|
||||||
id != null ? id : Patch.Key.parse(skip(p, token)), //
|
);
|
||||||
patchIndex, //
|
}
|
||||||
patchSetDetail, //
|
|
||||||
patchTable //
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotFoundScreen();
|
return new NotFoundScreen();
|
||||||
@@ -326,59 +452,56 @@ public class Dispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Screen select() {
|
private Screen select() {
|
||||||
String p;
|
if (matchExact(SETTINGS, token)) {
|
||||||
|
|
||||||
if (token.equals(SETTINGS)) {
|
|
||||||
return new MyProfileScreen();
|
return new MyProfileScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_PREFERENCES)) {
|
if (matchExact(SETTINGS_PREFERENCES, token)) {
|
||||||
return new MyPreferencesScreen();
|
return new MyPreferencesScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_PROJECTS)) {
|
if (matchExact(SETTINGS_PROJECTS, token)) {
|
||||||
return new MyWatchedProjectsScreen();
|
return new MyWatchedProjectsScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_CONTACT)) {
|
if (matchExact(SETTINGS_CONTACT, token)) {
|
||||||
return new MyContactInformationScreen();
|
return new MyContactInformationScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_SSHKEYS)) {
|
if (matchExact(SETTINGS_SSHKEYS, token)) {
|
||||||
return new MySshKeysScreen();
|
return new MySshKeysScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_WEBIDENT)) {
|
if (matchExact(SETTINGS_WEBIDENT, token)) {
|
||||||
return new MyIdentitiesScreen();
|
return new MyIdentitiesScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_HTTP_PASSWORD)) {
|
if (matchExact(SETTINGS_HTTP_PASSWORD, token)) {
|
||||||
return new MyPasswordScreen();
|
return new MyPasswordScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_MYGROUPS)) {
|
if (matchExact(SETTINGS_MYGROUPS, token)) {
|
||||||
return new MyGroupsScreen();
|
return new MyGroupsScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.equals(SETTINGS_AGREEMENTS)
|
if (matchExact(SETTINGS_AGREEMENTS, token)
|
||||||
&& Gerrit.getConfig().isUseContributorAgreements()) {
|
&& Gerrit.getConfig().isUseContributorAgreements()) {
|
||||||
return new MyAgreementsScreen();
|
return new MyAgreementsScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "register,";
|
if (matchExact(REGISTER, token)
|
||||||
if (token.startsWith(p)) {
|
|| matchExact("/register/", token)
|
||||||
return new RegisterScreen(skip(p, token));
|
|| matchExact("register", token)) {
|
||||||
} else if (REGISTER.equals(token)) {
|
|
||||||
return new RegisterScreen(MINE);
|
return new RegisterScreen(MINE);
|
||||||
|
} else if (matchPrefix("/register/", token)) {
|
||||||
|
return new RegisterScreen("/" + skip(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
p = "VE,";
|
if (matchPrefix("/VE/", token) || matchPrefix("VE,", token))
|
||||||
if (token.startsWith(p))
|
return new ValidateEmailScreen(skip(token));
|
||||||
return new ValidateEmailScreen(skip(p, token));
|
|
||||||
|
|
||||||
p = "SignInFailure,";
|
if (matchPrefix("/SignInFailure,", token)) {
|
||||||
if (token.startsWith(p)) {
|
final String[] args = skip(token).split(",");
|
||||||
final String[] args = skip(p, token).split(",");
|
|
||||||
final SignInMode mode = SignInMode.valueOf(args[0]);
|
final SignInMode mode = SignInMode.valueOf(args[0]);
|
||||||
final String msg = KeyUtil.decode(args[1]);
|
final String msg = KeyUtil.decode(args[1]);
|
||||||
final String to = MINE;
|
final String to = MINE;
|
||||||
@@ -401,12 +524,11 @@ public class Dispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SETTINGS_NEW_AGREEMENT.equals(token))
|
if (matchExact(SETTINGS_NEW_AGREEMENT, token))
|
||||||
return new NewAgreementScreen();
|
return new NewAgreementScreen();
|
||||||
|
|
||||||
p = SETTINGS_NEW_AGREEMENT + ",";
|
if (matchPrefix(SETTINGS_NEW_AGREEMENT + "/", token)) {
|
||||||
if (token.startsWith(p)) {
|
return new NewAgreementScreen(skip(token));
|
||||||
return new NewAgreementScreen(skip(p, token));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotFoundScreen();
|
return new NotFoundScreen();
|
||||||
@@ -421,54 +543,72 @@ public class Dispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Screen select() {
|
private Screen select() {
|
||||||
String p;
|
if (matchExact(ADMIN_GROUPS, token)
|
||||||
|
|| matchExact("/admin/groups", token)) {
|
||||||
|
return new GroupListScreen();
|
||||||
|
}
|
||||||
|
|
||||||
p = "admin,group,uuid-";
|
if (matchExact(ADMIN_PROJECTS, token)
|
||||||
if (token.startsWith(p))
|
|| matchExact("/admin/projects", token)) {
|
||||||
return new AccountGroupScreen(AccountGroup.UUID.parse(skip(p, token)));
|
return new ProjectListScreen();
|
||||||
|
}
|
||||||
|
|
||||||
p = "admin,group,";
|
if (matchPrefix("/admin/groups/uuid-", token))
|
||||||
if (token.startsWith(p))
|
return new AccountGroupScreen(AccountGroup.UUID.parse(skip(token)));
|
||||||
return new AccountGroupScreen(AccountGroup.Id.parse(skip(p, token)));
|
|
||||||
|
|
||||||
p = "admin,project,";
|
if (matchPrefix("/admin/groups/", token))
|
||||||
if (token.startsWith(p)) {
|
return new AccountGroupScreen(AccountGroup.Id.parse(skip(token)));
|
||||||
p = skip(p, token);
|
|
||||||
final int c = p.indexOf(',');
|
|
||||||
final Project.NameKey k = Project.NameKey.parse(p.substring(0, c));
|
|
||||||
final boolean isWild = k.equals(Gerrit.getConfig().getWildProject());
|
|
||||||
p = p.substring(c + 1);
|
|
||||||
|
|
||||||
if (ProjectScreen.INFO.equals(p)) {
|
if (matchPrefix("/admin/projects/", token)) {
|
||||||
|
String rest = skip(token);
|
||||||
|
int c = rest.lastIndexOf(',');
|
||||||
|
if (c < 0) {
|
||||||
|
return new ProjectInfoScreen(Project.NameKey.parse(rest));
|
||||||
|
} else if (c == 0) {
|
||||||
|
return new NotFoundScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
Project.NameKey k = Project.NameKey.parse(rest.substring(0, c));
|
||||||
|
String panel = rest.substring(c + 1);
|
||||||
|
|
||||||
|
if (ProjectScreen.INFO.equals(panel)) {
|
||||||
return new ProjectInfoScreen(k);
|
return new ProjectInfoScreen(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isWild && ProjectScreen.BRANCH.equals(p)) {
|
if (ProjectScreen.BRANCH.equals(panel)
|
||||||
|
&& !k.equals(Gerrit.getConfig().getWildProject())) {
|
||||||
return new ProjectBranchesScreen(k);
|
return new ProjectBranchesScreen(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ProjectScreen.ACCESS.equals(p)) {
|
if (ProjectScreen.ACCESS.equals(panel)) {
|
||||||
return new ProjectAccessScreen(k);
|
return new ProjectAccessScreen(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NotFoundScreen();
|
return new NotFoundScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ADMIN_GROUPS.equals(token)) {
|
|
||||||
return new GroupListScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ADMIN_PROJECTS.equals(token)) {
|
|
||||||
return new ProjectListScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NotFoundScreen();
|
return new NotFoundScreen();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String skip(final String prefix, final String in) {
|
private static boolean matchExact(String want, String token) {
|
||||||
return in.substring(prefix.length());
|
return token.equals(want);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int prefixlen;
|
||||||
|
|
||||||
|
private static boolean matchPrefix(String want, String token) {
|
||||||
|
if (token.startsWith(want)) {
|
||||||
|
prefixlen = want.length();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String skip(String token) {
|
||||||
|
return token.substring(prefixlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static abstract class AsyncSplit implements RunAsyncCallback {
|
private static abstract class AsyncSplit implements RunAsyncCallback {
|
||||||
|
@@ -201,16 +201,13 @@ public class UserPassSignInDialog extends SignInDialog {
|
|||||||
public void onSuccess(final LoginResult result) {
|
public void onSuccess(final LoginResult result) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
String to = token;
|
String to = token;
|
||||||
if (result.isNew && !to.startsWith(PageLinks.REGISTER + ",")) {
|
if (!to.startsWith("/")) {
|
||||||
to = PageLinks.REGISTER + "," + to;
|
to = "/" + to;
|
||||||
}
|
}
|
||||||
|
if (result.isNew && !token.startsWith(PageLinks.REGISTER + "/")) {
|
||||||
// Unfortunately we no longer support updating the web UI when the
|
to = PageLinks.REGISTER + to;
|
||||||
// user signs in. Instead we must force a reload of the page, but
|
}
|
||||||
// that isn't easy because we might need to change the anchor. So
|
Location.replace(Location.getPath() + "login" + to);
|
||||||
// we bounce through a little redirection servlet on the server.
|
|
||||||
//
|
|
||||||
Location.replace(Location.getPath() + "login/" + to);
|
|
||||||
} else {
|
} else {
|
||||||
showError(Util.C.invalidLogin());
|
showError(Util.C.invalidLogin());
|
||||||
enable(true);
|
enable(true);
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.client.changes;
|
package com.google.gerrit.client.changes;
|
||||||
|
|
||||||
|
import com.google.gerrit.client.Dispatcher;
|
||||||
import com.google.gerrit.client.Gerrit;
|
import com.google.gerrit.client.Gerrit;
|
||||||
import com.google.gerrit.client.rpc.GerritCallback;
|
import com.google.gerrit.client.rpc.GerritCallback;
|
||||||
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
||||||
@@ -475,8 +476,7 @@ public class ChangeScreen extends Screen {
|
|||||||
@Override
|
@Override
|
||||||
public void onKeyPress(final KeyPressEvent event) {
|
public void onKeyPress(final KeyPressEvent event) {
|
||||||
PatchSet.Id currentPatchSetId = patchSetsBlock.getCurrentPatchSet().getId();
|
PatchSet.Id currentPatchSetId = patchSetsBlock.getCurrentPatchSet().getId();
|
||||||
Gerrit.display("change,publish," + currentPatchSetId.toString(),
|
Gerrit.display(Dispatcher.toPublish(currentPatchSetId));
|
||||||
new PublishCommentScreen(currentPatchSetId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -518,8 +518,7 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements O
|
|||||||
b.addClickHandler(new ClickHandler() {
|
b.addClickHandler(new ClickHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(final ClickEvent event) {
|
public void onClick(final ClickEvent event) {
|
||||||
Gerrit.display("change,publish," + patchSet.getId().toString(),
|
Gerrit.display(Dispatcher.toPublish(patchSet.getId()));
|
||||||
new PublishCommentScreen(patchSet.getId()));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
actionsPanel.add(b);
|
actionsPanel.add(b);
|
||||||
|
@@ -37,7 +37,7 @@ public class QueryScreen extends PagedSingleListScreen implements
|
|||||||
private final String query;
|
private final String query;
|
||||||
|
|
||||||
public QueryScreen(final String encQuery, final String positionToken) {
|
public QueryScreen(final String encQuery, final String positionToken) {
|
||||||
super("q," + encQuery, positionToken);
|
super("/q/" + encQuery, positionToken);
|
||||||
query = KeyUtil.decode(encQuery);
|
query = KeyUtil.decode(encQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
package com.google.gerrit.client.patches;
|
package com.google.gerrit.client.patches;
|
||||||
|
|
||||||
|
import com.google.gerrit.client.Dispatcher;
|
||||||
import com.google.gerrit.client.Gerrit;
|
import com.google.gerrit.client.Gerrit;
|
||||||
import com.google.gerrit.client.changes.PatchTable;
|
import com.google.gerrit.client.changes.PatchTable;
|
||||||
import com.google.gerrit.client.changes.PublishCommentScreen;
|
|
||||||
import com.google.gerrit.client.changes.Util;
|
import com.google.gerrit.client.changes.Util;
|
||||||
import com.google.gerrit.client.rpc.GerritCallback;
|
import com.google.gerrit.client.rpc.GerritCallback;
|
||||||
import com.google.gerrit.client.ui.CommentPanel;
|
import com.google.gerrit.client.ui.CommentPanel;
|
||||||
@@ -682,8 +682,7 @@ public abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
|||||||
@Override
|
@Override
|
||||||
public void onKeyPress(final KeyPressEvent event) {
|
public void onKeyPress(final KeyPressEvent event) {
|
||||||
final PatchSet.Id id = patchKey.getParentKey();
|
final PatchSet.Id id = patchKey.getParentKey();
|
||||||
Gerrit.display("change,publish," + id.toString(),
|
Gerrit.display(Dispatcher.toPublish(id));
|
||||||
new PublishCommentScreen(id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright 2011 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
package com.google.gerrit.httpd;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.PageLinks;
|
||||||
|
import com.google.gerrit.reviewdb.Change;
|
||||||
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
import com.google.gerrit.server.query.Predicate;
|
||||||
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
|
import com.google.gerrit.server.query.change.ChangeData;
|
||||||
|
import com.google.gerrit.server.query.change.ChangeDataSource;
|
||||||
|
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
||||||
|
import com.google.gerrit.server.query.change.ChangeQueryRewriter;
|
||||||
|
import com.google.gwtorm.client.OrmException;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class DirectChangeByCommit extends HttpServlet {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Logger log =
|
||||||
|
LoggerFactory.getLogger(DirectChangeByCommit.class);
|
||||||
|
|
||||||
|
private final ChangeQueryBuilder.Factory queryBuilder;
|
||||||
|
private final Provider<ChangeQueryRewriter> queryRewriter;
|
||||||
|
private final Provider<CurrentUser> currentUser;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DirectChangeByCommit(ChangeQueryBuilder.Factory queryBuilder,
|
||||||
|
Provider<ChangeQueryRewriter> queryRewriter,
|
||||||
|
Provider<CurrentUser> currentUser) {
|
||||||
|
this.queryBuilder = queryBuilder;
|
||||||
|
this.queryRewriter = queryRewriter;
|
||||||
|
this.currentUser = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected void doGet(final HttpServletRequest req,
|
||||||
|
final HttpServletResponse rsp) throws IOException {
|
||||||
|
String query = req.getPathInfo();
|
||||||
|
HashSet<Change.Id> ids = new HashSet<Change.Id>();
|
||||||
|
try {
|
||||||
|
ChangeQueryBuilder builder = queryBuilder.create(currentUser.get());
|
||||||
|
Predicate<ChangeData> visibleToMe = builder.is_visible();
|
||||||
|
Predicate<ChangeData> q = builder.parse(query);
|
||||||
|
q = Predicate.and(q, builder.sortkey_before("z"), builder.limit(2), visibleToMe);
|
||||||
|
|
||||||
|
ChangeQueryRewriter rewriter = queryRewriter.get();
|
||||||
|
Predicate<ChangeData> s = rewriter.rewrite(q);
|
||||||
|
if (!(s instanceof ChangeDataSource)) {
|
||||||
|
s = rewriter.rewrite(Predicate.and(builder.status_open(), q));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s instanceof ChangeDataSource) {
|
||||||
|
for (ChangeData d : ((ChangeDataSource) s).read()) {
|
||||||
|
ids.add(d.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (QueryParseException e) {
|
||||||
|
log.warn("Received invalid query by URL: /r/" + query, e);
|
||||||
|
} catch (OrmException e) {
|
||||||
|
log.warn("Cannot process query by URL: /r/" + query, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String token;
|
||||||
|
if (ids.size() == 1) {
|
||||||
|
// If exactly one change matches, link to that change.
|
||||||
|
// TODO Link to a specific patch set, if one matched.
|
||||||
|
token = PageLinks.toChange(ids.iterator().next());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Otherwise, link to the query page.
|
||||||
|
token = PageLinks.toChangeQuery(query);
|
||||||
|
}
|
||||||
|
UrlModule.toGerrit(token, req, rsp);
|
||||||
|
}
|
||||||
|
}
|
@@ -23,6 +23,7 @@ import com.google.gerrit.httpd.raw.LegacyGerritServlet;
|
|||||||
import com.google.gerrit.httpd.raw.SshInfoServlet;
|
import com.google.gerrit.httpd.raw.SshInfoServlet;
|
||||||
import com.google.gerrit.httpd.raw.StaticServlet;
|
import com.google.gerrit.httpd.raw.StaticServlet;
|
||||||
import com.google.gerrit.httpd.raw.ToolServlet;
|
import com.google.gerrit.httpd.raw.ToolServlet;
|
||||||
|
import com.google.gerrit.reviewdb.Change;
|
||||||
import com.google.gwtexpui.server.CacheControlFilter;
|
import com.google.gwtexpui.server.CacheControlFilter;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
@@ -63,14 +64,13 @@ class UrlModule extends ServletModule {
|
|||||||
serve("/all").with(query("status:merged"));
|
serve("/all").with(query("status:merged"));
|
||||||
serve("/mine").with(screen(PageLinks.MINE));
|
serve("/mine").with(screen(PageLinks.MINE));
|
||||||
serve("/open").with(query("status:open"));
|
serve("/open").with(query("status:open"));
|
||||||
serve("/settings").with(screen(PageLinks.SETTINGS));
|
|
||||||
serve("/watched").with(query("is:watched status:open"));
|
serve("/watched").with(query("is:watched status:open"));
|
||||||
serve("/starred").with(query("is:starred"));
|
serve("/starred").with(query("is:starred"));
|
||||||
|
|
||||||
serveRegex( //
|
serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS));
|
||||||
"^/([1-9][0-9]*)/?$", //
|
serveRegex("^/register/?$").with(screen(PageLinks.REGISTER + "/"));
|
||||||
"^/r/(.+)/?$" //
|
serveRegex("^/([1-9][0-9]*)/?$").with(directChangeById());
|
||||||
).with(changeQuery());
|
serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Key<HttpServlet> notFound() {
|
private Key<HttpServlet> notFound() {
|
||||||
@@ -110,14 +110,19 @@ class UrlModule extends ServletModule {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Key<HttpServlet> changeQuery() {
|
private Key<HttpServlet> directChangeById() {
|
||||||
return key(new HttpServlet() {
|
return key(new HttpServlet() {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doGet(final HttpServletRequest req,
|
protected void doGet(final HttpServletRequest req,
|
||||||
final HttpServletResponse rsp) throws IOException {
|
final HttpServletResponse rsp) throws IOException {
|
||||||
toGerrit(PageLinks.toChangeQuery(req.getPathInfo()), req, rsp);
|
try {
|
||||||
|
Change.Id id = Change.Id.parse(req.getPathInfo());
|
||||||
|
toGerrit(PageLinks.toChange(id), req, rsp);
|
||||||
|
} catch (IllegalArgumentException err) {
|
||||||
|
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -146,7 +151,7 @@ class UrlModule extends ServletModule {
|
|||||||
return srv;
|
return srv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toGerrit(final String target, final HttpServletRequest req,
|
static void toGerrit(final String target, final HttpServletRequest req,
|
||||||
final HttpServletResponse rsp) throws IOException {
|
final HttpServletResponse rsp) throws IOException {
|
||||||
final StringBuilder url = new StringBuilder();
|
final StringBuilder url = new StringBuilder();
|
||||||
url.append(req.getContextPath());
|
url.append(req.getContextPath());
|
||||||
|
@@ -139,7 +139,6 @@ public class BecomeAnyAccountLoginServlet extends HttpServlet {
|
|||||||
rdr.append('#');
|
rdr.append('#');
|
||||||
if (res.isNew()) {
|
if (res.isNew()) {
|
||||||
rdr.append(PageLinks.REGISTER);
|
rdr.append(PageLinks.REGISTER);
|
||||||
rdr.append(',');
|
|
||||||
}
|
}
|
||||||
rdr.append(PageLinks.MINE);
|
rdr.append(PageLinks.MINE);
|
||||||
rsp.sendRedirect(rdr.toString());
|
rsp.sendRedirect(rdr.toString());
|
||||||
|
@@ -130,9 +130,8 @@ class HttpLoginServlet extends HttpServlet {
|
|||||||
final StringBuilder rdr = new StringBuilder();
|
final StringBuilder rdr = new StringBuilder();
|
||||||
rdr.append(urlProvider.get());
|
rdr.append(urlProvider.get());
|
||||||
rdr.append('#');
|
rdr.append('#');
|
||||||
if (arsp.isNew() && !token.startsWith(PageLinks.REGISTER + ",")) {
|
if (arsp.isNew() && !token.startsWith(PageLinks.REGISTER + "/")) {
|
||||||
rdr.append(PageLinks.REGISTER);
|
rdr.append(PageLinks.REGISTER);
|
||||||
rdr.append(',');
|
|
||||||
}
|
}
|
||||||
rdr.append(token);
|
rdr.append(token);
|
||||||
|
|
||||||
@@ -165,9 +164,6 @@ class HttpLoginServlet extends HttpServlet {
|
|||||||
|
|
||||||
private String getToken(final HttpServletRequest req) {
|
private String getToken(final HttpServletRequest req) {
|
||||||
String token = req.getPathInfo();
|
String token = req.getPathInfo();
|
||||||
if (token != null && token.startsWith("/")) {
|
|
||||||
token = token.substring(1);
|
|
||||||
}
|
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
token = PageLinks.MINE;
|
token = PageLinks.MINE;
|
||||||
}
|
}
|
||||||
|
@@ -63,9 +63,6 @@ public class HttpsClientSslCertLoginServlet extends HttpServlet {
|
|||||||
|
|
||||||
private String getToken(final HttpServletRequest req) {
|
private String getToken(final HttpServletRequest req) {
|
||||||
String token = req.getPathInfo();
|
String token = req.getPathInfo();
|
||||||
if (token != null && token.startsWith("/")) {
|
|
||||||
token = token.substring(1);
|
|
||||||
}
|
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
token = PageLinks.MINE;
|
token = PageLinks.MINE;
|
||||||
}
|
}
|
||||||
|
@@ -59,7 +59,7 @@ class LoginRedirectServlet extends HttpServlet {
|
|||||||
token = getToken(req);
|
token = getToken(req);
|
||||||
} else {
|
} else {
|
||||||
final String msg = "Session cookie not available.";
|
final String msg = "Session cookie not available.";
|
||||||
token = "SignInFailure," + SignInMode.SIGN_IN + "," + msg;
|
token = "/SignInFailure," + SignInMode.SIGN_IN + "," + msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
final StringBuilder rdr = new StringBuilder();
|
final StringBuilder rdr = new StringBuilder();
|
||||||
@@ -75,9 +75,6 @@ class LoginRedirectServlet extends HttpServlet {
|
|||||||
|
|
||||||
private String getToken(final HttpServletRequest req) {
|
private String getToken(final HttpServletRequest req) {
|
||||||
String token = req.getPathInfo();
|
String token = req.getPathInfo();
|
||||||
if (token != null && token.startsWith("/")) {
|
|
||||||
token = token.substring(1);
|
|
||||||
}
|
|
||||||
if (token == null || token.isEmpty()) {
|
if (token == null || token.isEmpty()) {
|
||||||
token = PageLinks.MINE;
|
token = PageLinks.MINE;
|
||||||
}
|
}
|
||||||
|
@@ -462,16 +462,15 @@ class OpenIdServiceImpl implements OpenIdService {
|
|||||||
private void callback(final boolean isNew, final HttpServletRequest req,
|
private void callback(final boolean isNew, final HttpServletRequest req,
|
||||||
final HttpServletResponse rsp) throws IOException {
|
final HttpServletResponse rsp) throws IOException {
|
||||||
String token = req.getParameter(P_TOKEN);
|
String token = req.getParameter(P_TOKEN);
|
||||||
if (token == null || token.isEmpty() || token.startsWith("SignInFailure,")) {
|
if (token == null || token.isEmpty() || token.startsWith("/SignInFailure,")) {
|
||||||
token = PageLinks.MINE;
|
token = PageLinks.MINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
final StringBuilder rdr = new StringBuilder();
|
final StringBuilder rdr = new StringBuilder();
|
||||||
rdr.append(urlProvider.get());
|
rdr.append(urlProvider.get());
|
||||||
rdr.append('#');
|
rdr.append('#');
|
||||||
if (isNew && !token.startsWith(PageLinks.REGISTER + ",")) {
|
if (isNew && !token.startsWith(PageLinks.REGISTER + "/")) {
|
||||||
rdr.append(PageLinks.REGISTER);
|
rdr.append(PageLinks.REGISTER);
|
||||||
rdr.append(',');
|
|
||||||
}
|
}
|
||||||
rdr.append(token);
|
rdr.append(token);
|
||||||
rsp.sendRedirect(rdr.toString());
|
rsp.sendRedirect(rdr.toString());
|
||||||
|
@@ -265,9 +265,9 @@ class GitWebServlet extends HttpServlet {
|
|||||||
p.print("+branch:$1,n,z};\n"); // wrapped
|
p.print("+branch:$1,n,z};\n"); // wrapped
|
||||||
p.print(" } elsif ($h =~ /^refs\\/changes\\/\\d{2}\\/(\\d+)\\/\\d+$/) ");
|
p.print(" } elsif ($h =~ /^refs\\/changes\\/\\d{2}\\/(\\d+)\\/\\d+$/) ");
|
||||||
p.print("{\n"); // wrapped
|
p.print("{\n"); // wrapped
|
||||||
p.print(" $q = qq{#change,$1};\n");
|
p.print(" $q = qq{#/c/$1};\n");
|
||||||
p.print(" } else {\n");
|
p.print(" } else {\n");
|
||||||
p.print(" $q = qq{#q,$h,n,z};\n");
|
p.print(" $q = qq{#/q/$h,n,z};\n");
|
||||||
p.print(" }\n");
|
p.print(" }\n");
|
||||||
p.print(" my $r = qq{$ENV{'GERRIT_CONTEXT_PATH'}$q};\n");
|
p.print(" my $r = qq{$ENV{'GERRIT_CONTEXT_PATH'}$q};\n");
|
||||||
p.print(" push @{$feature{'actions'}{'default'}},\n");
|
p.print(" push @{$feature{'actions'}{'default'}},\n");
|
||||||
|
@@ -36,7 +36,7 @@ Welcome to Gerrit Code Review at ${email.gerritHost}.
|
|||||||
To add a verified email address to your user account, please
|
To add a verified email address to your user account, please
|
||||||
click on the following link:
|
click on the following link:
|
||||||
|
|
||||||
$email.gerritUrl#VE,$email.emailRegistrationToken
|
$email.gerritUrl#/VE/$email.emailRegistrationToken
|
||||||
|
|
||||||
If you have received this mail in error, you do not need to take any
|
If you have received this mail in error, you do not need to take any
|
||||||
action to cancel the account. The account will not be activated, and
|
action to cancel the account. The account will not be activated, and
|
||||||
|
Reference in New Issue
Block a user