Merge "ExternalIdCacheLoader: suppress warning if cache is not persisted."
diff --git a/java/com/google/gerrit/server/logging/Metadata.java b/java/com/google/gerrit/server/logging/Metadata.java
index 64d156f..d312530 100644
--- a/java/com/google/gerrit/server/logging/Metadata.java
+++ b/java/com/google/gerrit/server/logging/Metadata.java
@@ -95,9 +95,6 @@
// The version of a secondary index.
public abstract Optional<Integer> indexVersion();
- // The number of inputs to an operation, eg. Reachable.fromRefs.
- public abstract Optional<Integer> inputSize();
-
// The name of the implementation method.
public abstract Optional<String> methodName();
@@ -303,8 +300,6 @@
public abstract Builder indexVersion(int indexVersion);
- public abstract Builder inputSize(int size);
-
public abstract Builder methodName(@Nullable String methodName);
public abstract Builder multiple(boolean multiple);
diff --git a/java/com/google/gerrit/server/project/Reachable.java b/java/com/google/gerrit/server/project/Reachable.java
index c30378b..6d28646a 100644
--- a/java/com/google/gerrit/server/project/Reachable.java
+++ b/java/com/google/gerrit/server/project/Reachable.java
@@ -67,7 +67,7 @@
try (TraceTimer timer =
TraceContext.newTimer(
"IncludedInResolver.includedInAny",
- Metadata.builder().projectName(project.get()).inputSize(refs.size()).build())) {
+ Metadata.builder().projectName(project.get()).resourceCount(refs.size()).build())) {
return IncludedInResolver.includedInAny(repo, rw, commit, filtered.values());
}
} catch (IOException | PermissionBackendException e) {
diff --git a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
index 94c379b..b44bb29 100644
--- a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
+++ b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
@@ -95,11 +95,12 @@
String.format("change is %s.", ChangeUtil.status(changeResource.getChange())));
}
- String submissionId =
- requireNonNull(
- changeResource.getChange().getSubmissionId(),
- String.format("merged change %s has no submission ID", changeResource.getId()));
-
+ String submissionId = changeResource.getChange().getSubmissionId();
+ if (submissionId == null) {
+ throw new ResourceConflictException(
+ "This change is merged but doesn't have a submission id,"
+ + " meaning it was not submitted through Gerrit.");
+ }
List<ChangeData> changeDatas = queryProvider.get().bySubmissionId(submissionId);
for (ChangeData changeData : changeDatas) {
diff --git a/plugins/replication b/plugins/replication
index 4689b41..d7c09fb 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 4689b419eab61ea204daf2dfca47296667ac317c
+Subproject commit d7c09fbb4c18b1743d6060d361171c2a5237f22b
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
index 0817762..6703651 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.html
@@ -269,6 +269,25 @@
Do you really want to delete the edit?
</div>
</gr-dialog>
+ <gr-dialog
+ id="showRevertSubmissionChangesDialog"
+ class="confirmDialog"
+ confirm-label="Close"
+ cancel-label=''
+ on-confirm="_handleShowRevertSubmissionChangesConfirm">
+ <div class="header" slot="header">
+ Reverted Changes
+ </div>
+ <div class="main" slot="main">
+ <template is="dom-repeat" items="[[_revertChanges]]">
+ <div>
+ <a href$="[[item.link]]" target="_blank">
+ Change [[item._number]]
+ </a>
+ </div>
+ </template>
+ </div>
+ </gr-dialog>
</gr-overlay>
<gr-js-api-interface id="jsAPI"></gr-js-api-interface>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
index 2ce0d7d..8ad2a06 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.js
@@ -420,6 +420,10 @@
type: Boolean,
value: true,
},
+ _revertChanges: {
+ type: Array,
+ value: [],
+ },
};
}
@@ -1258,6 +1262,7 @@
_handleResponse(action, response) {
if (!response) { return; }
return this.$.restAPI.getResponseObject(response).then(obj => {
+ let revertChanges = [];
switch (action.__key) {
case ChangeActions.REVERT:
this._waitForChangeReachable(obj._number)
@@ -1282,6 +1287,29 @@
case ChangeActions.REBASE_EDIT:
Gerrit.Nav.navigateToChange(this.change);
break;
+ case ChangeActions.REVERT_SUBMISSION:
+ revertChanges = obj.revert_changes || [];
+ revertChanges = revertChanges.map(change => {
+ change.link = '/q/' + encodeURIComponent(change.change_id);
+ return change;
+ });
+ // list of reverted changes can never be 0
+ if (revertChanges.length === 1) {
+ // redirect to the change if only 1 change is reverted
+ const change = revertChanges[0];
+ this._waitForChangeReachable(change._number).then(success => {
+ if (success) {
+ Gerrit.Nav.navigateToChange(change);
+ } else {
+ console.error('Change ' + change._number + ' not reachable');
+ }
+ });
+ } else {
+ // show multiple reverted changes in a dialog
+ this._revertChanges = revertChanges;
+ this._showActionDialog(this.$.showRevertSubmissionChangesDialog);
+ }
+ break;
default:
this.dispatchEvent(new CustomEvent('reload-change',
{detail: {action: action.__key}, bubbles: false}));
@@ -1290,6 +1318,10 @@
});
}
+ _handleShowRevertSubmissionChangesConfirm() {
+ this._hideAllDialogs();
+ }
+
_handleResponseError(action, response, body) {
if (action && action.__key === RevisionActions.CHERRYPICK) {
if (response && response.status === 409 &&
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
index a10f028..532c573 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.html
@@ -1422,6 +1422,7 @@
let payload;
let onShowError;
let onShowAlert;
+ let getResponseObjectStub;
setup(() => {
cleanup = sinon.stub();
@@ -1437,12 +1438,18 @@
suite('happy path', () => {
let sendStub;
-
+ let waitForChangeReachableStub;
setup(() => {
sandbox.stub(element, 'fetchChangeUpdates')
.returns(Promise.resolve({isLatest: true}));
sendStub = sandbox.stub(element.$.restAPI, 'executeChangeAction')
.returns(Promise.resolve({}));
+ getResponseObjectStub = sandbox.stub(element.$.restAPI,
+ 'getResponseObject');
+ waitForChangeReachableStub = sandbox.stub(element,
+ '_waitForChangeReachable').returns(Promise.resolve(true));
+ sandbox.stub(Gerrit.Nav,
+ 'navigateToChange').returns(Promise.resolve(true));
});
test('change action', () => {
@@ -1455,6 +1462,49 @@
});
});
+ suite('single changes revert', () => {
+ setup(() => {
+ getResponseObjectStub
+ .returns(Promise.resolve({revert_changes: [
+ {change_id: 12345},
+ ]}));
+ showActionDialogStub = sandbox.stub(element, '_showActionDialog');
+ });
+
+ test('revert submission single change', done => {
+ element._send('POST', {message: 'Revert submission'},
+ '/revert_submission', false, cleanup).then(res => {
+ element._handleResponse({__key: 'revert_submission'}, {}).
+ then(() => {
+ assert.isTrue(waitForChangeReachableStub.called);
+ done();
+ });
+ });
+ });
+ });
+
+ suite('multiple changes revert', () => {
+ let showActionDialogStub;
+ setup(() => {
+ getResponseObjectStub
+ .returns(Promise.resolve({revert_changes: [
+ {change_id: 12345}, {change_id: 23456},
+ ]}));
+ showActionDialogStub = sandbox.stub(element, '_showActionDialog');
+ });
+
+ test('revert submission multiple change', done => {
+ element._send('POST', {message: 'Revert submission'},
+ '/revert_submission', false, cleanup).then(res => {
+ element._handleResponse({__key: 'revert_submission'}, {}).then(
+ () => {
+ assert.isTrue(showActionDialogStub.called);
+ done();
+ });
+ });
+ });
+ });
+
test('revision action', () => {
return element._send('DELETE', payload, '/endpoint', true, cleanup)
.then(() => {
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
index fe8384e..d29858e 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.html
@@ -90,7 +90,7 @@
}
gr-smart-search {
flex-grow: 1;
- margin-left: var(--spacing-m);
+ margin: 0 var(--spacing-m);
max-width: 500px;
}
gr-dropdown,
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
index d7510ec..89b28d5 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.html
@@ -58,6 +58,9 @@
#container.unresolved {
background-color: var(--unresolved-comment-background-color);
}
+ #container.robotComment {
+ background-color: var(--robot-comment-background-color);
+ }
#commentInfoContainer {
border-top: 1px dotted var(--border-color);
display: flex;
@@ -82,7 +85,7 @@
<span class="descriptionText">Patchset [[patchNum]]</span>
</div>
</template>
- <div id="container" class$="[[_computeHostClass(unresolved)]]">
+ <div id="container" class$="[[_computeHostClass(unresolved, isRobotComment)]]">
<template id="commentList" is="dom-repeat" items="[[_orderedComments]]"
as="comment">
<gr-comment
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
index 72fc45d..8687e77 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.js
@@ -137,6 +137,11 @@
_lastComment: Object,
_orderedComments: Array,
_projectConfig: Object,
+ isRobotComment: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
};
}
@@ -221,6 +226,7 @@
this._lastComment = this._getLastComment();
this.unresolved = this._lastComment.unresolved;
this.hasDraft = this._lastComment.__draft;
+ this.isRobotComment = !!(this._lastComment.robot_id);
}
}
@@ -498,6 +504,9 @@
}
_computeHostClass(unresolved) {
+ if (this.isRobotComment) {
+ return 'robotComment';
+ }
return unresolved ? 'unresolved' : '';
}
diff --git a/polygerrit-ui/app/styles/themes/app-theme.html b/polygerrit-ui/app/styles/themes/app-theme.html
index 0ccb5c5..3a620d2 100644
--- a/polygerrit-ui/app/styles/themes/app-theme.html
+++ b/polygerrit-ui/app/styles/themes/app-theme.html
@@ -45,6 +45,7 @@
--assignee-highlight-color: #fcfad6;
--chip-background-color: #eee;
--comment-background-color: #fcfad6;
+ --robot-comment-background-color: #e8f0fe;
--default-button-background-color: white;
--dialog-background-color: white;
--dropdown-background-color: white;
diff --git a/polygerrit-ui/app/styles/themes/dark-theme.html b/polygerrit-ui/app/styles/themes/dark-theme.html
index 513f28a..4a91774 100644
--- a/polygerrit-ui/app/styles/themes/dark-theme.html
+++ b/polygerrit-ui/app/styles/themes/dark-theme.html
@@ -45,6 +45,7 @@
--assignee-highlight-color: #3a361c;
--chip-background-color: #131416;
--comment-background-color: #0b162b;
+ --robot-comment-background-color: #e8f0fe;
--default-button-background-color: #3c4043;
--dialog-background-color: #131416;
--dropdown-background-color: #131416;