Merge "Keep global capabilities sorted alphabetically"
diff --git a/javatests/com/google/gerrit/acceptance/api/group/BUILD b/javatests/com/google/gerrit/acceptance/api/group/BUILD
index 8530a92..29f532e 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/BUILD
+++ b/javatests/com/google/gerrit/acceptance/api/group/BUILD
@@ -22,7 +22,6 @@
     deps = [
         "//java/com/google/gerrit/entities",
         "//java/com/google/gerrit/extensions:api",
-        "//java/com/google/gerrit/server",
         "//lib/truth",
     ],
 )
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 7a5bc6f..eadcc30 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -42,7 +42,6 @@
 import '../../diff/gr-apply-fix-dialog/gr-apply-fix-dialog';
 import '../gr-reply-dialog/gr-reply-dialog';
 import '../gr-thread-list/gr-thread-list';
-import '../gr-upload-help-dialog/gr-upload-help-dialog';
 import '../../checks/gr-checks-tab';
 import {flush} from '@polymer/polymer/lib/legacy/polymer.dom';
 import {PolymerElement} from '@polymer/polymer/polymer-element';
@@ -227,7 +226,6 @@
     includedInDialog: GrIncludedInDialog;
     downloadOverlay: GrOverlay;
     downloadDialog: GrDownloadDialog;
-    uploadHelpOverlay: GrOverlay;
     replyOverlay: GrOverlay;
     replyDialog: GrReplyDialog;
     mainContent: HTMLDivElement;
@@ -1183,14 +1181,6 @@
     this.$.downloadOverlay.close();
   }
 
-  _handleOpenUploadHelpDialog() {
-    this.$.uploadHelpOverlay.open();
-  }
-
-  _handleCloseUploadHelpDialog() {
-    this.$.uploadHelpOverlay.close();
-  }
-
   _handleMessageReply(e: CustomEvent<{message: {message: string}}>) {
     const msg: string = e.detail.message.message;
     const quoteStr =
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index 993970a..4cc57c2 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -648,7 +648,6 @@
           diff-prefs-disabled="[[_diffPrefsDisabled]]"
           on-open-diff-prefs="_handleOpenDiffPrefs"
           on-open-download-dialog="_handleOpenDownloadDialog"
-          on-open-upload-help-dialog="_handleOpenUploadHelpDialog"
           on-open-included-in-dialog="_handleOpenIncludedInDialog"
           on-expand-diffs="_expandAllDiffs"
           on-collapse-diffs="_collapseAllDiffs"
@@ -794,13 +793,6 @@
       on-close="_handleDownloadDialogClose"
     ></gr-download-dialog>
   </gr-overlay>
-  <gr-overlay id="uploadHelpOverlay" with-backdrop="">
-    <gr-upload-help-dialog
-      revision="[[_currentRevision]]"
-      target-branch="[[_change.branch]]"
-      on-close="_handleCloseUploadHelpDialog"
-    ></gr-upload-help-dialog>
-  </gr-overlay>
   <gr-overlay id="includedInOverlay" with-backdrop="">
     <gr-included-in-dialog
       id="includedInDialog"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
index a9f8860..0dff5ec 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
@@ -98,10 +98,6 @@
    * @event open-download-dialog
    */
 
-  /**
-   * @event open-upload-help-dialog
-   */
-
   @property({type: Object})
   account: AccountInfo | undefined;
 
@@ -356,21 +352,4 @@
   _hideIncludedIn(change?: ChangeInfo) {
     return change?.status === MERGED_STATUS ? '' : 'hide';
   }
-
-  _handleUploadTap(e: Event) {
-    e.preventDefault();
-    e.stopPropagation();
-    this.dispatchEvent(
-      new CustomEvent('open-upload-help-dialog', {bubbles: false})
-    );
-  }
-
-  _computeUploadHelpContainerClass(change: ChangeInfo, account: AccountInfo) {
-    const changeIsMerged = change?.status === MERGED_STATUS;
-    const ownerId = change?.owner?._account_id || null;
-    const userId = account && account._account_id;
-    const userIsOwner = ownerId && userId && ownerId === userId;
-    const hideContainer = !userIsOwner || changeIsMerged;
-    return 'uploadContainer desktop' + (hideContainer ? ' hide' : '');
-  }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
index e0ee812..60958ba 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_html.ts
@@ -201,11 +201,6 @@
           <span class="separator"></span>
         </span>
       </template>
-      <span class$="[[_computeUploadHelpContainerClass(change, account)]]">
-        <gr-button link="" class="upload" on-click="_handleUploadTap"
-          >Update Change</gr-button
-        >
-      </span>
       <span class="downloadContainer desktop">
         <gr-button
           link=""
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
index a9349fb..078c46b 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
@@ -309,17 +309,6 @@
       assert.isFalse(isVisible(element.shadowRoot
           .querySelector('#editControls').parentElement));
     });
-
-    test('_computeUploadHelpContainerClass', () => {
-      // Only show the upload helper button when an unmerged change is viewed
-      // by its owner.
-      const accountA = {_account_id: 1};
-      const accountB = {_account_id: 2};
-      assert.notInclude(element._computeUploadHelpContainerClass(
-          {owner: accountA}, accountA), 'hide');
-      assert.include(element._computeUploadHelpContainerClass(
-          {owner: accountA}, accountB), 'hide');
-    });
   });
 });
 
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.ts b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.ts
deleted file mode 100644
index bfc2bdf..0000000
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * @license
- * Copyright (C) 2018 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.
- */
-import '../../shared/gr-dialog/gr-dialog';
-import '../../shared/gr-shell-command/gr-shell-command';
-import '../../../styles/shared-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-upload-help-dialog_html';
-import {customElement, property} from '@polymer/decorators';
-import {RevisionInfo} from '../../../types/common';
-import {appContext} from '../../../services/app-context';
-
-const COMMIT_COMMAND = 'git add . && git commit --amend --no-edit';
-const PUSH_COMMAND_PREFIX = 'git push origin HEAD:refs/for/';
-
-// Command names correspond to download plugin definitions.
-const PREFERRED_FETCH_COMMAND_ORDER = ['checkout', 'cherry pick', 'pull'];
-
-@customElement('gr-upload-help-dialog')
-export class GrUploadHelpDialog extends PolymerElement {
-  static get template() {
-    return htmlTemplate;
-  }
-
-  /**
-   * Fired when the user presses the close button.
-   *
-   * @event close
-   */
-
-  @property({type: Object})
-  revision?: RevisionInfo;
-
-  @property({type: String})
-  targetBranch?: string;
-
-  @property({type: String})
-  _commitCommand = COMMIT_COMMAND;
-
-  @property({
-    type: String,
-    computed: '_computeFetchCommand(revision, _preferredDownloadScheme)',
-  })
-  _fetchCommand?: string;
-
-  @property({type: String})
-  _preferredDownloadScheme?: string;
-
-  @property({type: String, computed: '_computePushCommand(targetBranch)'})
-  _pushCommand?: string;
-
-  private readonly restApiService = appContext.restApiService;
-
-  /** @override */
-  connectedCallback() {
-    super.connectedCallback();
-    this.restApiService
-      .getLoggedIn()
-      .then(loggedIn =>
-        loggedIn
-          ? this.restApiService.getPreferences()
-          : Promise.resolve(undefined)
-      )
-      .then(prefs => {
-        if (prefs) {
-          // TODO(TS): The download_command pref was deleted in change 249223.
-          // this._preferredDownloadCommand = prefs.download_command;
-          this._preferredDownloadScheme = prefs.download_scheme;
-        }
-      });
-  }
-
-  _handleCloseTap(e: Event) {
-    e.preventDefault();
-    e.stopPropagation();
-    this.dispatchEvent(
-      new CustomEvent('close', {
-        composed: true,
-        bubbles: false,
-      })
-    );
-  }
-
-  _computeFetchCommand(
-    revision?: RevisionInfo,
-    scheme?: string
-  ): string | undefined {
-    if (!revision || !revision.fetch) return undefined;
-    if (!scheme) {
-      const keys = Object.keys(revision.fetch).sort();
-      if (keys.length === 0) {
-        return undefined;
-      }
-      scheme = keys[0];
-    }
-    if (
-      !scheme ||
-      !revision.fetch[scheme] ||
-      !revision.fetch[scheme].commands
-    ) {
-      return undefined;
-    }
-
-    const cmds: {[key: string]: string} = {};
-    Object.entries(revision.fetch[scheme].commands!).forEach(([key, cmd]) => {
-      cmds[key.toLowerCase()] = cmd;
-    });
-
-    // If no supported command preference is given, look for known commands
-    // from the downloads plugin in order of preference.
-    for (let i = 0; i < PREFERRED_FETCH_COMMAND_ORDER.length; i++) {
-      if (cmds[PREFERRED_FETCH_COMMAND_ORDER[i]]) {
-        return cmds[PREFERRED_FETCH_COMMAND_ORDER[i]];
-      }
-    }
-
-    return undefined;
-  }
-
-  _computePushCommand(targetBranch: string) {
-    return PUSH_COMMAND_PREFIX + targetBranch;
-  }
-}
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'gr-upload-help-dialog': GrUploadHelpDialog;
-  }
-}
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_html.ts
deleted file mode 100644
index 9c27864..0000000
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_html.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 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.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
-  <style include="shared-styles">
-    :host {
-      background-color: var(--dialog-background-color);
-      display: block;
-    }
-    .main {
-      width: 100%;
-    }
-    ol {
-      margin-left: var(--spacing-xl);
-      list-style: decimal;
-    }
-    p {
-      margin-bottom: var(--spacing-m);
-    }
-    .warning {
-      color: var(--warning-foreground);
-    }
-  </style>
-  <gr-dialog confirm-label="Done" cancel-label="" on-confirm="_handleCloseTap">
-    <div class="header" slot="header">
-      How to update this change:
-    </div>
-    <div class="main" slot="main">
-      <iron-icon
-        icon="gr-icons:warning"
-        class="warningBeforeSubmit"
-      ></iron-icon>
-      <span class="warning"
-        >The Update Change button will be removed from Gerrit in 2 weeks. You
-        can find the checkout command in the Download Dialog(keyboard shortcut:
-        d). We recommend making an alias for the other commands.
-      </span>
-      <ol>
-        <li>
-          <p>
-            Checkout this change locally and make your desired modifications to
-            the files.
-          </p>
-          <template is="dom-if" if="[[_fetchCommand]]">
-            <gr-shell-command
-              class="fetch-command"
-              command="[[_fetchCommand]]"
-            ></gr-shell-command>
-          </template>
-        </li>
-        <li>
-          <p>
-            Update the local commit with your modifications using the following
-            command.
-          </p>
-          <gr-shell-command
-            class="commit-command"
-            command="[[_commitCommand]]"
-          ></gr-shell-command>
-          <p>
-            Leave the "Change-Id:" line of the commit message as is.
-          </p>
-        </li>
-        <li>
-          <p>Push the updated commit to Gerrit.</p>
-          <gr-shell-command
-            class="push-command"
-            command="[[_pushCommand]]"
-          ></gr-shell-command>
-        </li>
-        <li>
-          <p>Refresh this page to view the the update.</p>
-        </li>
-      </ol>
-    </div>
-  </gr-dialog>
-`;
diff --git a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js b/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js
deleted file mode 100644
index 005b20d..0000000
--- a/polygerrit-ui/app/elements/change/gr-upload-help-dialog/gr-upload-help-dialog_test.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @license
- * Copyright (C) 2018 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.
- */
-
-import '../../../test/common-test-setup-karma.js';
-import './gr-upload-help-dialog.js';
-
-const basicFixture = fixtureFromElement('gr-upload-help-dialog');
-
-suite('gr-upload-help-dialog tests', () => {
-  let element;
-
-  setup(() => {
-    element = basicFixture.instantiate();
-  });
-
-  test('constructs push command from branch', () => {
-    element.targetBranch = 'foo';
-    assert.equal(element._pushCommand, 'git push origin HEAD:refs/for/foo');
-
-    element.targetBranch = 'master';
-    assert.equal(element._pushCommand,
-        'git push origin HEAD:refs/for/master');
-  });
-
-  suite('fetch command', () => {
-    const testRev = {
-      fetch: {
-        http: {
-          commands: {
-            Checkout: 'http checkout',
-            Pull: 'http pull',
-          },
-        },
-        ssh: {
-          commands: {
-            Pull: 'ssh pull',
-          },
-        },
-      },
-    };
-
-    test('null cases', () => {
-      assert.isUndefined(element._computeFetchCommand());
-      assert.isUndefined(element._computeFetchCommand({}));
-      assert.isUndefined(element._computeFetchCommand({fetch: null}));
-      assert.isUndefined(element._computeFetchCommand({fetch: {}}));
-    });
-
-    test('revision not defined', () => {
-      assert.isUndefined(
-          element._computeFetchCommand(undefined, ''));
-    });
-
-    test('insufficiently defined scheme', () => {
-      assert.isUndefined(
-          element._computeFetchCommand(testRev, 'badscheme'));
-
-      const rev = {...testRev};
-      rev.fetch = {...testRev.fetch, nocmds: {commands: {}}};
-      assert.isUndefined(
-          element._computeFetchCommand(rev, 'nocmds'));
-
-      rev.fetch.nocmds.commands.unsupported = 'unsupported';
-      assert.isUndefined(
-          element._computeFetchCommand(rev, 'nocmds'));
-    });
-
-    test('default scheme and command', () => {
-      const cmd = element._computeFetchCommand(testRev, '');
-      assert.isTrue(cmd === 'http checkout' || cmd === 'ssh pull');
-    });
-
-    test('default command', () => {
-      assert.strictEqual(
-          element._computeFetchCommand(testRev, 'http'),
-          'http checkout');
-      assert.strictEqual(
-          element._computeFetchCommand(testRev, 'ssh'),
-          'ssh pull');
-    });
-  });
-});
-
diff --git a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
index 85931b4..746d101 100644
--- a/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
+++ b/polygerrit-ui/app/mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.ts
@@ -837,8 +837,9 @@
           // mark-reviewed and then press ] to go to the next file'.
           (tagName === 'INPUT' && type !== 'checkbox') ||
           tagName === 'TEXTAREA' ||
-          // Suppress shortcuts if the key is 'enter' and target is an anchor.
-          (e.keyCode === 13 && tagName === 'A')
+          // Suppress shortcuts if the key is 'enter'
+          // and target is an anchor or button.
+          (e.keyCode === 13 && (tagName === 'A' || tagName === 'BUTTON'))
         ) {
           return true;
         }
diff --git a/polygerrit-ui/app/utils/change-metadata-util.ts b/polygerrit-ui/app/utils/change-metadata-util.ts
index c3eb846..d39b10b 100644
--- a/polygerrit-ui/app/utils/change-metadata-util.ts
+++ b/polygerrit-ui/app/utils/change-metadata-util.ts
@@ -41,11 +41,11 @@
     Metadata.REVIEWERS,
     Metadata.REPO_BRANCH,
     Metadata.SUBMITTED,
+    Metadata.TOPIC,
   ],
   SHOW_IF_SET: [
     Metadata.CC,
     Metadata.HASHTAGS,
-    Metadata.TOPIC,
     Metadata.UPLOADER,
     Metadata.AUTHOR,
     Metadata.COMMITTER,