Merge "Add BEFORE_CHERRY_PICK event"
diff --git a/polygerrit-ui/app/api/plugin.ts b/polygerrit-ui/app/api/plugin.ts
index 471e99c..a248db6 100644
--- a/polygerrit-ui/app/api/plugin.ts
+++ b/polygerrit-ui/app/api/plugin.ts
@@ -47,6 +47,7 @@
BEFORE_PUBLISH_EDIT = 'before-publish-edit',
PUBLISH_EDIT = 'publish-edit',
BEFORE_REBASE = 'before-rebase',
+ BEFORE_CHERRY_PICK = 'before-cherry-pick',
}
export declare interface PluginApi {
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index edb2e2f..5b96c09 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -1722,18 +1722,27 @@
}
// private but used in test
- handleCherrypickConfirm() {
- this.handleCherryPickRestApi(false);
+ async handleCherrypickConfirm() {
+ await this.handleCherryPickRestApi(false);
}
// private but used in test
- handleCherrypickConflictConfirm() {
- this.handleCherryPickRestApi(true);
+ async handleCherrypickConflictConfirm() {
+ await this.handleCherryPickRestApi(true);
}
- private handleCherryPickRestApi(conflicts: boolean) {
+ private async handleCherryPickRestApi(conflicts: boolean) {
assertIsDefined(this.confirmCherrypick, 'confirmCherrypick');
assertIsDefined(this.actionsModal, 'actionsModal');
+
+ if (
+ !(await this.getPluginLoader().jsApiService.handleBeforeCherryPick(
+ this.change as ChangeInfo
+ ))
+ ) {
+ return;
+ }
+
const el = this.confirmCherrypick;
if (!el.branch) {
fireAlert(this, ERR_BRANCH_EMPTY);
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
index c522e81..5544e15 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
@@ -1146,14 +1146,14 @@
title: 'Cherry pick change to a different branch',
};
- element.handleCherrypickConfirm();
+ await element.handleCherrypickConfirm();
assert.equal(fireActionStub.callCount, 0);
queryAndAssert<GrConfirmCherrypickDialog>(
element,
'#confirmCherrypick'
).branch = 'master' as BranchName;
- element.handleCherrypickConfirm();
+ await element.handleCherrypickConfirm();
assert.equal(fireActionStub.callCount, 0); // Still needs a message.
// Add attributes that are used to determine the message.
@@ -1171,7 +1171,7 @@
).commitNum = '123' as CommitId;
await element.updateComplete;
- element.handleCherrypickConfirm();
+ await element.handleCherrypickConfirm();
await element.updateComplete;
const autogrowEl = queryAndAssert<GrAutogrowTextarea>(
@@ -1229,7 +1229,7 @@
).commitNum = '123' as CommitId;
await element.updateComplete;
- element.handleCherrypickConflictConfirm();
+ await element.handleCherrypickConflictConfirm();
await element.updateComplete;
assert.deepEqual(fireActionStub.lastCall.args, [
@@ -1246,6 +1246,30 @@
]);
});
+ test('handleBeforeCherryPick blocks action', async () => {
+ const handleBeforeCherryPickStub = sinon
+ .stub(
+ testResolver(pluginLoaderToken).jsApiService,
+ 'handleBeforeCherryPick'
+ )
+ .returns(Promise.resolve(false));
+
+ element.handleCherrypickTap();
+ queryAndAssert<GrConfirmCherrypickDialog>(
+ element,
+ '#confirmCherrypick'
+ ).branch = 'master' as BranchName;
+ queryAndAssert<GrConfirmCherrypickDialog>(
+ element,
+ '#confirmCherrypick'
+ ).commitMessage = 'foo message';
+ await element.updateComplete;
+
+ await element.handleCherrypickConfirm();
+ assert.equal(fireActionStub.callCount, 0);
+ assert.isTrue(handleBeforeCherryPickStub.called);
+ });
+
test('branch name cleared when re-open cherrypick', () => {
const emptyBranchName = '';
queryAndAssert<GrConfirmCherrypickDialog>(
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
index a0afce1..a2e901a 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
@@ -107,6 +107,19 @@
return okay;
}
+ async handleBeforeCherryPick(change: ChangeInfo): Promise<boolean> {
+ await this.waitForPluginsToLoad();
+ let okay = true;
+ for (const cb of this._getEventCallbacks(EventType.BEFORE_CHERRY_PICK)) {
+ try {
+ okay = (await cb(change)) && okay;
+ } catch (err: unknown) {
+ this.reportError(err, EventType.BEFORE_CHERRY_PICK);
+ }
+ }
+ return okay;
+ }
+
handlePublishEdit(change: ChangeInfo, revision?: RevisionInfo | null) {
for (const cb of this._getEventCallbacks(EventType.PUBLISH_EDIT)) {
try {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-types.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-types.ts
index 813faf3..220fed3 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-types.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-types.ts
@@ -68,6 +68,13 @@
* @return A promise that resolves to true if the rebase should proceed.
*/
handleBeforeRebase(change: ChangeInfo): Promise<boolean>;
+ /**
+ * This method is called before a cherry-pick.
+ * It allows plugins to conditionally block the cherry-pick.
+ * @param change The relevant change.
+ * @return A promise that resolves to true if the cherry-pick should proceed.
+ */
+ handleBeforeCherryPick(change: ChangeInfo): Promise<boolean>;
handlePublishEdit(change: ChangeInfo, revision?: RevisionInfo | null): void;
handleShowChange(detail: ShowChangeDetail): Promise<void>;
handleShowRevisionActions(detail: ShowRevisionActionsDetail): void;