Merge "Fix copy & paste issue on diff list page"
diff --git a/java/com/google/gerrit/server/git/receive/BUILD b/java/com/google/gerrit/server/git/receive/BUILD
index 7402a37..766a835 100644
--- a/java/com/google/gerrit/server/git/receive/BUILD
+++ b/java/com/google/gerrit/server/git/receive/BUILD
@@ -34,7 +34,7 @@
java_library(
name = "ref_cache",
- srcs = glob(["ReceivePackRefCache.java"]),
+ srcs = ["ReceivePackRefCache.java"],
visibility = ["//visibility:public"],
deps = [
"//java/com/google/gerrit/entities",
diff --git a/java/com/google/gerrit/server/group/GroupResolver.java b/java/com/google/gerrit/server/group/GroupResolver.java
index a54f465..1aa265b 100644
--- a/java/com/google/gerrit/server/group/GroupResolver.java
+++ b/java/com/google/gerrit/server/group/GroupResolver.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.group;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.entities.AccountGroup;
@@ -28,6 +29,8 @@
@Singleton
public class GroupResolver {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
private final GroupBackend groupBackend;
private final GroupCache groupCache;
private final GroupControl.Factory groupControlFactory;
@@ -81,36 +84,48 @@
* @return the group, null if no group is found for the given group ID
*/
public GroupDescription.Basic parseId(String id) {
+ logger.atFine().log("Parsing group %s", id);
+
AccountGroup.UUID uuid = AccountGroup.uuid(id);
if (groupBackend.handles(uuid)) {
+ logger.atFine().log("Group UUID %s is handled by a group backend", uuid.get());
GroupDescription.Basic d = groupBackend.get(uuid);
if (d != null) {
+ logger.atFine().log("Found group %s", d.getName());
return d;
}
}
// Might be a numeric AccountGroup.Id. -> Internal group.
if (id.matches("^[1-9][0-9]*$")) {
+ logger.atFine().log("Group ID %s is a numeric ID", id);
try {
AccountGroup.Id groupId = AccountGroup.Id.parse(id);
Optional<InternalGroup> group = groupCache.get(groupId);
if (group.isPresent()) {
+ logger.atFine().log(
+ "Found internal group %s (UUID = %s)",
+ group.get().getName(), group.get().getGroupUUID().get());
return new InternalGroupDescription(group.get());
}
} catch (IllegalArgumentException e) {
// Ignored
+ logger.atFine().withCause(e).log("Parsing numeric group ID %s failed", id);
}
}
// Might be a group name, be nice and accept unique names.
+ logger.atFine().log("Try finding a group with name %s", id);
GroupReference ref = GroupBackends.findExactSuggestion(groupBackend, id);
if (ref != null) {
GroupDescription.Basic d = groupBackend.get(ref.getUUID());
if (d != null) {
+ logger.atFine().log("Found group %s", d.getName());
return d;
}
}
+ logger.atFine().log("Group %s not found", id);
return null;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/GetPatch.java b/java/com/google/gerrit/server/restapi/change/GetPatch.java
index 31785be..66ccef3 100644
--- a/java/com/google/gerrit/server/restapi/change/GetPatch.java
+++ b/java/com/google/gerrit/server/restapi/change/GetPatch.java
@@ -136,7 +136,9 @@
} finally {
if (close) {
rw.close();
- bin.close();
+ if (bin != null) {
+ bin.close();
+ }
}
}
} finally {
diff --git a/plugins/gitiles b/plugins/gitiles
index 22b8e24..825ca06 160000
--- a/plugins/gitiles
+++ b/plugins/gitiles
@@ -1 +1 @@
-Subproject commit 22b8e242b5eaa9eae817b776bc862b096479ceaa
+Subproject commit 825ca06dddc9de89daa6b126dfc187fbeb25280c
diff --git a/plugins/webhooks b/plugins/webhooks
index 377fec1..570daca 160000
--- a/plugins/webhooks
+++ b/plugins/webhooks
@@ -1 +1 @@
-Subproject commit 377fec17d2c0fc71cdfb1d12f502cfa1eba1fbd7
+Subproject commit 570dacacc64f7c01e0bc0f1301aa1d5a218cfc1b
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
index 9ef2461..5a7e58d 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.js
@@ -178,6 +178,8 @@
_showAlert(text, opt_actionText, opt_actionCallback,
opt_dismissOnNavigation) {
if (this._alertElement) {
+ // do not override auth alerts
+ if (this._alertElement.type === 'AUTH') return;
this._hideAlert();
}
@@ -212,10 +214,14 @@
}
_showAuthErrorAlert(errorText, actionText) {
- // TODO(viktard): close alert if it's not for auth error.
- if (this._alertElement) { return; }
+ // hide any existing alert like `reload`
+ // as auth error should have the highest priority
+ if (this._alertElement) {
+ this._alertElement.hide();
+ }
this._alertElement = this._createToastAlert();
+ this._alertElement.type = 'AUTH';
this._alertElement.show(errorText, actionText,
this._createLoginPopup.bind(this));
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
index a0a5731..72f5d5b 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.html
@@ -52,6 +52,7 @@
sandbox.stub(window, 'fetch')
.returns(Promise.resolve({ok: true, status: 204}));
element = fixture('basic');
+ element._authService.clearCache();
});
test('does not show auth error on 403 by default', done => {
@@ -184,7 +185,8 @@
);
assert.equal(window.fetch.callCount, 1);
flush(() => {
- // auth check again
+ // here needs two flush as there are two chanined
+ // promises on server-error handler and flush only flushes one
assert.equal(window.fetch.callCount, 2);
flush(() => {
// auth-error fired
@@ -238,6 +240,97 @@
});
});
+ test('auth toast should dismiss existing toast', done => {
+ // starts with authed state
+ element.$.restAPI.getLoggedIn();
+ const toastSpy = sandbox.spy(element, '_createToastAlert');
+ const responseText = Promise.resolve('Authentication required\n');
+
+ // fake an alert
+ element.fire('show-alert', {message: 'test reload', action: 'reload'});
+ const toast = toastSpy.lastCall.returnValue;
+ assert.isOk(toast);
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'test reload');
+
+ // fake auth
+ window.fetch.returns(Promise.resolve({status: 403}));
+ element.fire('server-error',
+ {response: {status: 403, text() { return responseText; }}}
+ );
+ assert.equal(window.fetch.callCount, 1);
+ flush(() => {
+ // here needs two flush as there are two chanined
+ // promises on server-error handler and flush only flushes one
+ assert.equal(window.fetch.callCount, 2);
+ flush(() => {
+ // toast
+ const toast = toastSpy.lastCall.returnValue;
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'Credentails expired.');
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'Refresh credentials');
+ done();
+ });
+ });
+ });
+
+ test('regular toast should dismiss regular toast', () => {
+ // starts with authed state
+ element.$.restAPI.getLoggedIn();
+ const toastSpy = sandbox.spy(element, '_createToastAlert');
+
+ // fake an alert
+ element.fire('show-alert', {message: 'test reload', action: 'reload'});
+ let toast = toastSpy.lastCall.returnValue;
+ assert.isOk(toast);
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'test reload');
+
+ // new alert
+ element.fire('show-alert', {message: 'second-test', action: 'reload'});
+
+ toast = toastSpy.lastCall.returnValue;
+ assert.include(Polymer.dom(toast.root).textContent, 'second-test');
+ });
+
+ test('regular toast should not dismiss auth toast', done => {
+ // starts with authed state
+ element.$.restAPI.getLoggedIn();
+ const toastSpy = sandbox.spy(element, '_createToastAlert');
+ const responseText = Promise.resolve('Authentication required\n');
+
+ // fake auth
+ window.fetch.returns(Promise.resolve({status: 403}));
+ element.fire('server-error',
+ {response: {status: 403, text() { return responseText; }}}
+ );
+ assert.equal(window.fetch.callCount, 1);
+ flush(() => {
+ // here needs two flush as there are two chanined
+ // promises on server-error handler and flush only flushes one
+ assert.equal(window.fetch.callCount, 2);
+ flush(() => {
+ let toast = toastSpy.lastCall.returnValue;
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'Credentails expired.');
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'Refresh credentials');
+
+ // fake an alert
+ element.fire('show-alert', {
+ message: 'test-alert', action: 'reload',
+ });
+ toast = toastSpy.lastCall.returnValue;
+ assert.isOk(toast);
+ assert.include(
+ Polymer.dom(toast.root).textContent, 'Credentails expired.');
+
+ done();
+ });
+ });
+ });
+
test('show alert', () => {
const alertObj = {message: 'foo'};
sandbox.stub(element, '_showAlert');
diff --git a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
index 215f469..6a0769d 100644
--- a/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
+++ b/polygerrit-ui/app/elements/shared/gr-alert/gr-alert.js
@@ -32,6 +32,8 @@
return {
text: String,
actionText: String,
+ /** @type {?string} */
+ type: String,
shown: {
type: Boolean,
value: true,