Merge branch 'stable-3.1-2021-07'

* stable-3.1-2021-07:
  Update Gitiles plugin
  IncludedIn: filter out non-visible branches
  Point gitiles submodule to gitiles security fix repo

Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I7298bc114f89564dbf019ea0bebbc10bc5575002
diff --git a/.bazelignore b/.bazelignore
index 30f1613..69c04b1 100644
--- a/.bazelignore
+++ b/.bazelignore
@@ -1 +1,2 @@
 eclipse-out
+node_modules
diff --git a/.bazelproject b/.bazelproject
index e14c108..a7f5450 100644
--- a/.bazelproject
+++ b/.bazelproject
@@ -22,3 +22,12 @@
 
 build_flags:
   --javacopt=-g
+
+additional_languages:
+  javascript
+  typescript
+
+ts_config_rules:
+  //tools/node_tools/node_modules_licenses:tsconfig_editor
+  //tools/node_tools/polygerrit_app_preprocessor:preprocessor_tsconfig.json
+  //polygerrit-ui/app/node_modules_licenses:tsconfig_editor
diff --git a/.bazelrc b/.bazelrc
index e560f2397..aece2e0 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -11,6 +11,10 @@
 # this flag here once flipped in Bazel again.
 build --incompatible_strict_action_env
 
+# Workaround Bazel worker crash (remove after upgrading to 4.1.0)
+# https://github.com/bazelbuild/bazel/issues/13333
+build --experimental_worker_multiplex=false
+
 test --build_tests_only
 test --test_output=errors
 
diff --git a/.gitignore b/.gitignore
index fb53fc6..1e91c8f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 # Keep following lines sorted according to `LC_COLLATE=C sort`
 *.eml
 *.iml
+*.log
 *.pyc
 *.sublime-*
 *.swp
diff --git a/.gitmodules b/.gitmodules
index 2e39ff2..6f493f0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -56,3 +56,8 @@
 	path = plugins/webhooks
 	url = ../plugins/webhooks
 	branch = .
+
+[submodule "polymer-bridges"]
+	path = polymer-bridges
+	url = ../polymer-bridges
+	branch = .
diff --git a/.gitreview b/.gitreview
index 9df7aae..dc05242 100644
--- a/.gitreview
+++ b/.gitreview
@@ -2,4 +2,4 @@
 host=gerrit-review.googlesource.com
 scheme=https
 project=gerrit.git
-defaultbranch=stable-3.1
+defaultbranch=master
diff --git a/.zuul.yaml b/.zuul.yaml
index fe9dc80..d6dbc34 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -30,6 +30,7 @@
       - plugins/reviewnotes
       - plugins/singleusergroup
       - plugins/webhooks
+      - polymer-bridges
 
 - project:
     check:
diff --git a/Documentation/BUILD b/Documentation/BUILD
index 52ab7a8..11d3efa 100644
--- a/Documentation/BUILD
+++ b/Documentation/BUILD
@@ -42,6 +42,9 @@
 
 license_map(
     name = "licenses",
+    json_maps = [
+        "//polygerrit-ui/app/node_modules_licenses:polygerrit-licenses.json",
+    ],
     opts = ["--asciidoctor"],
     targets = [
         "//polygerrit-ui/app:polygerrit_ui",
@@ -51,6 +54,9 @@
 
 license_map(
     name = "js_licenses",
+    json_maps = [
+        "//polygerrit-ui/app/node_modules_licenses:polygerrit-licenses.json",
+    ],
     targets = [
         "//polygerrit-ui/app:polygerrit_ui",
     ],
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 7961b7e..71c9330 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Access Controls
 
 Access controls in Gerrit are group based.  Every user account is a
@@ -7,10 +8,10 @@
 
 To view/edit the access controls for a specific project, first
 navigate to the projects page: for example,
-https://gerrit-review.googlesource.com/admin/repos/ . Then click on
+https://gerrit-review.googlesource.com/admin/repos/[role=external,window=_blank]. Then click on
 the individual project, and then click Access. This will bring you
 to a url that looks like
-https://gerrit-review.googlesource.com/admin/repos/gerrit,access
+https://gerrit-review.googlesource.com/admin/repos/gerrit,access[role=external,window=_blank]
 
 [[system_groups]]
 == System Groups
@@ -218,7 +219,7 @@
 `^refs/heads/[a-z]{1,8}` matches all lower case branch names
 between 1 and 8 characters long.  Within a regular expression `.`
 is a wildcard matching any character, but may be escaped as `\.`.
-The link:http://www.brics.dk/automaton/[dk.brics.automaton library]
+The link:http://www.brics.dk/automaton/[dk.brics.automaton library,role=external,window=_blank]
 is used for evaluation of regular expression access control
 rules. See the library documentation for details on this
 particular regular expression flavor. One quirk is that the
@@ -779,6 +780,14 @@
 can still do the rebase locally and upload the rebased commit as a new
 patch set.
 
+[[category_revert]]
+=== Revert
+
+This category permits users to revert changes via the web UI by pushing
+the `Revert Change` button.
+
+Users without this access right who are able to upload changes can
+still do the revert locally and upload the revert commit as a new change.
 
 [[category_remove_reviewer]]
 === Remove Reviewer
@@ -987,7 +996,7 @@
 to build and then leave a verdict somehow.
 
 As an example, the popular
-link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[gerrit-trigger plugin]
+link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[gerrit-trigger plugin,role=external,window=_blank]
 for Jenkins/Hudson can set labels at:
 
 * The start of a build
@@ -1318,7 +1327,9 @@
 
 Allow group creation.  Groups are used to grant users access to different
 actions in projects.  This capability allows the granted group members to
-either link:cmd-create-group.html[create new groups via ssh] or via the web UI.
+either link:cmd-create-group.html[create new groups via ssh] or via the web UI
+by navigating at the top of the page to BROWSE -> Groups, and then pushing the
+"CREATE NEW" button.
 
 
 [[capability_createProject]]
diff --git a/Documentation/backup.txt b/Documentation/backup.txt
index 7220c74..dd47035 100644
--- a/Documentation/backup.txt
+++ b/Documentation/backup.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Backup
 
 A Gerrit Code Review site contains data that needs to be backed up regularly.
@@ -47,7 +48,7 @@
 +
 If you have chosen to use _Elastic Search_ for indexing,
 refer to its
-link:https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html[backup documentation].
+link:https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html[backup documentation,role=external,window=_blank].
 
 [#optional-backup-cache]
 Caches::
@@ -70,7 +71,7 @@
 * public and private SSH host keys
 +
 You may consider to use the
-link:https://gerrit.googlesource.com/plugins/secure-config/[secure-config plugin]
+link:https://gerrit.googlesource.com/plugins/secure-config/[secure-config plugin,role=external,window=_blank]
 to encrypt these secrets.
 
 [#optional-backup-plugin-data]
@@ -145,7 +146,7 @@
 backup. This means read-access is still available from replica servers during
 backup, because only write operations have to be stopped to ensure consistency.
 This can be implemented using the
-link:https://gerrit.googlesource.com/plugins/readonly/[_readonly_] plugin.
+link:https://gerrit.googlesource.com/plugins/readonly/[_readonly_,role=external,window=_blank] plugin.
 
 [#cons-backup-replicate]
 === Replicate data for backup
@@ -157,9 +158,9 @@
 Replicate all git repositories to another file system using
 `git clone --mirror`,
 or the
-link:https://gerrit.googlesource.com/plugins/replication[replication plugin]
+link:https://gerrit.googlesource.com/plugins/replication[replication plugin,role=external,window=_blank]
 or the
-link:https://gerrit.googlesource.com/plugins/pull-replication[pull-replication plugin].
+link:https://gerrit.googlesource.com/plugins/pull-replication[pull-replication plugin,role=external,window=_blank].
 Best you use a filesystem supporting snapshots to create a backup archive
 of such a replica.
 
@@ -174,7 +175,7 @@
 Do not skip backing up the replica, the replica alone IS NOT a backup.
 Imagine someone deleted a project by mistake and this deletion got replicated.
 Replication of repository deletions can be switched off using the
-link:https://gerrit.googlesource.com/plugins/replication/+/refs/heads/master/src/main/resources/Documentation/config.md[server option]
+link:https://gerrit.googlesource.com/plugins/replication/+/refs/heads/master/src/main/resources/Documentation/config.md[server option,role=external,window=_blank]
 `remote.NAME.replicateProjectDeletions`.
 
 If you are using Gerrit replica to offload read traffic you can use one of these
@@ -197,13 +198,13 @@
 Filesystems supporting copy on write snapshots::
 +
 Use a file system supporting copy-on-write snapshots like
-link:https://btrfs.wiki.kernel.org/index.php/SysadminGuide#Snapshots[btrfs]
+link:https://btrfs.wiki.kernel.org/index.php/SysadminGuide#Snapshots[btrfs,role=external,window=_blank]
 or
-https://wiki.debian.org/ZFS#Snapshots[zfs].
+https://wiki.debian.org/ZFS#Snapshots[zfs,role=external,window=_blank].
 
 
 Other filesystems supporting snapshots::
-https://wiki.archlinux.org/index.php/LVM#Snapshots[lvm] or nfs.
+https://wiki.archlinux.org/index.php/LVM#Snapshots[lvm,role=external,window=_blank] or nfs.
 +
 Create a snapshot and then archive the snapshot to another storage.
 +
@@ -259,7 +260,7 @@
 [#backup-dr-multi-site]
 === Multi-site setup
 
-Use the https://gerrit.googlesource.com/plugins/multi-site[multi-site plugin]
+Use the https://gerrit.googlesource.com/plugins/multi-site[multi-site plugin,role=external,window=_blank]
 to install Gerrit with multiple sites installed in different datacenters
 across different regions. This ensures that in case of a severe problem with
 one of the sites, the other sites can still serve your repositories.
diff --git a/Documentation/cmd-hook-commit-msg.txt b/Documentation/cmd-hook-commit-msg.txt
index 49d5c17..2b6d7af 100644
--- a/Documentation/cmd-hook-commit-msg.txt
+++ b/Documentation/cmd-hook-commit-msg.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = commit-msg Hook
 
 
@@ -86,8 +87,8 @@
 
 
 * link:user-changeid.html[Change-Id Lines]
-* link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[git-commit(1)]
-* link:http://www.kernel.org/pub/software/scm/git/docs/githooks.html[githooks(5)]
+* link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[git-commit(1),role=external,window=_blank]
+* link:http://www.kernel.org/pub/software/scm/git/docs/githooks.html[githooks(5),role=external,window=_blank]
 
 == IMPLEMENTATION
 
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt
index edb54b5..8a970c5 100644
--- a/Documentation/cmd-index.txt
+++ b/Documentation/cmd-index.txt
@@ -94,6 +94,9 @@
 link:cmd-set-reviewers.html[gerrit set-reviewers]::
 	Add or remove reviewers on a change.
 
+link:cmd-set-topic.html[gerrit set-topic]::
+	Set the topic for a change.
+
 link:cmd-stream-events.html[gerrit stream-events]::
 	Monitor events occurring in real time.
 
@@ -178,6 +181,12 @@
 link:cmd-set-account.html[gerrit set-account]::
 	Change an account's settings.
 
+link:cmd-sequence-set.html[gerrit sequence set]::
+        Set new sequence value.
+
+link:cmd-sequence-show.html[gerrit sequence show]::
+	Display current sequence value.
+
 link:cmd-set-members.html[gerrit set-members]::
 	Set group members.
 
diff --git a/Documentation/cmd-sequence-set.txt b/Documentation/cmd-sequence-set.txt
new file mode 100644
index 0000000..9023ceb
--- /dev/null
+++ b/Documentation/cmd-sequence-set.txt
@@ -0,0 +1,54 @@
+= gerrit sequence set
+
+== NAME
+gerrit sequence set - Set new sequence value.
+
+== SYNOPSIS
+[verse]
+--
+_ssh_ -p <port> <host> _gerrit sequence set_ <NAME> <VALUE>
+--
+
+== DESCRIPTION
+Gerrit maintains the generation of the next available sequence numbers for
+account, group and change entities. The sequences are stored as UTF-8 text in
+a blob pointed to by the `refs/sequences/accounts`, `refs/sequences/groups`
+and `refs/sequences/changes` refs. Those refs are stored in `All-Users` and
+`All-Projects` git repositories correspondingly.
+
+This command allows to set a new sequence value for those sequences.
+
+The link:cmd-sequence-show.html[sequence-show] command displays current
+sequence value.
+
+== ACCESS
+Caller must be a member of the privileged 'Administrators' group.
+
+== SCRIPTING
+This command is intended to be used in scripts.
+
+== OPTIONS
+<NAME>::
+  Sequence name to set a new value for.
+  Currently supported values:
+    * accounts
+    * groups
+    * changes
+
+<VALUE>::
+  New value for the sequence.
+
+== EXAMPLES
+Set a new value for the 'changes' sequence:
+
+----
+$ ssh -p 29418 review.example.com gerrit sequence set changes 42
+The value for the changes sequence was set to 42.
+----
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/cmd-sequence-show.txt b/Documentation/cmd-sequence-show.txt
new file mode 100644
index 0000000..6b9371f
--- /dev/null
+++ b/Documentation/cmd-sequence-show.txt
@@ -0,0 +1,51 @@
+= gerrit sequence show
+
+== NAME
+gerrit sequence show - Display current sequence value.
+
+== SYNOPSIS
+[verse]
+--
+_ssh_ -p <port> <host> _gerrit sequence show_ <NAME>
+--
+
+== DESCRIPTION
+Gerrit maintains the generation of the next available sequence numbers for
+account, group and change entities. The sequences are stored as UTF-8 text in
+a blob pointed to by the `refs/sequences/accounts`, `refs/sequences/groups`
+and `refs/sequences/changes` refs. Those refs are stored in `All-Users` and
+`All-Projects` git repositories correspondingly.
+
+This command allows to display the current sequence value for those sequences.
+
+The link:cmd-sequence-set.html[sequence-set] command allows to set a new
+sequence value.
+
+== ACCESS
+Caller must be a member of the privileged 'Administrators' group.
+
+== SCRIPTING
+This command is intended to be used in scripts.
+
+== OPTIONS
+<NAME>::
+  Sequence name to show the current value for.
+  Currently supported values:
+    * accounts
+    * groups
+    * changes
+
+== EXAMPLES
+Display the current value for the 'changes' sequence:
+
+----
+$ ssh -p 29418 review.example.com gerrit sequence show changes
+42
+----
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/cmd-set-topic.txt b/Documentation/cmd-set-topic.txt
new file mode 100644
index 0000000..6ed1a49
--- /dev/null
+++ b/Documentation/cmd-set-topic.txt
@@ -0,0 +1,43 @@
+= gerrit set-topic
+
+== NAME
+gerrit set-topic - Set the topic for one or more changes.
+
+== SYNOPSIS
+[verse]
+--
+_ssh_ -p <port> <host> _gerrit set-topic_
+  <CHANGE>
+  [ --topic <TOPIC> | -t <TOPIC> ]
+--
+
+== DESCRIPTION
+Sets the topic for the specified changes.
+
+== ACCESS
+Caller must have the rights to modify the topic of the specified changes.
+
+== SCRIPTING
+This command is intended to be used in scripts.
+
+== OPTIONS
+<CHANGE>::
+	Required; change id.
+
+--topic::
+-topic::
+	Valid topic name to apply to the specified changes.
+
+== EXAMPLES
+Set the topic of the change "I6686e64a788365bd252df69ae5b3ec9d65aaf068" in "MyProject" on branch "master" to "MyTopic".
+
+----
+$ ssh -p 29418 user@review.example.com gerrit set-topic MyProject~master~I6686e64a788365bd252df69ae5b3ec9d65aaf068 --topic MyTopic
+----
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/concept-refs-for-namespace.txt b/Documentation/concept-refs-for-namespace.txt
index c8776ae..003a106 100644
--- a/Documentation/concept-refs-for-namespace.txt
+++ b/Documentation/concept-refs-for-namespace.txt
@@ -1,7 +1,8 @@
+:linkattrs:
 = The refs/for namespace
 
 When pushing a new or updated commit to Gerrit, you push that commit using a
-link:https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html#def_ref[reference],
+link:https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html#def_ref[reference,role=external,window=_blank],
 in the `refs/for` namespace. This reference must also define
 the target branch, such as `refs/for/[BRANCH_NAME]`.
 
diff --git a/Documentation/config-accounts.txt b/Documentation/config-accounts.txt
index 90150b1..67159f4 100644
--- a/Documentation/config-accounts.txt
+++ b/Documentation/config-accounts.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Accounts
 
 == Overview
@@ -6,10 +7,10 @@
 link:note-db.html[NoteDb].
 
 The account data consists of a sequence number (account ID), account
-properties (full name, preferred email, registration date, status,
-inactive flag), preferences (general, diff and edit preferences),
-project watches, SSH keys, external IDs, starred changes and reviewed
-flags.
+properties (full name, display name, preferred email, registration
+date, status, inactive flag), preferences (general, diff and edit
+preferences), project watches, SSH keys, external IDs, starred changes
+and reviewed flags.
 
 Most account data is stored in a special link:#all-users[All-Users]
 repository, which has one branch per user. Within the user branch there
@@ -143,7 +144,7 @@
 
 In addition it contains an
 link:https://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#.7E.2F.ssh.2Fauthorized_keys[
-authorized_keys] file with the link:#ssh-keys[SSH keys] of the account.
+authorized_keys,role=external,window=_blank] file with the link:#ssh-keys[SSH keys] of the account.
 
 [[account-properties]]
 === Account Properties
@@ -154,6 +155,7 @@
 ----
 [account]
   fullName = John Doe
+  displayName = John
   preferredEmail = john.doe@example.com
   status = OOO
   active = false
@@ -256,7 +258,7 @@
 SSH keys are stored in the user branch in an `authorized_keys` file,
 which is the
 link:https://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#.7E.2F.ssh.2Fauthorized_keys[
-standard OpenSSH file format] for storing SSH keys:
+standard OpenSSH file format,role=external,window=_blank] for storing SSH keys:
 
 ----
 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCgug5VyMXQGnem2H1KVC4/HcRcD4zzBqSuJBRWVonSSoz3RoAZ7bWXCVVGwchtXwUURD689wFYdiPecOrWOUgeeyRq754YWRhU+W28vf8IZixgjCmiBhaL2gt3wff6pP+NXJpTSA4aeWE5DfNK5tZlxlSxqkKOS8JRSUeNQov5Tw== john.doe@example.com
@@ -357,6 +359,15 @@
 * hashed passwords of external IDs with scheme `username` cannot be
   decoded
 
+Users can edit some external IDs via the user settings page or the
+REST API. Note that email addresses cannot be deleted if they are
+associated with the user's login credentials external ID, for
+example the email address associated with an OpenId or OAUTH external
+ID. If users wish to remove these email addresses from Gerrit they must
+first update the external authentication record in that system,
+log in to Gerrit, then Gerrit will update the external ID record with
+the new email address.
+
 [[starred-changes]]
 == Starred Changes
 
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index bcb13fe..0c0626e 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Configuration
 
 == File `etc/gerrit.config`
@@ -120,6 +121,27 @@
 +
 Default is `ALL`.
 
+[[accounts.defaultDisplayName]]accounts.defaultDisplayName::
++
+If a user account does not have a display name set, which is the normal
+case, then this configuration value chooses the strategy how to choose
+the display name. Note that this strategy is not applied by the backend.
+If the AccountInfo has the display name unset, then the client has to
+apply this strategy.
++
+If `FULL_NAME`, then the (full) name of the user is chosen from
+link:rest-api-accounts.html#account-info[AccountInfo].
++
+If `FIRST_NAME`, then the first word (i.e. everything until first
+whitespace character) of the (full) name of the user is chosen from
+link:rest-api-accounts.html#account-info[AccountInfo].
++
+If `USERNAME`, then the username of the user is chosen from
+link:rest-api-accounts.html#account-info[AccountInfo]. If that is not
+set, then the (full) name will be used.
++
+Default is `FULL_NAME`.
+
 [[addreviewer]]
 === Section addreviewer
 
@@ -174,7 +196,7 @@
 +
 The default setting.  Gerrit uses any valid OpenID
 provider chosen by the end-user.  For more information see
-http://openid.net/[openid.net].
+http://openid.net/[openid.net,role=external,window=_blank].
 +
 * `OpenID_SSO`
 +
@@ -286,7 +308,7 @@
 +
 Patterns may be either a
 link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
-Java regular expression (java.util.regex)] (start with `^` and
+Java regular expression (java.util.regex),role=external,window=_blank] (start with `^` and
 end with `$`) or be a simple prefix (any other string).
 +
 By default, the list contains two values, `http://` and `https://`,
@@ -304,7 +326,7 @@
 +
 Patterns may be either a
 link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
-Java regular expression (java.util.regex)] (start with `^` and
+Java regular expression (java.util.regex),role=external,window=_blank] (start with `^` and
 end with `$`) or be a simple prefix (any other string).
 +
 By default, the list contains two values, `http://` and `https://`,
@@ -711,7 +733,7 @@
 +
 Technically the H2 cache size is configured using the CACHE_SIZE parameter in
 the H2 JDBC connection URL, as described
-link:http://www.h2database.com/html/features.html#cache_settings[here]
+link:http://www.h2database.com/html/features.html#cache_settings[here,role=external,window=_blank]
 +
 Default is unset, using up to half of the available memory.
 +
@@ -724,7 +746,7 @@
 If set to true, enable H2 autoserver mode for the H2-backed persistent cache
 databases.
 +
-See link:http://www.h2database.com/html/features.html#auto_mixed_mode[here]
+See link:http://www.h2database.com/html/features.html#auto_mixed_mode[here,role=external,window=_blank]
 for detail.
 +
 Default is false.
@@ -834,6 +856,12 @@
 requires two HTTP requests, and this cache tries to carry state from
 the first request into the second to ensure it can complete.
 
+cache `"default_preferences"`::
++
+Caches the server's default general, edit and diff preferences.
++
+Default value is 1 to hold only the most current version in-memory.
+
 cache `"changes"`::
 +
 The size of `memoryLimit` determines the number of projects for which
@@ -960,6 +988,19 @@
 Caches the parent groups of a subgroup.  If direct updates are made
 to the `account_group_includes` table, this cache should be flushed.
 
+cache `"groups_external"`::
++
+Caches all the external groups available to Gerrit. The cache holds a
+single entry which maps to the latest available of all external groups'
+UUIDs. This cache uses "groups_external_persisted" to load its value.
+
+cache `"groups_external_persisted"`::
++
+Caches all external groups available to Gerrit at some point in history.
+The cache key is representation of a specific groups state in NoteDb and
+the value is the list of all external groups.
+The cache is persisted to enhance performance.
+
 cache `"ldap_groups"`::
 +
 Caches the LDAP groups that a user belongs to, if LDAP has been
@@ -1174,15 +1215,6 @@
 +
 Default is true.
 
-[[change.api.excludeMergeableInChangeInfo]]change.api.excludeMergeableInChangeInfo::
-+
-If true, the mergeability bit in
-link:rest-api-changes.html#change-info[ChangeInfo] will never be set. It can
-be requested separately through the
-link:rest-api-changes.html#get-mergeable[get-mergeable] endpoint.
-+
-Default is false.
-
 [[change.cacheAutomerge]]change.cacheAutomerge::
 +
 When reviewing merge commits, the left-hand side shows the output of the
@@ -1198,12 +1230,43 @@
 +
 Default is true.
 
+[[change.commentSizeLimit]]change.commentSizeLimit::
++
+Maximum allowed size in characters of a regular (non-robot) comment. Comments
+which exceed this size will be rejected. Size computation is approximate and may
+be off by roughly 1%. Common unit suffixes of 'k', 'm', or 'g' are supported.
+The value must be positive.
++
+The default limit is 16kiB.
+
+[[change.cumulativeCommentSizeLimit]]change.cumulativeCommentSizeLimit::
++
+Maximum allowed size in characters of all comments (including robot comments)
+and change messages. Size computation is approximate and may be off by roughly
+1%. Common unit suffixes of 'k', 'm', or 'g' are supported.
++
+The default limit is 3MiB.
+
 [[change.disablePrivateChanges]]change.disablePrivateChanges::
 +
 If set to true, users are not allowed to create private changes.
 +
 The default is false.
 
+[[change.enableAttentionSet]]change.enableAttentionSet::
++
+If set to true, then all UI features for using and interacting with the
+attention set are enabled.
++
+The default is false for now, but will be changed to true in Q2 2020.
+
+[[change.enableAssignee]]change.enableAssignee::
++
+If set to true, then all UI features for using and interacting with the
+assignee are enabled.
++
+The default is true for now, but will be changed to false in Q2 2020.
+
 [[change.largeChange]]change.largeChange::
 +
 Number of changed lines from which on a change is considered as a large
@@ -1215,6 +1278,13 @@
 +
 By default 500.
 
+[[change.maxComments]]change.maxComments::
++
+Maximum number of comments (regular plus robot) allowed per change. Additional
+comments are rejected.
++
+By default 5,000.
+
 [[change.maxUpdates]]change.maxUpdates::
 +
 Maximum number of updates to a change. Counts only updates to the main NoteDb
@@ -1226,14 +1296,43 @@
 high CPU usage, memory pressure, persistent cache bloat, and other problems.
 +
 The following operations are allowed even when a change is at the limit:
+
 * Abandon
 * Submit
 * Submit by push with `%submit`
 * Auto-close by pushing directly to the branch
 * Fix with link:rest-api-changes.html#fix-input[`expect_merged_as`]
-+
+
 By default 1000.
 
+[[change.mergeabilityComputationBehavior]]change.mergeabilityComputationBehavior::
++
+This setting determines when Gerrit computes if a change is mergeable or not.
+This computation is expensive, especially when the repository is large or when
+there are many open changes.
++
+This config can have the following states:
++
+* `API_REF_UPDATED_AND_CHANGE_REINDEX`: Gerrit indexes `mergeability` enabling
+  the `is:mergeable` predicate in change search and allowing fast retrieval of
+  this bit in query responses. Gerrit will always serve `mergeable` in
+  link:rest-api-changes.html#change-info[ChangeInfo] objects.
+  Gerrit will reindex all open changes when the target ref advances (expensive).
+* `REF_UPDATED_AND_CHANGE_REINDEX`: Gerrit indexes `mergeability` enabling the
+  `is:mergeable` predicate in change search and allowing fast retrieval of this
+  bit in query responses. Gerrit will never serve `mergeable` in
+  link:rest-api-changes.html#change-info[ChangeInfo]
+  objects. This state can be a final state for instances that only want to
+  optimize the read path, but not the write path for speed or serve as an
+  intermediary step for instances that want to optimize both and need to migrate
+  callers of their API.
+  Gerrit will reindex all open changes when the target ref advances (expensive).
+* `NEVER`: Gerrit does not index `mergeable`, so `is:mergeable` is disabled as
+  query operator. Gerrit does not serve `mergeable` in
+  link:rest-api-changes.html#change-info[ChangeInfo].
+
+Default is `REF_UPDATED_AND_CHANGE_REINDEX`.
+
 [[change.move]]change.move::
 +
 Whether the link:rest-api-changes.html#move-change[Move Change] REST
@@ -1268,13 +1367,12 @@
 
 [[change.robotCommentSizeLimit]]change.robotCommentSizeLimit::
 +
-Maximum allowed size of a robot comment that will be accepted. Robot comments
-which exceed the indicated size will be rejected on addition. The specified
-value is interpreted as the maximum size in bytes of the JSON representation of
-the robot comment. Common unit suffixes of 'k', 'm', or 'g' are supported.
-Zero or negative values allow robot comments of unlimited size.
+Maximum allowed size in characters of a robot comment. Robot comments which
+exceed this size will be rejected on addition. Size computation is approximate
+and may be off by roughly 1%. Common unit suffixes of 'k', 'm', or 'g' are
+supported. Zero or negative values allow robot comments of unlimited size.
 +
-The default limit is 1024kB.
+The default limit is 1MiB.
 
 [[change.showAssigneeInChangesTable]]change.showAssigneeInChangesTable::
 +
@@ -1396,9 +1494,16 @@
 
 [[changeCleanup.abandonIfMergeable]]changeCleanup.abandonIfMergeable::
 +
-Whether changes which are mergeable should be auto-abandoned.
+Whether changes which are mergeable should be auto-abandoned. When set
+to `false`, `-is:mergeable` is appended to the query used to find
+the changes to auto-abandon.
 +
-By default `true`.
+By default `true`, meaning mergeable changes are auto-abandoned.
++
+If
+link:#change.mergeabilityComputationBehavior[`change.mergeabilityComputationBehavior`]
+is set to `NEVER`, setting this option to `false` has no effect and it behaves
+as though it were set to `true`.
 
 [[changeCleanup.cleanupAccountPatchReview]]changeCleanup.cleanupAccountPatchReview::
 +
@@ -1729,7 +1834,7 @@
 +
 As explained in this
 link:http://codicesoftware.blogspot.com/2011/09/merge-recursive-strategy.html[
-blog], the recursive merge produces better results if the two commits
+blog,role=external,window=_blank], the recursive merge produces better results if the two commits
 that are merged have more than one common predecessor.
 +
 Default is true.
@@ -2148,6 +2253,12 @@
 Path for PolyGerrit's favicon after link:#gerrit.canonicalWebUrl[default URL],
 including icon name and extension (.ico should be used).
 
+[[gerrit.instanceId]]gerrit.instanceId::
++
+Optional identifier for this Gerrit instance.
+Used to identify a specific instance within a group of Gerrit instances with the
+same `serverId` (i.e.: a Gerrit cluster).
+Unlike `instanceName` this value is not available in the email templates.
 
 [[gerrit.instanceName]]gerrit.instanceName::
 +
@@ -2311,9 +2422,9 @@
 branch names. Some web servers, such as Tomcat, reject this hexadecimal
 encoding in the URL.
 +
-Some alternative gitweb services, such as link:http://gitblit.com[Gitblit],
+Some alternative gitweb services, such as link:http://gitblit.com[Gitblit,role=external,window=_blank],
 allow using an alternative path separator character. In Gitblit, this can be
-configured through the property link:http://gitblit.com/properties.html[web.forwardSlashCharacter].
+configured through the property link:http://gitblit.com/properties.html[web.forwardSlashCharacter,role=external,window=_blank].
 In Gerrit, the alternative path separator can be configured correspondingly
 using the property `gitweb.pathSeparator`.
 +
@@ -2365,6 +2476,40 @@
 when this parameter is removed and the system group uses the default
 name again.
 
+[[has-operand-alias]]
+=== Section has operand alias
+
+'has' operand aliasing allows global aliases to be defined for query
+'has' operands. Currently only change queries are supported. The alias
+name is the git config key name, and the 'has' operand being aliased
+is the git config value.
+
+For example:
+
+----
+[has-operand-alias "change"]
+  oldtopic = topic
+----
+
+This section is particularly useful to alias 'has' operands (which may
+be long and clunky as they include a plugin name in them) to shorter
+operands without the plugin name. Admins should take care to choose
+shorter operands that are unique and unlikely to conflict in the future.
+
+Aliases are resolved dynamically at invocation time to the currently
+loaded version of plugins. If a referenced plugin is not loaded, or
+does not define the command, "unsupported operand" is returned to the
+user.
+
+Aliases will override existing 'has' operands. In case of multiple
+aliases with same name, the last one defined will be used.
+
+When the target of an alias does not exist, the 'has' operand with the
+name of the alias will be used (if present). This enables an admin to
+configure the system to override a core 'has' operand with an operand
+provided by a plugin when present and otherwise fall back to the 'has'
+operand provided by core.
+
 [[http]]
 === Section http
 
@@ -2463,7 +2608,7 @@
 Like `http://`, but additional header parsing features are
 enabled to honor `X-Forwarded-For`, `X-Forwarded-Host` and
 `X-Forwarded-Server`.  These headers are typically set by Apache's
-link:https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers[mod_proxy].
+link:https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers[mod_proxy,role=external,window=_blank].
 +
 [NOTE]
 --
@@ -2739,6 +2884,28 @@
 	filterClass = org.anyorg.MySecureIPFilter
 ----
 
+[[filterClass.className.initParam]]filterClass.<className>.initParam::
++
+Gerrit supports customized pluggable HTTP filters as `filterClass`. This
+option allows to pass extra initialization parameters to the filter. It
+allows for multiple key/value pairs to be passed in this pattern:
++
+----
+initParam = <key>=<value>
+----
+For a comprehensive example:
++
+----
+[httpd]
+	filterClass = org.anyorg.AFilter
+	filterClass = org.anyorg.BFilter
+[filterClass "org.anyorg.AFilter"]
+	key1 = value1
+	key2 = value2
+[filterClass "org.anyorg.BFilter"]
+	key3 = value3
+----
+
 [[httpd.idleTimeout]]httpd.idleTimeout::
 +
 Maximum idle time for a connection, which roughly translates to the
@@ -2793,7 +2960,7 @@
 +
 * `ELASTICSEARCH` look into link:#elasticsearch[Elasticsearch section]
 +
-An link:https://www.elastic.co/products/elasticsearch[Elasticsearch] index is
+An link:https://www.elastic.co/products/elasticsearch[Elasticsearch,role=external,window=_blank] index is
 used. Refer to the link:#elasticsearch[Elasticsearch section] for further
 configuration details.
 
@@ -2864,19 +3031,6 @@
 +
 Defaults to 1024.
 
-[[index.reindexAfterRefUpdate]]index.reindexAfterRefUpdate::
-+
-Whether to reindex all affected open changes after a ref is updated. This
-includes reindexing all open changes to recompute the "mergeable" bit every time
-the destination branch moves, as well as reindexing changes to take into account
-new project configuration (e.g. label definitions).
-+
-Leaving this enabled may result in fresher results, but may cause performance
-problems if there are lots of open changes on a project whose branches advance
-frequently.
-+
-Defaults to true.
-
 [[index.autoReindexIfStale]]index.autoReindexIfStale::
 +
 Whether to automatically check if a document became stale in the index
@@ -2954,7 +3108,7 @@
 Determines the amount of RAM that may be used for buffering added documents
 and deletions before they are flushed to the index.  See the
 link:http://lucene.apache.org/core/4_6_0/core/org/apache/lucene/index/LiveIndexWriterConfig.html#setRAMBufferSizeMB(double)[
-Lucene documentation] for further details.
+Lucene documentation,role=external,window=_blank] for further details.
 +
 Defaults to 16M.
 
@@ -2964,7 +3118,7 @@
 in-memory documents are flushed to the index. Large values generally
 give faster indexing.  See the
 link:http://lucene.apache.org/core/4_6_0/core/org/apache/lucene/index/LiveIndexWriterConfig.html#setMaxBufferedDocs(int)[
-Lucene documentation] for further details.
+Lucene documentation,role=external,window=_blank] for further details.
 +
 Defaults to -1, meaning no maximum is set and the writer will flush
 according to RAM usage.
@@ -2997,7 +3151,7 @@
 completed.  Note that Lucene will only run the smallest maxThreadCount merges
 at a time. See the
 link:https://lucene.apache.org/core/5_5_0/core/org/apache/lucene/index/ConcurrentMergeScheduler.html#setDefaultMaxMergesAndThreads(boolean)[
-Lucene documentation] for further details.
+Lucene documentation,role=external,window=_blank] for further details.
 +
 Defaults to -1 for (auto detection).
 
@@ -3007,13 +3161,13 @@
 Determines the max number of simultaneous Lucene merge threads that should be running at
 once. This must be less than or equal to maxMergeCount. See the
 link:https://lucene.apache.org/core/5_5_0/core/org/apache/lucene/index/ConcurrentMergeScheduler.html#setDefaultMaxMergesAndThreads(boolean)[
-Lucene documentation] for further details.
+Lucene documentation,role=external,window=_blank] for further details.
 +
 For further details on Lucene index configuration (auto detection) which
 affects maxThreadCount and maxMergeCount settings.
 See the
 link:https://lucene.apache.org/core/5_5_0/core/org/apache/lucene/index/ConcurrentMergeScheduler.html#AUTO_DETECT_MERGES_AND_THREADS[
-Lucene documentation]
+Lucene documentation,role=external,window=_blank]
 +
 Defaults to -1 for (auto detection).
 
@@ -3024,7 +3178,7 @@
 on is used to adaptively rate limit writes bytes/sec to the minimal rate necessary
 so merges do not fall behind. See the
 link:https://lucene.apache.org/core/5_5_0/core/org/apache/lucene/index/ConcurrentMergeScheduler.html#enableAutoIOThrottle()[
-Lucene documentation] for further details.
+Lucene documentation,role=external,window=_blank] for further details.
 +
 Defaults to true (throttling enabled).
 
@@ -3054,7 +3208,7 @@
 
 WARNING: Support for Elasticsearch is still experimental and is not recommended
 for production use. For compatibility information, please refer to the
-link:https://www.gerritcodereview.com/elasticsearch.html[project homepage].
+link:https://www.gerritcodereview.com/elasticsearch.html[project homepage,role=external,window=_blank].
 
 Note that when Gerrit is configured to use Elasticsearch, the Elasticsearch
 server(s) must be reachable during the site initialization.
@@ -3083,7 +3237,7 @@
 +
 Sets the number of shards to use per index. Refer to the
 link:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#_static_index_settings[
-Elasticsearch documentation] for details.
+Elasticsearch documentation,role=external,window=_blank] for details.
 +
 Defaults to 1.
 
@@ -3091,7 +3245,7 @@
 +
 Sets the number of replicas to use per index. Refer to the
 link:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#dynamic-index-settings[
-Elasticsearch documentation] for details.
+Elasticsearch documentation,role=external,window=_blank] for details.
 +
 Defaults to 1.
 
@@ -3099,7 +3253,7 @@
 +
 Sets the maximum value of `from + size` for searches to use per index. Refer to the
 link:https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#dynamic-index-settings[
-Elasticsearch documentation] for details.
+Elasticsearch documentation,role=external,window=_blank] for details.
 +
 Defaults to 10000.
 
@@ -3109,7 +3263,7 @@
 Note that the same username and password are used for all servers.
 
 For further information about Elasticsearch security, please refer to
-link:https://www.elastic.co/guide/en/elasticsearch/reference/current/security-getting-started.html[the documentation].
+link:https://www.elastic.co/guide/en/elasticsearch/reference/current/security-getting-started.html[the documentation,role=external,window=_blank].
 This is the current documentation link. Select another Elasticsearch version
 from the dropdown menu available on that page if need be.
 
@@ -3138,7 +3292,7 @@
 events.
 +
 This can be set to the set of minimal options that consumers of Gerrit's
-events need. A minimal set would be (`SKIP_MERGEABLE`,`SKIP_DIFFSTAT`).
+events need. A minimal set would be (`SKIP_DIFFSTAT`).
 +
 Every option that gets added here will have a performance impact. The
 general recommendation is therefore to set this to a minimal set of
@@ -3162,8 +3316,8 @@
 the parameters introduced here.  Suitable defaults for most
 parameters are automatically guessed based on the type of server
 detected during startup.  The guessed defaults support
-link:http://www.ietf.org/rfc/rfc2307.txt[RFC 2307], Active
-Directory and link:https://www.freeipa.org[FreeIPA].
+link:http://www.ietf.org/rfc/rfc2307.txt[RFC 2307,role=external,window=_blank], Active
+Directory and link:https://www.freeipa.org[FreeIPA,role=external,window=_blank].
 
 ----
 [ldap]
@@ -3517,8 +3671,8 @@
 garbage collected), the connection is returned to the pool for future use.
 +
 For details, see link:http://docs.oracle.com/javase/tutorial/jndi/ldap/pool.html[
-LDAP connection management (Pool)] and link:http://docs.oracle.com/javase/tutorial/jndi/ldap/config.html[
-LDAP connection management (Configuration)]
+LDAP connection management (Pool),role=external,window=_blank] and link:http://docs.oracle.com/javase/tutorial/jndi/ldap/config.html[
+LDAP connection management (Configuration),role=external,window=_blank]
 +
 By default, false.
 
@@ -3537,7 +3691,7 @@
 ldap.useConnectionPooling] configuration property to `true`, the connection pool
 can be configured using JVM system properties as explained in the
 link:http://docs.oracle.com/javase/7/docs/technotes/guides/jndi/jndi-ldap.html#POOL[
-Java SE Documentation].
+Java SE Documentation,role=external,window=_blank].
 
 For standalone Gerrit (running with the embedded Jetty), JVM system properties
 are specified in the link:#container[container section]:
@@ -3555,7 +3709,7 @@
 +
 The name of a plugin which serves the
 link:https://github.com/github/git-lfs/blob/master/docs/api/v1/http-v1-batch.md[
-LFS protocol] on the `<project-name>/info/lfs/objects/batch` endpoint. When
+LFS protocol,role=external,window=_blank] on the `<project-name>/info/lfs/objects/batch` endpoint. When
 not configured Gerrit will respond with `501 Not Implemented` on LFS protocol
 requests.
 +
@@ -3678,6 +3832,39 @@
 +
 Default is false.
 
+[[operator-alias]]
+=== Section operator alias
+
+Operator aliasing allows global aliases to be defined for query operators.
+Currently only change queries are supported. The alias name is the git
+config key name, and the operator being aliased is the git config value.
+
+For example:
+
+----
+[operator-alias "change"]
+  oldage = age
+  number = change
+----
+
+This section is particularly useful to alias operator names which may be
+long and clunky because they include a plugin name in them to a shorter
+name without the plugin name.
+
+Aliases are resolved dynamically at invocation time to any currently
+loaded versions of plugins. If the alias points to an operator provided
+by a plugin which is not currently loaded, or the plugin does not define
+the operator, then "unsupported operator" is returned to the user.
+
+Aliases will override existing operators. In the case of multiple aliases
+with the same name, the last one defined will be used.
+
+When the target of an alias doesn't exist, the operator with the name
+of the alias will be used (if present). This enables an admin to config
+the system to override a core operator with an operator provided by a
+plugin when present and otherwise fall back to the operator provided by
+core.
+
 [[pack]]
 === Section pack
 
@@ -3832,6 +4019,19 @@
 +
 Default is true.
 
+[[receive.enableInMemoryRefCache]]receive.enableInMemoryRefCache::
++
+If true, Gerrit will cache all refs advertised during push in memory and
+base later receive operations on that cache.
++
+Turning this cache off is considered experimental.
++
+This cache provides value when the ref database is slow and/or does not
+offer an inverse lookup of object ID to ref name. When RefTable is used,
+this cache can be turned off (experimental) to get speed improvements.
++
+Default is true.
+
 [[receive.enableSignedPush]]receive.enableSignedPush::
 +
 If true, server-side signed push validation is enabled.
@@ -3933,7 +4133,7 @@
 +
 Trust signatures can be added to a key using the `tsign` command to
 link:https://www.gnupg.org/documentation/manuals/gnupg/OpenPGP-Key-Management.html[
-`gpg --edit-key`], after which the signed key should be re-uploaded.
+`gpg --edit-key`,role=external,window=_blank], after which the signed key should be re-uploaded.
 +
 If no keys are specified, web-of-trust checks are disabled. This is the
 default behavior.
@@ -4399,7 +4599,7 @@
 [[sendemail.allowTLD]]sendemail.allowTLD::
 +
 List of custom TLDs to allow sending emails to in addition to those specified
-in the link:http://data.iana.org/TLD/[IANA list].
+in the link:http://data.iana.org/TLD/[IANA list,role=external,window=_blank].
 +
 Defaults to an empty list, meaning no additional TLDs are allowed.
 
@@ -4817,6 +5017,17 @@
 used for suggesting accounts when adding members to a group.
 +
 By default 0.
+[[suggest.relevantChanges]]suggest.relevantChanges::
++
+When suggesting reviewers, we go over recent changes of the user, and
+give priority to users that are present as reviewers in any of those
+changes. The number of changes we go over is `sugggest.relevantChanges`.
++
+This nubmer is a tradeoff between speed and accuracy.
+A high number would be accurate but slow, and a low number would be
+fast but inaccurate.
++
+By default 50.
 
 [[tracing]]
 === Section tracing
@@ -4925,7 +5136,7 @@
 [[trackingid.name.match]]trackingid.<name>.match::
 +
 A link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
-Java regular expression (java.util.regex)] used to match the
+Java regular expression (java.util.regex),role=external,window=_blank] used to match the
 external tracking id part of the footer line. The match can
 result in several entries in the DB.  If grouping is used in the
 regex the first group will be interpreted as the tracking id.
@@ -5221,7 +5432,13 @@
 login as the 'Gerrit Code Review' user, required for the link:cmd-suexec.html[suexec]
 command.
 
-The format is one Base-64 encoded public key per line.
+The format is one Base-64 encoded public key per line with optional comment, e.g.:
+----
+# Comments allowed at start of line
+AAAAC3...51R== john@example.net
+# Another comment
+AAAAB5...21S== jane@example.net
+----
 
 === Configurable Parameters
 
diff --git a/Documentation/config-gitweb.txt b/Documentation/config-gitweb.txt
index d49acfee..46c9ced 100644
--- a/Documentation/config-gitweb.txt
+++ b/Documentation/config-gitweb.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 == Gitweb Integration
 
 Gerrit Code Review can manage and generate hyperlinks to gitweb,
@@ -167,21 +168,21 @@
 Instructions are available for installing the gitweb module distributed with
 MsysGit:
 
-link:https://github.com/msysgit/msysgit/wiki/GitWeb[GitWeb]
+link:https://github.com/msysgit/msysgit/wiki/GitWeb[GitWeb,role=external,window=_blank]
 
 If you don't have Apache installed, you can download the appropriate build for
 Windows from link:http://www.apachelounge.com/download[apachelounge.org].
 
 After you have installed Apache, you will want to create a link:http://httpd.apache.org/docs/2.0/platform/windows.html#winsvc[new service user
-account] to use with Apache.
+account,role=external,window=_blank] to use with Apache.
 
 If you're still having difficulty setting up permissions, you may find this
 tech note useful for configuring Apache Service to run under another account.
-You must grant the new account link:http://technet.microsoft.com/en-us/library/cc794944(WS.10).aspx["run as service"] permission:
+You must grant the new account link:http://technet.microsoft.com/en-us/library/cc794944(WS.10).aspx["run as service",role=external,window=_blank] permission:
 
 The gitweb version in msysgit is missing several important and required
 perl modules, including CGI.pm. The perl included with the msysgit distro 1.7.8
-is broken.. The link:http://groups.google.com/group/msysgit/browse_thread/thread/ba3501f1f0ed95af[unicore folder is missing along with utf8_heavy.pl and CGI.pm]. You can
+is broken.. The link:http://groups.google.com/group/msysgit/browse_thread/thread/ba3501f1f0ed95af[unicore folder is missing along with utf8_heavy.pl and CGI.pm,role=external,window=_blank]. You can
 verify by checking for perl modules. From an msys console, execute the
 following to check:
 
@@ -202,7 +203,7 @@
 If you're missing CGI.pm, you'll have to deploy the module to the msys
 environment: You will have to retrieve them from the 5.8.8 distro on :
 
-http://strawberryperl.com/releases.html
+http://strawberryperl.com/releases.html[role=external,window=_blank]
 
 File: strawberry-perl-5.8.8.3.zip
 
@@ -272,7 +273,7 @@
 === SEE ALSO
 
 * link:config-gerrit.html#gitweb[Section gitweb]
-* link:http://git.zx2c4.com/cgit/about/[cgit]
+* link:http://git.zx2c4.com/cgit/about/[cgit,role=external,window=_blank]
 
 GERRIT
 ------
diff --git a/Documentation/config-hooks.txt b/Documentation/config-hooks.txt
index 835ec11..7d8112c 100644
--- a/Documentation/config-hooks.txt
+++ b/Documentation/config-hooks.txt
@@ -1,9 +1,10 @@
+:linkattrs:
 = Gerrit Code Review - Hooks
 
 Gerrit does not run any of the standard git hooks in the repositories
 it works with, but it does have its own hook mechanism included via
 the link:https://gerrit-review.googlesource.com/admin/repos/plugins/hooks[
-hooks plugin].
+hooks plugin,role=external,window=_blank].
 
 GERRIT
 ------
diff --git a/Documentation/config-labels.txt b/Documentation/config-labels.txt
index 193a96f..a3b9d0b 100644
--- a/Documentation/config-labels.txt
+++ b/Documentation/config-labels.txt
@@ -344,6 +344,13 @@
 
 Defaults to true.
 
+[[label_copyValue]]
+=== `label.Label-Name.copyValue`
+
+Value that should be copied forward when a new patch set is uploaded.
+This can be used to enable sticky votes. Can be specified multiple
+times. By default not set.
+
 [[label_canOverride]]
 === `label.Label-Name.canOverride`
 
diff --git a/Documentation/config-mail.txt b/Documentation/config-mail.txt
index 7d46e26..5d22c0b 100644
--- a/Documentation/config-mail.txt
+++ b/Documentation/config-mail.txt
@@ -1,6 +1,7 @@
+:linkattrs:
 = Gerrit Code Review - Mail Templates
 
-Gerrit uses link:https://developers.google.com/closure/templates/[Closure Templates]
+Gerrit uses link:https://developers.google.com/closure/templates/[Closure Templates,role=external,window=_blank]
 (Soy) for the bulk of the standard mails it sends out.
 There are builtin default templates which are used if they are not overridden.
 These defaults are also provided as examples so that administrators may copy
diff --git a/Documentation/config-plugins.txt b/Documentation/config-plugins.txt
index fb53937..272c4eb 100644
--- a/Documentation/config-plugins.txt
+++ b/Documentation/config-plugins.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Plugins
 
 The Gerrit server functionality can be extended by installing plugins.
@@ -25,10 +26,10 @@
 
 If you want to share your plugin under the link:licenses.html#Apache2_0[
 Apache License 2.0] you can host your plugin development on the
-link:https://gerrit-review.googlesource.com[gerrit-review] Gerrit
+link:https://gerrit-review.googlesource.com[gerrit-review,role=external,window=_blank] Gerrit
 Server. You can request the creation of a new Project by email
 to the link:https://groups.google.com/forum/#!forum/repo-discuss[Gerrit
-mailing list]. You would be assigned as project owner of the new plugin
+mailing list,role=external,window=_blank]. You would be assigned as project owner of the new plugin
 project so that you can submit changes on your own. It is the
 responsibility of the project owner to maintain the plugin, e.g. to
 make sure that it works with new Gerrit versions and to create stable
@@ -37,11 +38,9 @@
 [[core-plugins]]
 == Core Plugins
 
-Core plugins are packaged within the Gerrit war file and can easily be
-installed during the link:pgm-init.html[Gerrit initialization].
-
-The core plugins are developed and maintained by the Gerrit maintainers
-and the Gerrit community.
+link:dev-core-plugins.html[Core plugins] are packaged within the Gerrit
+war file and can easily be installed during the link:pgm-init.html[
+Gerrit initialization].
 
 Note that the documentation and configuration links in the list below are
 to the plugins' master branch. Please refer to the appropriate branch or
@@ -53,7 +52,7 @@
 CodeMirror plugin for polygerrit.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/codemirror-editor[
-Project] |
+Project,role=external,window=_blank] |
 
 [[commit-message-length-validator]]
 === commit-message-length-validator
@@ -63,11 +62,11 @@
 lengths are exceeded.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/commit-message-length-validator[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/commit-message-length-validator/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/commit-message-length-validator/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[delete-project]]
 === delete-project
@@ -75,11 +74,11 @@
 Provides the ability to delete a project.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/delete-project[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/delete-project/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/delete-project/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[download-commands]]
 === download-commands
@@ -88,11 +87,11 @@
 download schemes (for downloading via different network protocols).
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/download-commands[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/download-commands/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/download-commands/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[gitiles]]
 === gitiles
@@ -100,7 +99,7 @@
 Plugin running Gitiles alongside a Gerrit server.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/gitiles[
-Project]
+Project,role=external,window=_blank]
 
 [[hooks]]
 === hooks
@@ -108,11 +107,11 @@
 This plugin runs server-side hooks on events.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/hooks[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/hooks/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/hooks/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[plugin-manager]]
 === plugin-manager
@@ -122,11 +121,11 @@
 this can be changed per plugin configuration.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/plugin-manager[
-Project]
+Project,role=external,window=_blank]
 link:https://gerrit.googlesource.com/plugins/plugin-manager/+doc/master/src/main/resources/Documentation/about.md[
-Documentation]
+Documentation,role=external,window=_blank]
 link:https://gerrit.googlesource.com/plugins/plugin-manager/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[replication]]
 === replication
@@ -137,11 +136,11 @@
 backups, or a load-balanced public mirror farm.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/replication[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/replication/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/replication/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[reviewnotes]]
 === reviewnotes
@@ -150,9 +149,9 @@
 branch.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/reviewnotes[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/reviewnotes/+doc/master/src/main/resources/Documentation/about.md[
-Documentation]
+Documentation,role=external,window=_blank]
 
 [[singleusergroup]]
 === singleusergroup
@@ -167,11 +166,11 @@
 This plugin allows to propagate Gerrit events to remote http endpoints.
 
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/webhooks[
-Project] |
+Project,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/webhooks/+doc/master/src/main/resources/Documentation/about.md[
-Documentation] |
+Documentation,role=external,window=_blank] |
 link:https://gerrit.googlesource.com/plugins/webhooks/+doc/master/src/main/resources/Documentation/config.md[
-Configuration]
+Configuration,role=external,window=_blank]
 
 [[other-plugins]]
 == Other Plugins
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index 22d8a0d..a01df50 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -316,16 +316,19 @@
 The submit section includes configuration of project-specific
 submit settings:
 
-[[submit.mergeContent]]submit.mergeContent::
+[[content_merge]]submit.mergeContent::
 +
-Defines whether to automatically merge changes.  Valid values are 'true', 'false', or 'INHERIT'.
-Default is 'INHERIT'.
+Defines whether Gerrit will try to
+do a content merge when a path conflict occurs. Valid values are
+'true', 'false', or 'INHERIT'.  Default is 'INHERIT'. This option can
+be modified by any project owner through the project console, `Browse`
+> `Repositories` > my/project > `Allow content merges`.
 
 [[submit.action]]submit.action::
 +
-Defines the link:#submit-type[submit type].  Valid values are 'fast forward only',
-'merge if necessary', 'rebase if necessary', 'rebase always', 'merge always' and 'cherry pick'.
-The default is 'merge if necessary'.
+Defines the link:#submit-type[submit type].  Valid
+values are 'fast forward only', 'merge if necessary', 'rebase if necessary',
+'rebase always', 'merge always' and 'cherry pick'.  The default is 'merge if necessary'.
 
 [[submit.matchAuthorToCommitterDate]]submit.matchAuthorToCommitterDate::
 +
@@ -343,6 +346,99 @@
 is set to 'true' the merge would fail in such a case. An empty commit is still allowed as the
 initial commit on a branch.
 
+[[submit-type]]
+==== Submit Type
+
+'submit.action': The method Gerrit uses to submit a change to a project.
+
+The submit type can also be modified by any project owner through the
+project console, `Browse` > `Repositories` > my/project > 'Submit type'.
+In general, a submitting a change only merges the change if all its
+dependencies are also submitted, with exceptions documented below.
+
+The following submit types are supported:
+
+[[submit_type_inherit]]
+* Inherit
++
+This is the default for new projects, unless overridden by a global
+link:config-gerrit.html#repository.name.defaultSubmitType[`defaultSubmitType` option].
++
+Inherit the submit type from the parent project. In `All-Projects`, this
+is equivalent to link:#merge_if_necessary[Merge If Necessary].
+
+[[fast_forward_only]]
+* Fast Forward Only
++
+With this method Gerrit does not create merge commits on submitting a
+change. Merge commits may still be submitted, but they must be created
+on the client prior to uploading to Gerrit for review.
++
+To submit a change, the change must be a strict superset of the
+destination branch.  That is, the change must already contain the
+tip of the destination branch at submit time.
+
+[[merge_if_necessary]]
+* Merge If Necessary
++
+If the change being submitted is a strict superset of the destination
+branch, then the branch is fast-forwarded to the change.  If not,
+then a merge commit is automatically created.  This is identical
+to the classical `git merge` behavior, or `git merge --ff`.
+
+[[always_merge]]
+* Always Merge
++
+Always produce a merge commit, even if the change is a strict
+superset of the destination branch.  This is identical to the
+behavior of `git merge --no-ff`, and may be useful if the
+project needs to follow submits with `git log --first-parent`.
+
+[[cherry_pick]]
+* Cherry Pick
++
+Always cherry pick the patch set, ignoring the parent lineage
+and instead creating a brand new commit on top of the current
+branch head.
++
+When cherry picking a change, Gerrit automatically appends onto the
+end of the commit message a short summary of the change's approvals,
+and a URL link back to the change on the web.  The committer header
+is also set to the submitter, while the author header retains the
+original patch set author.
++
+Note that Gerrit ignores dependencies between changes when using this
+submit type unless
+link:config-gerrit.html#change.submitWholeTopic[`change.submitWholeTopic`]
+is enabled and depending changes share the same topic. So generally
+submitters must remember to submit changes in the right order when using this
+submit type. If all you want is extra information in the commit message,
+consider using the Rebase Always submit strategy.
+
+[[rebase_if_necessary]]
+* Rebase If Necessary
++
+If the change being submitted is a strict superset of the destination
+branch, then the branch is fast-forwarded to the change.  If not,
+then the change is automatically rebased and then the branch is
+fast-forwarded to the change.
++
+When Gerrit tries to do a merge, by default the merge will only
+succeed if there is no path conflict.  A path conflict occurs when
+the same file has also been changed on the other side of the merge.
+
+[[rebase_always]]
+* Rebase Always
++
+Basically, the same as Rebase If Necessary, but it creates a new patchset even
+if fast forward is possible AND like Cherry Pick it ensures footers such as
+Change-Id, Reviewed-On, and others are present in resulting commit that is
+merged.
++
+Thus, Rebase Always can be considered similar to Cherry Pick, but with
+the important distinction that Rebase Always does not ignore dependencies.
+
+
 [[access-section]]
 === Access section
 
@@ -479,100 +575,6 @@
 You can read more about the +rules.pl+ file and the prolog rules on
 link:prolog-cookbook.html[the Prolog cookbook page].
 
-[[submit-type]]
-=== Submit Type
-
-The method Gerrit uses to submit a change to a project can be
-modified by any project owner through the project console, `Projects` >
-`List` > my/project. In general, a submitted change is only merged if all
-its dependencies are also submitted, with exceptions documented below.
-The following submit types are supported:
-
-[[submit_type_inherit]]
-* Inherit
-+
-This is the default for new projects, unless overridden by a global
-link:config-gerrit.html#repository.name.defaultSubmitType[`defaultSubmitType` option].
-+
-Inherit the submit type from the parent project. In `All-Projects`, this
-is equivalent to link:#merge_if_necessary[Merge If Necessary].
-
-[[fast_forward_only]]
-* Fast Forward Only
-+
-With this method Gerrit does not create merge commits on submitting a
-change. Merge commits may still be submitted, but they must be created
-on the client prior to uploading to Gerrit for review.
-+
-To submit a change, the change must be a strict superset of the
-destination branch.  That is, the change must already contain the
-tip of the destination branch at submit time.
-
-[[merge_if_necessary]]
-* Merge If Necessary
-+
-If the change being submitted is a strict superset of the destination
-branch, then the branch is fast-forwarded to the change.  If not,
-then a merge commit is automatically created.  This is identical
-to the classical `git merge` behavior, or `git merge --ff`.
-
-[[always_merge]]
-* Always Merge
-+
-Always produce a merge commit, even if the change is a strict
-superset of the destination branch.  This is identical to the
-behavior of `git merge --no-ff`, and may be useful if the
-project needs to follow submits with `git log --first-parent`.
-
-[[cherry_pick]]
-* Cherry Pick
-+
-Always cherry pick the patch set, ignoring the parent lineage
-and instead creating a brand new commit on top of the current
-branch head.
-+
-When cherry picking a change, Gerrit automatically appends onto the
-end of the commit message a short summary of the change's approvals,
-and a URL link back to the change on the web.  The committer header
-is also set to the submitter, while the author header retains the
-original patch set author.
-+
-Note that Gerrit ignores dependencies between changes when using this
-submit type unless
-link:config-gerrit.html#change.submitWholeTopic[`change.submitWholeTopic`]
-is enabled and depending changes share the same topic. So generally
-submitters must remember to submit changes in the right order when using this
-submit type. If all you want is extra information in the commit message,
-consider using the Rebase Always submit strategy.
-
-[[rebase_if_necessary]]
-* Rebase If Necessary
-+
-If the change being submitted is a strict superset of the destination
-branch, then the branch is fast-forwarded to the change.  If not,
-then the change is automatically rebased and then the branch is
-fast-forwarded to the change.
-+
-When Gerrit tries to do a merge, by default the merge will only
-succeed if there is no path conflict.  A path conflict occurs when
-the same file has also been changed on the other side of the merge.
-
-[[rebase_always]]
-* Rebase Always
-+
-Basically, the same as Rebase If Necessary, but it creates a new patchset even
-if fast forward is possible AND like Cherry Pick it ensures footers such as
-Change-Id, Reviewed-On, and others are present in resulting commit that is
-merged.
-+
-Thus, Rebase Always can be considered similar to Cherry Pick, but with
-the important distinction that Rebase Always does not ignore dependencies.
-
-[[content_merge]]
-=== Allow content merges
-If `Allow content merges` is enabled, Gerrit will try
-to do a content merge when a path conflict occurs.
-
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/config-sso.txt b/Documentation/config-sso.txt
index 88de85e..37ab0c0 100644
--- a/Documentation/config-sso.txt
+++ b/Documentation/config-sso.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Single Sign-On Security
 
 Gerrit supports integration with some types of single sign-on
@@ -17,7 +18,7 @@
 As this is the default setting there is nothing required from the
 site administrator to make use of the OpenID authentication services.
 
-* http://openid.net/[openid.net]
+* http://openid.net/[openid.net,,role=external,window=_blank]
 
 If Jetty is being used, you may need to increase the header
 buffer size parameter, due to very long header lines.
@@ -34,7 +35,7 @@
 `auth.trustedOpenID` list in `gerrit.config`.  Patterns may be
 either a
 link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
-Java regular expression (java.util.regex)] (must start with `^`
+Java regular expression (java.util.regex),,role=external,window=_blank] (must start with `^`
 and end with `$`) or be a simple prefix (any other string).
 
 Out of the box Gerrit is configured to trust two patterns, which
@@ -65,12 +66,12 @@
 subsequent attempts to link that account with the existing account will fail.
 In cases where this happens, the administrator will need to manually merge the
 accounts.  See link:https://gerrit.googlesource.com/homepage/+/md-pages/docs/SqlMergeUserAccounts.md[
-Merging Gerrit User Accounts] on the Gerrit Wiki for details.
+Merging Gerrit User Accounts,,role=external,window=_blank] on the Gerrit Wiki for details.
 
 Linking another identity is also useful for users whose primary OpenID provider
 shuts down. For example Google
 link:https://developers.google.com/+/api/auth-migration[shut down their OpenID
-service on 20th April 2015]. Users who failed to add an alternative identity with
+service on 20th April 2015,,role=external,window=_blank]. Users who failed to add an alternative identity with
 another OpenID provider before that date will end up with their account only having
 a disabled Google identity. After creating a separate account with an alternative
 provider, they will need to ask the administrator to merge the accounts using the
diff --git a/Documentation/dev-bazel.txt b/Documentation/dev-bazel.txt
index 10ee761..564b2a6 100644
--- a/Documentation/dev-bazel.txt
+++ b/Documentation/dev-bazel.txt
@@ -1,5 +1,17 @@
+:linkattrs:
 = Gerrit Code Review - Building with Bazel
 
+[[summary]]
+== TL;DR
+
+If you have the prerequisites, running
+
+```
+  $ bazel build gerrit
+```
+
+should generate a .war file under `bazel-bin/gerrit.war`.
+
 [[installation]]
 == Prerequisites
 
@@ -8,10 +20,10 @@
 * A Linux or macOS system (Windows is not supported at this time)
 * A JDK for Java 8|9|10|11|...
 * Python 3
-* link:https://github.com/nodesource/distributions/blob/master/README.md[Node.js (including npm)]
+* link:https://github.com/nodesource/distributions/blob/master/README.md[Node.js (including npm),role=external,window=_blank]
 * Bower (`sudo npm install -g bower`)
-* link:https://docs.bazel.build/versions/master/install.html[Bazel] -launched with
-link:https://github.com/bazelbuild/bazelisk[Bazelisk]
+* link:https://docs.bazel.build/versions/master/install.html[Bazel,role=external,window=_blank] -launched with
+link:https://github.com/bazelbuild/bazelisk[Bazelisk,role=external,window=_blank]
 * Maven
 * zip, unzip
 * curl
@@ -20,8 +32,8 @@
 [[bazel]]
 === Bazel
 
-link:https://github.com/bazelbuild/bazelisk[Bazelisk] includes a
-link:https://bazel.build/[Bazel] version check and downloads the correct
+link:https://github.com/bazelbuild/bazelisk[Bazelisk,role=external,window=_blank] includes a
+link:https://bazel.build/[Bazel,role=external,window=_blank] version check and downloads the correct
 `bazel` version for the git project/repository. Bazelisk is the recommended
 `bazel` launcher for Gerrit. Once Bazelisk is installed locally, a `bazel`
 symlink can be created towards it. This is so that every `bazel` command
@@ -43,17 +55,17 @@
 
 `java -version`
 
-[[java-12]]
-==== Java 12 support
+[[java-13]]
+==== Java 13 support
 
-Java 12 (and newer) is supported through vanilla java toolchain
-link:https://docs.bazel.build/versions/master/toolchains.html[Bazel option].
-To build Gerrit with Java 12 and newer, specify vanilla java toolchain and
+Java 13 (and newer) is supported through vanilla java toolchain
+link:https://docs.bazel.build/versions/master/toolchains.html[Bazel option,role=external,window=_blank].
+To build Gerrit with Java 13 and newer, specify vanilla java toolchain and
 provide the path to JDK home:
 
 ```
   $ bazel build \
-    --define=ABSOLUTE_JAVABASE=<path-to-java-12> \
+    --define=ABSOLUTE_JAVABASE=<path-to-java-13> \
     --javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
@@ -66,7 +78,7 @@
 
 ```
   $ bazel test \
-    --define=ABSOLUTE_JAVABASE=<path-to-java-12> \
+    --define=ABSOLUTE_JAVABASE=<path-to-java-13> \
     --javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
     --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
@@ -79,7 +91,7 @@
 
 ```
 $ cat << EOF > ~/.bazelrc
-build --define=ABSOLUTE_JAVABASE=<path-to-java-12>
+build --define=ABSOLUTE_JAVABASE=<path-to-java-13>
 build --javabase=@bazel_tools//tools/jdk:absolute_javabase
 build --host_javabase=@bazel_tools//tools/jdk:absolute_javabase
 build --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla
@@ -107,7 +119,7 @@
 ```
 
 === Node.js and npm packages
-See link:https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/README.md#installing-node_js-and-npm-packages[Installing Node.js and npm packages].
+See link:https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/README.md#installing-node_js-and-npm-packages[Installing Node.js and npm packages,role=external,window=_blank].
 
 [[build]]
 == Building on the Command Line
@@ -223,7 +235,7 @@
 
 === IntelliJ
 
-The Gerrit build works with Bazel's link:https://ij.bazel.build[IntelliJ plugin].
+The Gerrit build works with Bazel's link:https://ij.bazel.build[IntelliJ plugin,role=external,window=_blank].
 Please follow the instructions on <<dev-intellij#,IntelliJ Setup>>.
 
 === Eclipse
@@ -243,7 +255,7 @@
 If an updated classpath is needed, the Eclipse project can be
 refreshed and missing dependency JARs can be downloaded by running
 `project.py` again. For IntelliJ, you need to click the `Sync Project
-with BUILD Files` button of link:https://ij.bazel.build[Bazel plugin].
+with BUILD Files` button of link:https://ij.bazel.build[Bazel plugin,role=external,window=_blank].
 
 [[documentation]]
 == Documentation
@@ -354,17 +366,17 @@
 
 Successfully running the Elasticsearch tests requires Docker, and
 may require setting the local virtual memory on
-link:https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html[linux] and
-link:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_set_vm_max_map_count_to_at_least_262144[macOS].
+link:https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html[linux,role=external,window=_blank] and
+link:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_set_vm_max_map_count_to_at_least_262144[macOS,role=external,window=_blank].
 
-On macOS, if using link:https://docs.docker.com/docker-for-mac/[Docker Desktop],
+On macOS, if using link:https://docs.docker.com/docker-for-mac/[Docker Desktop,role=external,window=_blank],
 the effective memory value can be set in the Preferences, under the Advanced tab.
 The default value usually does not suffice and is causing premature container exits.
 That default is currently 2 GB and should be set to at least 5 (GB).
 
 If Docker is not available, the Elasticsearch tests will be skipped.
 Note that Bazel currently does not show
-link:https://github.com/bazelbuild/bazel/issues/3476[the skipped tests].
+link:https://github.com/bazelbuild/bazel/issues/3476[the skipped tests,role=external,window=_blank].
 
 [[logging]]
 === Controlling logging level
@@ -500,7 +512,7 @@
 `bazel build` options `--repository_cache` and `--disk_cache` respectively.
 
 Currently none of these caches have a maximum size limit. See
-link:https://github.com/bazelbuild/bazel/issues/5139[this bazel issue] for
+link:https://github.com/bazelbuild/bazel/issues/5139[this bazel issue,role=external,window=_blank] for
 details. Users should watch the cache sizes and clean them manually if
 necessary.
 
@@ -511,7 +523,7 @@
 "binaries". We don't attempt to resolve and download NPM dependencies at build
 time, but instead use pre-built bundles of the NPM binary along with all its
 dependencies. Some packages on
-link:https://docs.npmjs.com/misc/registry[registry.npmjs.org] come with their
+link:https://docs.npmjs.com/misc/registry[registry.npmjs.org,role=external,window=_blank] come with their
 dependencies bundled, but this is the exception rather than the rule. More
 commonly, to add a new binary to this list, you will need to bundle the binary
 yourself.
@@ -527,10 +539,11 @@
   package=some-npm-package
   version=1.2.3
 
-  npm install -g license-checker && \
+  # Note - yarn must be installed before running the following commands
+  yarn global add license-checker && \
   rm -rf /tmp/$package-$version && mkdir -p /tmp/$package-$version && \
   cd /tmp/$package-$version && \
-  npm install $package@$version && \
+  yarn add $package@$version && \
   license-checker | grep licenses: | sort -u
 ----
 
@@ -539,7 +552,7 @@
 storage bucket if the licenses allow us to do so. As long as all of the listed
 license are allowed by
 link:https://opensource.google.com/docs/thirdparty/licenses/[Google's
-standards]. Any `by_exception_only`, commercial, prohibited, or unlisted
+standards,role=external,window=_blank]. Any `by_exception_only`, commercial, prohibited, or unlisted
 licenses are not allowed; otherwise, it is ok to distribute the source. If in
 doubt, contact a maintainer who is a Googler.
 
@@ -553,41 +566,44 @@
 If you see anything that looks like a native library or binary, then we can't
 use the bundle.
 
-If everything looks good, create the bundle, and note the SHA-1:
-[source,bash]
+If everything looks good, install the package with the following command:
+[source, bash]
 ----
-  $gerrit_repo/tools/js/npm_pack.py $package $version && \
-  sha1sum $package-$version.tgz
+# Add to ui_npm. Other packages.json can be updated in the same way
+cd $gerrit_repo/polygerrit-ui/app
+bazel run @nodejs//:yarn add $package
 ----
 
-This creates a file named `$package-$version.tgz` in your working directory.
+Update the `polygerrit-ui/app/node_modules_licenses/licenses.ts` file. You should add licenses
+for the package itself and for all transitive depndencies. If you forgot to add a license, the
+`Documentation:check_licenses` test will fail.
 
-Any project maintainer can upload this file to the
-link:https://console.cloud.google.com/storage/browser/gerrit-maven/npm-packages[storage
-bucket].
+After the update, commit all changes to the repository (including `yarn.lock`).
 
-Finally, add the new binary to the build process:
-----
-  # WORKSPACE
-  npm_binary(
-      name = "some-npm-package",
-      repository = GERRIT,
-  )
+[NOTE]
+====
+If a npm package has transitive dependencies (or just several files) with a not allowed
+license and you can't avoid use it in release, then you can add this package.
+For example some packages contain demo-code with a different license. Another example - optional
+dependencies, which are not needed to build polygerrit, but they are installed together with
+the package anyway.
 
-  # lib/js/npm.bzl
-  NPM_VERSIONS = {
-    ...
-    "some-npm-package": "1.2.3",
-  }
+In this case you should exclude all files and/or transitive dependencies with a not allowed license.
+Adding such package requires additional updates:
 
-  NPM_SHA1S = {
-    ...
-    "some-npm-package": "<sha1>",
-  }
-----
+- Add dependencies (or files) to the license.ts with an appropriate license marked with
+`allowed: false`.
 
-To use the binary from the Bazel build, you need to use the `run_npm_binary.py`
-wrapper script. For an example, see the use of `crisper` in `tools/bzl/js.bzl`.
+- update package.json postinstall script to remove all non-allowed files (if you don't
+update postinstall script, `Documentation:check_licenses` test will fail.)
+====
+
+=== Update NPM Binaries
+To update a NPM binary the same actions as for a new one must be done (check licenses,
+update `licenses.ts` file, etc...). The only difference is a command to install a package: instead
+of `bazel run @nodejs//:yarn add $package` you should run the `bazel run @nodejs//:yarn upgrade ...`
+command with correct arguments. You can find the list of arguments in the
+link:https://classic.yarnpkg.com/en/docs/cli/upgrade/[yarn upgrade doc,role=external,window=_blank].
 
 
 [[RBE]]
@@ -611,7 +627,7 @@
     --project=${PROJECT} \
     --instance=default_instance \
     --worker-count=50 \
-    --machine-type=n1-highcpu-4 \
+    --machine-type=e2-standard-4 \
     --disk-size=200
 ```
 
diff --git a/Documentation/dev-cla.txt b/Documentation/dev-cla.txt
index 5bc34a7..2aa459c 100644
--- a/Documentation/dev-cla.txt
+++ b/Documentation/dev-cla.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Contributor License Agreement
 
 In order to link:dev-community.html#how-to-contribute[contribute] to
@@ -6,17 +7,17 @@
 following:
 
 . Click 'Sign In' at the top right corner of
-  https://gerrit-review.googlesource.com/
+  https://gerrit-review.googlesource.com/[role=external,window=_blank]
 . Sign In with your Google account
 . After signing in, go to the
-  link:https://gerrit-review.googlesource.com/#/settings/agreements[Agreements]
+  link:https://gerrit-review.googlesource.com/#/settings/agreements[Agreements,role=external,window=_blank]
   tab on the settings page
 . Click on 'New Contributor Agreement' and follow the instructions
 
 For reference, the actual agreements are linked below:
 
-* link:https://cla.developers.google.com/about/google-individual[Individual Agreement]
-* link:https://cla.developers.google.com/about/google-corporate[Corporate Agreement]
+* link:https://cla.developers.google.com/about/google-individual[Individual Agreement,role=external,window=_blank]
+* link:https://cla.developers.google.com/about/google-corporate[Corporate Agreement,role=external,window=_blank]
 
 GERRIT
 ------
diff --git a/Documentation/dev-community.txt b/Documentation/dev-community.txt
index 4fb025f..53829c9 100644
--- a/Documentation/dev-community.txt
+++ b/Documentation/dev-community.txt
@@ -1,19 +1,20 @@
+:linkattrs:
 = Gerrit Community
 
 Gerrit is developed as a
-link:https://gerrit-review.googlesource.com/[self-hosting open source project]
+link:https://gerrit-review.googlesource.com/[self-hosting open source project,role=external,window=_blank]
 and very much welcomes contributions from anyone with a
 link:dev-cla.html[contributor's agreement] on file with the project.
 
 [[project-information]]
 == Project Information
 
-* link:https://www.gerritcodereview.com/[Project Homepage]
-* link:https://www.gerritcodereview.com/codeofconduct.html[Code of Conduct]
-* link:https://www.gerritcodereview.com/releases-readme.html[Release Versions]
-* link:https://gerrit.googlesource.com/gerrit[Source]
-* link:https://bugs.chromium.org/p/gerrit/issues/list[Issue Tracking]
-* link:https://gerrit-review.googlesource.com/q/status:open+project:gerrit[Change Review]
+* link:https://www.gerritcodereview.com/[Project Homepage,role=external,window=_blank]
+* link:https://www.gerritcodereview.com/codeofconduct.html[Code of Conduct,role=external,window=_blank]
+* link:https://www.gerritcodereview.com/releases-readme.html[Release Versions,role=external,window=_blank]
+* link:https://gerrit.googlesource.com/gerrit[Source,role=external,window=_blank]
+* link:https://bugs.chromium.org/p/gerrit/issues/list[Issue Tracking,role=external,window=_blank]
+* link:https://gerrit-review.googlesource.com/q/status:open+project:gerrit[Change Review,role=external,window=_blank]
 * link:dev-design.html[System Design]
 * Processes
 ** link:dev-processes.html#project-governance[Project Governance / Engineering Steering Committee]
diff --git a/Documentation/dev-contributing.txt b/Documentation/dev-contributing.txt
index 49f8fcf..23ecd67 100644
--- a/Documentation/dev-contributing.txt
+++ b/Documentation/dev-contributing.txt
@@ -1,10 +1,12 @@
+:linkattrs:
 = Gerrit Code Review - Contributing
 
 [[cla]]
 == Contributor License Agreement
 
 In order to contribute to Gerrit a link:dev-cla.html[Contributor
-License Agreement] must be completed before contributions are accepted.
+License Agreement,role=external,window=_blank] must be completed before
+contributions are accepted.
 
 [[contribution-processes]]
 == Contribution Processes
@@ -19,26 +21,28 @@
 The lightweight contribution process has little overhead and is best
 suited for small contributions (documentation updates, bug fixes, small
 features). Contributions are pushed as changes and
-link:dev-roles.html#maintainer[maintainers] review them adhoc.
+link:dev-roles.html#maintainer[maintainers,role=external,window=_blank]
+review them adhoc.
 
 For large/complex features, it is required to follow the
 link:#design-driven-contribution-process[design-driven contribution
 process] and specify the feature in a link:dev-design-docs.html[design
-doc] before starting with the implementation.
+doc,role=external,window=_blank] before starting with the implementation.
 
-If link:dev-roles.html#contributor[contributors] choose the lightweight
-contribution process and during the review it turns out that the feature
-is too large or complex, link:dev-roles.html#maintainer[maintainers] can
+If link:dev-roles.html#contributor[contributors,role=external,window=_blank]
+choose the lightweight contribution process and during the review it turns out
+that the feature is too large or complex,
+link:dev-roles.html#maintainer[maintainers,role=external,window=_blank] can
 require to follow the design-driven contribution process instead.
 
 If you are in doubt which process is right for you, consult the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
 mailing list.
 
 These contribution processes apply to everyone who contributes code to
-the Gerrit project, including link:dev-roles.html#maintainer[maintainers].
-When reading this document, keep in mind that maintainers are also
-contributors when they contribute code.
+the Gerrit project, including link:dev-roles.html#maintainer[
+maintainers,role=external,window=_blank]. When reading this document, keep in
+mind that maintainers are also contributors when they contribute code.
 
 If a new feature is large or complex, it is often difficult to find a
 maintainer who can take the time that is needed for a thorough review,
@@ -55,7 +59,8 @@
 |======================
 |        |Lightweight Contribution Process|Design-Driven Contribution Process
 |Overhead|low (write good commit message, address review comments)|
-high (write link:dev-design-docs.html[design doc] and get it approved)
+high (write link:dev-design-docs.html[design doc,role=external,window=_blank]
+and get it approved)
 |Technical Guidance|by reviewer|during the design review and by
 reviewer/mentor
 |Review  |adhoc (when reviewer is available)|by a dedicated mentor (if
@@ -82,16 +87,16 @@
 be reviewed before they will get submitted to the code base.  To
 start your contribution, please make a git commit and upload it
 for review to the link:https://gerrit-review.googlesource.com/[
-gerrit-review.googlesource.com] Gerrit server.  To help speed up the
-review of your change, review these link:dev-crafting-changes.html[
-guidelines] before submitting your change.  You can view the pending
-Gerrit contributions and their statuses
-link:https://gerrit-review.googlesource.com/#/q/status:open+project:gerrit[here].
+gerrit-review.googlesource.com,role=external,window=_blank] Gerrit server.  To
+help speed up the review of your change, review these link:dev-crafting-changes.html[
+guidelines,role=external,window=_blank] before submitting your change.  You can
+view the pending Gerrit contributions and their statuses
+link:https://gerrit-review.googlesource.com/#/q/status:open+project:gerrit[here,role=external,window=_blank].
 
 Depending on the size of that list it might take a while for
 your change to get reviewed.  Naturally there are fewer
-link:dev-roles.html#maintainer[maintainers], that can approve changes,
-than link:dev-roles.html#contributor[contributors];
+link:dev-roles.html#maintainer[maintainers,role=external,window=_blank], that
+can approve changes, than link:dev-roles.html#contributor[contributors,role=external,window=_blank];
 so anything that you can do to ensure that your contribution will undergo fewer
 revisions will speed up the contribution process.  This includes
 helping out reviewing other people's changes to relieve the load from
@@ -123,26 +128,28 @@
 * think about possibilities how the feature could be evolved over time
 
 This is why for large/complex features it is required to describe the
-feature in a link:dev-design-docs.html[design doc] and get it approved
-by the link:dev-processes.html#steering-committee[steering committee],
+feature in a link:dev-design-docs.html[design doc,role=external,window=_blank]
+and get it approved by the
+link:dev-processes.html#steering-committee[steering committee,role=external,window=_blank],
 before starting the implementation.
 
 The design-driven contribution process has the following steps:
 
-* A link:dev-roles.html#contributor[contributor]
-  link:dev-design-docs.html#propose[proposes] a new feature by uploading
-  a change with a link:dev-design-docs.html[design doc].
-* The design doc is link:dev-design-docs.html#review[reviewed]
+* A link:dev-roles.html#contributor[contributor,role=external,window=_blank]
+  link:dev-design-docs.html#propose[proposes,role=external,window=_blank] a new
+  feature by uploading a change with a
+  link:dev-design-docs.html[design doc,role=external,window=_blank].
+* The design doc is link:dev-design-docs.html#review[reviewed,role=external,window=_blank]
   by interested parties from the community. The design review is public
   and everyone can comment and raise concerns.
 * Design docs should stay open for a minimum of 10 calendar days so
   that everyone has a fair chance to join the review.
 * Within 14 calendar days the contributor should hear back from the
-  link:dev-processes.html#steering-committee[steering committee]
+  link:dev-processes.html#steering-committee[steering committee,role=external,window=_blank]
   whether the proposed feature is in scope of the project and if it can
   be accepted.
 * To be submitted, the design doc needs to be approved by the
-  link:dev-processes.html#steering-committee[steering committee].
+  link:dev-processes.html#steering-committee[steering committee,role=external,window=_blank].
 * After the design was approved, the implementation is done by pushing
   changes for review, see link:#lightweight-contribution-process[
   lightweight contribution process]. Changes that are associated with
@@ -168,7 +175,7 @@
 
 * Accepting the feature when it is implemented.
 * Supporting the feature by assigning a link:dev-roles.html#mentor[
-  mentor] (if requested, see link:#mentorship[mentorship]).
+  mentor,role=external,window=_blank] (if requested, see link:#mentorship[mentorship]).
 
 If the implementation of a feature gets stuck and it's unclear whether
 the feature gets fully done, it should be discussed with the steering
@@ -184,7 +191,7 @@
   design review, feedback from various sides can be collected, which
   likely leads to improvements of the feature.
 * Once a design was approved by the
-  link:dev-processes.html#steering-committee[steering committee],
+  link:dev-processes.html#steering-committee[steering committee,role=external,window=_blank],
   the contributor can be almost certain that the feature will be accepted.
   Hence, there is only a low risk to invest into implementing a feature
   and see it being rejected later during the code review, as it can
@@ -196,12 +203,12 @@
 [[mentorship]]
 == Mentorship
 
-For features for which a link:dev-design-docs.html[design]
+For features for which a link:dev-design-docs.html[design,role=external,window=_blank]
 has been approved (see link:#design-driven-contribution-process[design-driven
 contribution process]), contributors can gain the support of a mentor
 if they are committed to implement the feature.
 
-A link:dev-roles.html#mentor[mentor] helps with:
+A link:dev-roles.html#mentor[mentor,role=external,window=_blank] helps with:
 
 * doing timely reviews
 * providing technical guidance during code reviews
@@ -211,12 +218,12 @@
 
 A feature can have more than one mentor. To be able to deliver the
 promised support, at least one of the mentors must be a
-link:dev-roles.html#maintainer[maintainer].
+link:dev-roles.html#maintainer[maintainer,role=external,window=_blank].
 
 Mentors are assigned by the link:dev-processes.html#steering-committee[
-steering committee]. To gain a mentor, ask for a
+steering committee,role=external,window=_blank]. To gain a mentor, ask for a
 mentor in the link:dev-design-doc-template.html#implementation-plan[Implementation
-Plan] section of the design doc or ask the steering
+Plan,role=external,window=_blank] section of the design doc or ask the steering
 committee after the design has been approved.
 
 Mentors may not be available immediately. In this case, the steering
diff --git a/Documentation/dev-core-plugins.txt b/Documentation/dev-core-plugins.txt
new file mode 100644
index 0000000..04e2420
--- /dev/null
+++ b/Documentation/dev-core-plugins.txt
@@ -0,0 +1,163 @@
+:linkattrs:
+= Gerrit Code Review - Core Plugins
+
+[[definition]]
+== What are core plugins?
+
+Core plugins are plugins that are packaged within the Gerrit war file. This
+means during the link:pgm-init.html[Gerrit initialization] they can be easily
+installed without downloading any additional files.
+
+To make working with core plugins easy, they are linked as
+link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/.gitmodules[Git
+submodules,role=external,window=_blank] in the `gerrit` repository. E.g. this means they can be easily
+link:dev-readme.html#clone[cloned] together with Gerrit.
+
+All core plugins are developed and maintained by the
+link:dev-roles.html#maintainers[Gerrit maintainers] and everyone can
+link:dev-contributing.html[contribute] to them.
+
+Adding a new core plugin feature that is large or complex requires a
+link:dev-design-doc.html[design doc] (also see
+link:dev-contributing.html#design-driven-contribution-process[design-driven
+contribution process]). The link:dev-processes.html#steering-committee[
+engineering steering committee (ESC)] is the authority that approves the design
+docs. The ESC is also in charge of adding and removing core plugins.
+
+Non-Gerrit maintainers cannot have link:access-control.html#category_owner[
+Owner] permissions for core plugins.
+
+[[list]]
+== Which core plugins exist?
+
+See link:config-plugins.html#core-plugins[here].
+
+[[criteria]]
+=== Criteria for Core Plugins
+
+To be considered as a core plugin, a plugin must fulfill the following
+criteria:
+
+1. License:
++
+The plugin code is available under the
+link:http://www.apache.org/licenses/LICENSE-2.0[Apache License Version 2.0,role=external,window=_blank].
+
+2. Hosting:
++
+The plugin development is hosted on the
+link:https://gerrit-review.googlesource.com[gerrit-review,role=external,window=_blank] Gerrit Server.
+
+3. Scope:
++
+The plugin functionality is Gerrit-related, has a clear scope and does not
+conflict with other core plugins or existing and planned Gerrit core features.
+
+4. Relevance:
++
+The plugin functionality is relevant to a majority of the Gerrit community:
++
+--
+** An out of the box Gerrit installation would seem like it is missing
+   something if the plugin is not installed.
+** It's expected that most sites would use the plugin.
+** Multiple parties (different organizations/companies) already use the plugin
+   and agree that it should be offered as core plugin.
+** If the same or similar functionality is provided by multiple plugins,
+   the plugin is the clear recommended solution by the community.
+--
++
+Whether a plugin is relevant to a majority of the Gerrit community must be
+discussed on a case-by-case basis. In case of doubt, it's up to the
+link:dev-processes.html#steering-committee[engineering steering committee] to
+make a decision.
+
+5. Code Quality:
++
+The plugin code is mature and has a good test coverage. Maintaining the plugin
+code creates only little overhead for the Gerrit maintainers.
+
+6. Documentation:
++
+The plugin functionality is fully documented.
+
+7. Ownership:
++
+Existing plugin owners which are not Gerrit maintainers must agree to give up
+their ownership. If the current plugin owners disagree, forking the plugin is
+possible, but this should happen only in exceptional cases.
+
+[[process-to-make-a-plugin-a-core-plugin]]
+== Process to make a plugin a core plugin
+
+Anyone can propose to make a plugin a core plugin, but to be accepted as core
+plugin the plugin must fulfill certain link:#criteria[criteria].
+
+1. Propose a plugin as core plugin:
++
+File a link:https://bugs.chromium.org/p/gerrit/issues/entry?template=Core+Plugin+Request[
+Core Plugin Request] in the issue tracker and provide the information that is
+being asked for in the request template.
+
+2. Community Feedback:
++
+Anyone can comment on the issue to raise concerns or to support the request.
+The issue should stay open for at least 10 calendar days so that everyone in
+the community has a chance to comment.
+
+3. ESC Decision:
++
+The ESC should discuss the request and reject/approve it or ask for further
+information that the reporter or commenters should provide.
++
+Any decision must be based on the link:#criteria[criteria] that core plugins
+are expected to fulfill and should take the feedback from the community into
+account.
++
+Accepting the request is only possible if the issue was open for at least 10
+calendar days (see 2., this gives the community time to comment).
++
+When the ESC approves/rejects the request a summary of the reasons for the
+decision should be added to the issue.
++
+If a request is rejected, it's possible to ask for a revalidation if the
+concerns that led to the rejection have been addressed (e.g. the plugin was
+rejected due to missing tests, but tests have been added afterwards).
+
+4. Add plugin as core plugin:
++
+If the request was accepted, a Gerrit maintainer should add the plugin as
+core plugin:
++
+--
+** Host the plugin repo on link:https://gerrit-review.googlesource.com/[
+   gerrit-review].
+** Ensure that the plugin repo inherits from the
+   link:https://gerrit-review.googlesource.com/admin/repos/Public-Plugins[
+   Public-Plugins] repo.
+** Remove all permissions on the plugin repo (the inherited permissions from
+   `Public-Plugins` should be enough). Especially make sure that there are no
+   link:access-control.html#category_owner[Owner],
+   link:access-control.html#category_push_direct[Direct Push],
+   link:access-control.html#category_submit[Submit] or
+   link:access-control.html#category_review_labels[Code-Review+2]
+   permissions for non-Gerrit maintainers.
+** Create a component for the plugin in
+   link:https://bugs.chromium.org/p/gerrit/adminComponents[Monorail] and assign
+   all issues that already exist for the plugin to this component.
+** Add the plugin as
+   link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/.gitmodules[Git
+   submodule].
+** Register the plugin as core plugin in
+   link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/tools/bzl/plugins.bzl[
+   plugins.bzl].
+** Announce the new core plugin in the
+   link:https://www.gerritcodereview.com/news.html[project news].
+--
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/dev-crafting-changes.txt b/Documentation/dev-crafting-changes.txt
index 2bbbc45..7935f30 100644
--- a/Documentation/dev-crafting-changes.txt
+++ b/Documentation/dev-crafting-changes.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Crafting Changes
 
 Here are some hints as to what approvers may be looking for
@@ -117,10 +118,10 @@
 The HTTPS access requires proper username and password; this can be obtained
 by clicking the 'Obtain Password' link on the
 link:https://gerrit-review.googlesource.com/#/settings/http-password[HTTP
-Password tab of the user settings page].
+Password tab of the user settings page,role=external,window=_blank].
 
 Alternately, you may use the
-link:https://pypi.org/project/git-review/[git-review] tool to submit changes
+link:https://pypi.org/project/git-review/[git-review,role=external,window=_blank] tool to submit changes
 to Gerrit. If you do, it will set up the Change-Id hook and `gerrit` remote
 for you. You will still need to do the HTTP access step.
 
@@ -140,14 +141,14 @@
 
 Gerrit follows the
 link:https://google.github.io/styleguide/javaguide.html[Google Java Style
-Guide].
+Guide,role=external,window=_blank].
 
 To format Java source code, Gerrit uses the
-link:https://github.com/google/google-java-format[`google-java-format`]
+link:https://github.com/google/google-java-format[`google-java-format`,role=external,window=_blank]
 tool (version 1.7), and to format Bazel BUILD, WORKSPACE and .bzl files the
-link:https://github.com/bazelbuild/buildtools/tree/master/buildifier[`buildifier`]
+link:https://github.com/bazelbuild/buildtools/tree/master/buildifier[`buildifier`,role=external,window=_blank]
 tool (version 4.0.0). Unused dependencies are found and removed using the
-link:https://github.com/bazelbuild/buildtools/tree/master/unused_deps[`unused_deps`]
+link:https://github.com/bazelbuild/buildtools/tree/master/unused_deps[`unused_deps`,role=external,window=_blank]
 build tool, a sibling of `buildifier`.
 
 These tools automatically apply format according to the style guides; this
@@ -260,6 +261,13 @@
 
   * Tests for new code will greatly help your change get approved.
 
+[[javadoc]]
+== Javadoc
+
+  * Javadocs for new code (especially public classes and
+    public/protected methods) will greatly help your change get
+    approved.
+
 [[change-size]]
 == Change Size/Number of Files Touched
 
diff --git a/Documentation/dev-design-docs.txt b/Documentation/dev-design-docs.txt
index a339da3..7e48eea 100644
--- a/Documentation/dev-design-docs.txt
+++ b/Documentation/dev-design-docs.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Design Docs
 
 For the link:dev-contributing.html#design-driven-contribution-process[
@@ -73,7 +74,7 @@
 
 To propose a new design, upload a change to the
 link:https://gerrit-review.googlesource.com/admin/repos/homepage[
-homepage] repository that adds a new folder under `pages/design-docs/`
+homepage,role=external,window=_blank] repository that adds a new folder under `pages/design-docs/`
 which contains at least an `index.md` and a `uses-cases.md` file (see
 link:#structure[design doc structure] above).
 
@@ -88,7 +89,7 @@
 
 Only very few maintainers actively watch out for uploaded design docs.
 To raise awareness you may want to send a notification to the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
 mailing list about your uploaded design doc. But the discussion should
 not take place on the mailing list, comments should be made by reviewing
 the change in Gerrit.
@@ -99,7 +100,14 @@
 Everyone in the link:dev-roles.html[Gerrit community] is welcome to
 take part in the design review and comment on the design. As such, every
 design reviewer is expected to respect the community
-link:https://www.gerritcodereview.com/codeofconduct.html[Code of Conduct].
+link:https://www.gerritcodereview.com/codeofconduct.html[Code of Conduct,role=external,window=_blank].
+
+Positive `Code-Review` votes on changes that add/modify design docs are
+sticky. This means any `Code-Review+1` and `Code-Review+2` vote is
+preserved when a new patch set is uploaded. If a new patch set makes
+significant changes, the uploader of the new patch set must start a new
+review round by removing all positive `Code-Review` votes from the
+change manually.
 
 Ideas for alternative solutions should be uploaded as a change that
 describes the solution (see link:#collaboration[above]). This should be
@@ -134,14 +142,15 @@
 too much or becomes overly complex, one can use a meeting to refocus it. From
 that review thread, the organizer can volunteer oneself, or be proposed (even
 requested) by a reviewer. link:https://www.gerritcodereview.com/members.html#community-managers[
-Community managers] may help facilitate that if ultimately necessary.
+Community managers,role=external,window=_blank] may help facilitate that if
+ultimately necessary.
 
 [[watch-designs]]
 == How to get notified for new design docs?
 
 . Go to the
   link:https://gerrit-review.googlesource.com/settings/#Notifications[
-  notification settings]
+  notification settings,role=external,window=_blank]
 . Add a project watch for the `homepage` repository with the following
   query: `dir:pages/design-docs`
 
diff --git a/Documentation/dev-design.txt b/Documentation/dev-design.txt
index 0243a58..1935586 100644
--- a/Documentation/dev-design.txt
+++ b/Documentation/dev-design.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - System Design
 
 == Objective
@@ -68,10 +69,10 @@
 Since Gerrit 3.x link:note-db.html[NoteDb] replaced the SQL database
 and all metadata is now stored in Git.
 
-* link:http://video.google.com/videoplay?docid=-8502904076440714866[Mondrian Code Review On The Web]
-* link:https://github.com/rietveld-codereview/rietveld[Rietveld - Code Review for Subversion]
-* link:http://eagain.net/gitweb/?p=gitosis.git;a=blob;f=README.rst;hb=HEAD[Gitosis README]
-* link:http://source.android.com/[Android Open Source Project]
+* link:http://video.google.com/videoplay?docid=-8502904076440714866[Mondrian Code Review On The Web,role=external,window=_blank]
+* link:https://github.com/rietveld-codereview/rietveld[Rietveld - Code Review for Subversion,role=external,window=_blank]
+* link:http://eagain.net/gitweb/?p=gitosis.git;a=blob;f=README.rst;hb=HEAD[Gitosis README,role=external,window=_blank]
+* link:http://source.android.com/[Android Open Source Project,role=external,window=_blank]
 
 
 == Overview
@@ -167,8 +168,8 @@
 requires that the OpenID provider selected by a user must be
 online and operating in order to authenticate that user.
 
-* link:http://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html[Git Repository Format]
-* link:http://openid.net/developers/specs/[OpenID Specifications]
+* link:http://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html[Git Repository Format,role=external,window=_blank]
+* link:http://openid.net/developers/specs/[OpenID Specifications,role=external,window=_blank]
 
 *1  Although an effort is underway to eliminate the use of the
 database altogether, and to store all the metadata directly in
diff --git a/Documentation/dev-e2e-tests.txt b/Documentation/dev-e2e-tests.txt
index bf35c32..c50a293 100644
--- a/Documentation/dev-e2e-tests.txt
+++ b/Documentation/dev-e2e-tests.txt
@@ -1,14 +1,15 @@
+:linkattrs:
 = Gerrit Code Review - End to end tests
 
 This document provides descriptions of Gerrit end-to-end (`e2e`) test scenarios implemented using
-the link:https://gatling.io/[Gatling] framework.
+the link:https://gatling.io/[Gatling,role=external,window=_blank] framework.
 
 Similar scenarios have been successfully used to compare performance of different Gerrit versions
 or study the Gerrit response under different load profiles. Although mostly for load, scenarios can
-either be for link:https://gatling.io/load-testing-continuous-integration/[load or functional]
+either be for link:https://gatling.io/load-testing-continuous-integration/[load or functional,role=external,window=_blank]
 (e2e) testing purposes. Functional scenarios may then reuse this framework and Gatling's usability
 features such as its protocols (more below) and
-link:https://en.wikipedia.org/wiki/Domain-specific_language[DSL].
+link:https://en.wikipedia.org/wiki/Domain-specific_language[DSL,role=external,window=_blank].
 
 That cross test-scope reusability applies to both Gerrit core scenarios and non-core ones, such as
 for Gerrit plugins or other potential extensions. End-to-end testing may then include scopes like
@@ -20,26 +21,27 @@
 
 Gatling is mostly a load testing tool which provides out of the box support for the HTTP protocol.
 Documentation on how to write an HTTP load test can be found
-link:https://gatling.io/docs/current/http/http_protocol/[here]. However, in the scenarios that were
-initially proposed, the link:https://github.com/GerritForge/gatling-git[Gatling Git extension] was
+link:https://gatling.io/docs/current/http/http_protocol/[here,role=external,window=_blank].
+However, in the scenarios that were initially proposed, the
+link:https://github.com/GerritForge/gatling-git[Gatling Git extension,role=external,window=_blank] was
 leveraged to run tests at the Git protocol level.
 
 Gatling is written in Scala, but the abstraction provided by the Gatling DSL makes the scenarios
 implementation easy even without any Scala knowledge. The online `End-to-end tests`
-link:https://www.gerritcodereview.com/presentations.html#list-of-presentations[presentation] links
-posted on the homepage have more introductory information.
+link:https://www.gerritcodereview.com/presentations.html#list-of-presentations[presentation,role=external,window=_blank]
+links posted on the homepage have more introductory information.
 
 == IDE: IntelliJ
 
 Examples of scenarios can be found in the `e2e-tests` directory. The files in that directory should
 be formatted using the mainstream
-link:https://plugins.jetbrains.com/plugin/1347-scala[Scala plugin for IntelliJ]. The latter is not
-mandatory but preferred for `sbt` and Scala IDE purposes in this project. So, Eclipse can also be
-used alongside as a development IDE; this is described below.
+link:https://plugins.jetbrains.com/plugin/1347-scala[Scala plugin for IntelliJ,role=external,window=_blank].
+The latter is not mandatory but preferred for `sbt` and Scala IDE purposes in this project.
+So, Eclipse can also be used alongside as a development IDE; this is described below.
 
 === Eclipse
 
-1. Install the link:http://scala-ide.org/docs/user/gettingstarted.html[Scala plugin for Eclipse].
+1. Install the link:http://scala-ide.org/docs/user/gettingstarted.html[Scala plugin for Eclipse,role=external,window=_blank].
 2. Run `sbt eclipse` from the `e2e-tests` root directory.
 3. Import the resulting `e2e-tests` eclipse file inside the Gerrit project, in Eclipse.
 4. You should see errors in Eclipse telling you there are missing packages.
@@ -55,8 +57,8 @@
 
 == How to build the tests
 
-An link:https://www.scala-sbt.org/download.html[sbt-based installation] of
-link:https://www.scala-lang.org/download/[Scala] is required.
+An link:https://www.scala-sbt.org/download.html[sbt-based installation,role=external,window=_blank]
+of link:https://www.scala-lang.org/download/[Scala,role=external,window=_blank] is required.
 
 The `scalaVersion` used by `sbt` once installed is defined in the `build.sbt` file. That specific
 version of Scala is automatically used by `sbt` while building:
@@ -66,7 +68,7 @@
 ----
 
 The following warning, if present when executing `sbt` commands, can be removed by creating the
-link:https://www.scala-sbt.org/1.x/docs/Using-Sonatype.html#step+3%3A+Credentials[related credentials file]
+link:https://www.scala-sbt.org/1.x/docs/Using-Sonatype.html#step+3%3A+Credentials[related credentials file,role=external,window=_blank]
 locally. Dummy values for `user` and `password` in that file can be used initially.
 
 ----
@@ -82,7 +84,7 @@
 ----
 
 Every `sbt` command can include an optional log level
-link:https://www.scala-sbt.org/1.x/docs/Howto-Logging.html#Change+the+logging+level+globally[argument].
+link:https://www.scala-sbt.org/1.x/docs/Howto-Logging.html#Change+the+logging+level+globally[argument,role=external,window=_blank].
 Below, `[info]` logs are no longer shown:
 
 ----
@@ -101,7 +103,7 @@
 
 If you are running SSH commands, the private keys of the users used for testing need to go in
 `/tmp/ssh-keys`. The keys need to be generated this way (JSch won't validate them
-link:https://stackoverflow.com/questions/53134212/invalid-privatekey-when-using-jsch[otherwise]):
+link:https://stackoverflow.com/questions/53134212/invalid-privatekey-when-using-jsch[otherwise,role=external,window=_blank]):
 
 ----
 mkdir /tmp/ssh-keys
@@ -125,7 +127,7 @@
 below. This scenario serves as a simple example with no actual load in it. It can be used to test
 or validate the local setup. More complex scenarios can be further developed, under the
 `com.google.gerrit.scenarios` package. The uppercase keywords are set through
-link:#_environment_properties[environment properties].
+link:#_environment_properties[environment properties,role=external,window=_blank].
 
 ----
 [
@@ -164,9 +166,9 @@
 === Environment properties
 
 The `JAVA_OPTS` environment variable
-link:https://gatling.io/docs/current/cookbook/passing_parameters[can optionally be used] to define
-non-default values for keys found in scenario `json` data files. That variable can currently be set
-with either one or many of these supported properties, from the core framework:
+link:https://gatling.io/docs/current/cookbook/passing_parameters[can optionally be used,role=external,window=_blank]
+to define non-default values for keys found in scenario `json` data files. That variable can
+currently be set with either one or many of these supported properties, from the core framework:
 
 * `-Dcom.google.gerrit.scenarios.hostname=localhost`
 * `-Dcom.google.gerrit.scenarios.ssh_port=29418`
@@ -175,7 +177,8 @@
 
 Above, the properties can be set with values matching specific deployment topologies under test.
 The name of the property corresponds to the uppercase keyword found in the json file. For example,
-`hostname` above will set the value of `HOSTNAME` in the link:#_input_file[aforementioned example].
+`hostname` above will set the value of `HOSTNAME` in the
+link:#_input_file[aforementioned example,role=external,window=_blank].
 
 The example values shown above are the currently coded default ones. For example, the `http` scheme
 above could be replaced with `https`. The framework may support differing or more properties over time.
@@ -194,10 +197,11 @@
 
 ==== Automatic properties
 
-The link:#_input_file[example keywords] also include `_PROJECT`, prefixed with an underscore, which
-means that its value gets automatically generated by the scenario. Any property setting for it is
-therefore not applicable. Its usage differs from the non-prefixed `PROJECT` keyword, in that sense.
-Using the latter instead in json files requires setting this `JAVA_OPTS` property:
+The link:#_input_file[example keywords,role=external,window=_blank] also include `_PROJECT`,
+prefixed with an underscore, which means that its value gets automatically generated by the
+scenario. Any property setting for it is therefore not applicable. Its usage differs from the
+non-prefixed `PROJECT` keyword, in that sense. Using the latter instead in json files requires
+setting this `JAVA_OPTS` property:
 
 * `-Dcom.google.gerrit.scenarios.project=myOwnTestRepoProjectName`
 
@@ -210,10 +214,10 @@
 those scenario classes are. Such extending scenarios can also add extension-specific properties.
 Examples of this can be found in these Gerrit plugins test code:
 
-* `link:https://gerrit.googlesource.com/plugins/gc-conductor[gc-conductor]`
-* `link:https://gerrit.googlesource.com/plugins/high-availability[high-availability]`
-* `link:https://gerrit.googlesource.com/plugins/multi-site[multi-site]`
-* `link:https://gerrit.googlesource.com/plugins/rename-project[rename-project]`
+* `link:https://gerrit.googlesource.com/plugins/gc-conductor[gc-conductor,role=external,window=_blank]`
+* `link:https://gerrit.googlesource.com/plugins/high-availability[high-availability,role=external,window=_blank]`
+* `link:https://gerrit.googlesource.com/plugins/multi-site[multi-site,role=external,window=_blank]`
+* `link:https://gerrit.googlesource.com/plugins/rename-project[rename-project,role=external,window=_blank]`
 
 ==== Power factor
 
@@ -257,9 +261,10 @@
 ----
 
 The `src/test/resources/logback.xml` file
-link:http://logback.qos.ch/manual/configuration.html[configures] Gatling's logging level. To quickly
-enable link:https://gatling.io/docs/current/general/debugging#logback[detailed logging] of `http`
-requests and responses, the `root level` can be set to `trace` in that file.
+link:http://logback.qos.ch/manual/configuration.html[configures,role=external,window=_blank]
+Gatling's logging level. To quickly enable
+link:https://gatling.io/docs/current/general/debugging#logback[detailed logging,role=external,window=_blank]
+of `http` requests and responses, the `root level` can be set to `trace` in that file.
 
 === How to run using Docker
 
diff --git a/Documentation/dev-eclipse.txt b/Documentation/dev-eclipse.txt
index bdd6360..742cf42 100644
--- a/Documentation/dev-eclipse.txt
+++ b/Documentation/dev-eclipse.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Eclipse Setup
 
 This document is about configuring Gerrit Code Review into an
@@ -8,7 +9,7 @@
 [[setup]]
 == Project Setup
 
-In your Eclipse installation's link:https://wiki.eclipse.org/Eclipse.ini[`eclipse.ini`] file,
+In your Eclipse installation's link:https://wiki.eclipse.org/Eclipse.ini[`eclipse.ini`,role=external,window=_blank] file,
 add the following line in the `vmargs` section:
 
 ----
@@ -91,13 +92,13 @@
 == Code Formatter Settings
 
 To format source code, Gerrit uses the
-link:https://github.com/google/google-java-format[`google-java-format`]
+link:https://github.com/google/google-java-format[`google-java-format`,role=external,window=_blank]
 tool (version 1.7), which automatically formats code to follow the
 style guide. See link:dev-crafting-changes.html#style[Code Style] for the
 instruction how to set up command line tool that uses this formatter.
 The Eclipse plugin is provided that allows to format with the same
 formatter from within the Eclipse IDE. See
-link:https://github.com/google/google-java-format#eclipse[Eclipse plugin]
+link:https://github.com/google/google-java-format#eclipse[Eclipse plugin,role=external,window=_blank]
 for details how to install it. It's important to use the same plugin version
 as the `google-java-format` script.
 
@@ -111,6 +112,13 @@
 
 == Testing
 
+=== PolyGerrit UI is served by `server.go` process. To launch it,
+run this command:
+
+----
+  $ bazel run polygerrit-ui:devserver
+----
+
 === Running the Daemon
 
 Duplicate the existing launch configuration:
diff --git a/Documentation/dev-inspector.txt b/Documentation/dev-inspector.txt
index 39736d7..da6e3aa 100644
--- a/Documentation/dev-inspector.txt
+++ b/Documentation/dev-inspector.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Inspector
 
 == NAME
@@ -33,7 +34,7 @@
 
 Gerrit Inspector requires Jython library ('jython.jar') to be installed
 in the '$site_path/lib' directory. Jython, a Python interpreter for
-the Java Virtual Machine, can be obtained from the http://www.jython.org/
+the Java Virtual Machine, can be obtained from the http://www.jython.org/[role=external,window=_blank]
 website. Only 'jython.jar' file is needed, installation of Jython libraries
 is optional. Gerrit Inspector has been tested with Jython 2.5.2 but
 might work an earlier version.
@@ -87,7 +88,7 @@
 
 For more information on using Jython, especially with regards to its limitations
 in interfacing to the Java Virtual Machine, please refer to the
-http://www.jython.org/[Jython documentation].
+http://www.jython.org/[Jython documentation,role=external,window=_blank].
 
 After successful initialization it is possible to examine components of
 Java packages, classes and live instances.
diff --git a/Documentation/dev-intellij.txt b/Documentation/dev-intellij.txt
index 81790db..b67d546 100644
--- a/Documentation/dev-intellij.txt
+++ b/Documentation/dev-intellij.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - IntelliJ IDEA Setup
 
 == Prerequisites
@@ -14,7 +15,7 @@
 === IntelliJ version and Bazel plugin
 
 Before downloading IntelliJ, look at the
-link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[JetBrains plugin repository page of the Bazel plugin]
+link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[JetBrains plugin repository page of the Bazel plugin,role=external,window=_blank]
 to see what version of the IntelliJ IDEA it is actually compatible with.
 
 Also note that the version of the Bazel plugin used in turn may or may not be
@@ -30,7 +31,7 @@
 === Installation of IntelliJ IDEA
 
 Please refer to the
-link:https://www.jetbrains.com/help/idea/installation-guide.html[installation guide provided by Jetbrains]
+link:https://www.jetbrains.com/help/idea/installation-guide.html[installation guide provided by Jetbrains,role=external,window=_blank]
 to install it on your platform. Make sure to install a version compatible with
 the Bazel plugin as mentioned above.
 
@@ -47,7 +48,7 @@
 . Search for the plugin `Bazel` (by Google).
 +
 TIP: In case the Bazel plugin is not listed, or if it shows an outdated version,
-verify the compatibility between the Bazel plugin and IntelliJ IDEA on link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[the JetBrains plugin page].
+verify the compatibility between the Bazel plugin and IntelliJ IDEA on link:https://plugins.jetbrains.com/plugin/8609-bazel/versions[the JetBrains plugin page,role=external,window=_blank].
 . Install it.
 . Restart IntelliJ IDEA.
 
@@ -117,7 +118,7 @@
 
 . Download
 https://raw.githubusercontent.com/google/styleguide/gh-pages/intellij-java-google-style.xml[
-intellij-java-google-style.xml].
+intellij-java-google-style.xml,role=external,window=_blank].
 . Go to *File -> Settings -> Editor -> Code Style*.
 . Click on the wrench icon with the tooltip _Show Scheme Actions_.
 . Click on *Import Scheme*.
@@ -196,7 +197,7 @@
 use the instructions of <<dev-readme#run_daemon,Running the Daemon>> in
 combination with <<remote-debug,Debugging a remote Gerrit server>>.
 
-(link:https://bugs.chromium.org/p/gerrit/issues/detail?id=11360[Issue 11360])
+(link:https://bugs.chromium.org/p/gerrit/issues/detail?id=11360[Issue 11360,role=external,window=_blank])
 ====
 
 Copy `$(gerrit_source_code)/tools/intellij/gerrit_daemon.xml` to
diff --git a/Documentation/dev-plugins-lifecycle.txt b/Documentation/dev-plugins-lifecycle.txt
index b552472..d5bd791 100644
--- a/Documentation/dev-plugins-lifecycle.txt
+++ b/Documentation/dev-plugins-lifecycle.txt
@@ -1,7 +1,8 @@
+:linkattrs:
 = Plugin Lifecycle
 
 Most of the plugins are hosted on the same instance as the
-link:https://gerrit-review.googlesource.com[Gerrit project itself] to make them
+link:https://gerrit-review.googlesource.com[Gerrit project itself,role=external,window=_blank] to make them
 more discoverable and have more chances to be reviewed by the whole community.
 
 [[hosting_lifecycle]]
@@ -12,7 +13,7 @@
 - Ideation and Discussion:
 +
 The idea of creating a new plugin is posted and discussed on the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss] mailing list.
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank] mailing list.
 +
 Also see section link#ideation_discussion[Ideation and discussion] below.
 
@@ -27,14 +28,14 @@
 +
 The author proposes to release the plugin under the
 link:https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 OpenSource
-license] and requests the plugin to be hosted on
-link:https://gerrit-review.googlesource.com[the Gerrit project site]. The
+license,role=external,window=_blank] and requests the plugin to be hosted on
+link:https://gerrit-review.googlesource.com[the Gerrit project site,role=external,window=_blank]. The
 proposal must be   accepted by at least one Gerrit maintainer. In case of
 disagreement between maintainers, the issue can be escalated to the
 link:dev-processes.html#steering-committee[Engineering Steering Committee]. If
 the plugin is accepted, the Gerrit maintainer creates the project under the
 plugins path on link:https://gerrit-review.googlesource.com[the Gerrit project
-site].
+site,role=external,window=_blank].
 +
 Also see section link#plugin_proposal[Plugin Proposal] below.
 
@@ -42,7 +43,7 @@
 +
 To make the consumption of the plugin easy and to notice plugin breakages early
 the plugin author should setup build jobs on
-link:https://gerrit-ci.gerritforge.com[the GerritForge CI] that build the
+link:https://gerrit-ci.gerritforge.com[the GerritForge CI,role=external,window=_blank] that build the
 plugin for each Gerrit version that it supports.
 +
 Also see section link#build[Build] below.
@@ -58,7 +59,7 @@
 - Release:
 +
 The author releases the plugin by creating a Git tag and announcing the plugin
-on the link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+on the link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
 mailing list.
 +
 Also see section link#plugin_release[Plugin release] below.
@@ -84,7 +85,7 @@
 contribution of ideas and suggestions by the whole community.
 
 The ideator of the plugin starts with an RFC (Request For Comments) post on the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss] mailing list
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank] mailing list
 with a description of the main reasons for starting a new plugin.
 
 Example of a post:
@@ -138,9 +139,9 @@
 
 The author decides that the plugin prototype makes sense as a general purpose
 plugin and decides to release the code with the same
-link:https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license]
+link:https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license,role=external,window=_blank]
 as the Gerrit Code Review project and have it hosted on
-link:https://gerrit-review.googlesource.com[the Gerrit project site].
+link:https://gerrit-review.googlesource.com[the Gerrit project site,role=external,window=_blank].
 
 The plugin author formalizes the proposal with a follow-up of the initial RFC
 post and asks for public opinion on it.
@@ -167,7 +168,7 @@
 - The plugin's project request is widely appreciated and formally accepted by
   at least one Gerrit maintainer who creates the repository as child project of
   'Public-Projects' on link:https://gerrit-review.googlesource.com[the Gerrit
-  project site], creates an associated plugin owners group with "Owner"
+  project site,role=external,window=_blank], creates an associated plugin owners group with "Owner"
   permissions for the plugin and adds the plugin's author as member of it.
 - The plugin's project is widely appreciated; however, another existing plugin
   already partially covers the same use-case and thus it would make more sense
@@ -177,15 +178,15 @@
 - The plugin's project is found useful; however, it is too specific to the
   author's use-case and would not make sense outside of it. The plugin remains
   in a public repository, widely accessible and OpenSource, but not hosted on
-  link:https://gerrit-review.googlesource.com[the Gerrit project site].
+  link:https://gerrit-review.googlesource.com[the Gerrit project site,role=external,window=_blank].
 
 [[build]]
 == Build
 
 The plugin's maintainer creates a job on the
-link:https://gerrit-ci.gerritforge.com[GerritForge CI] by creating a new YAML
+link:https://gerrit-ci.gerritforge.com[GerritForge CI,role=external,window=_blank] by creating a new YAML
 definition in the link:https://gerrit.googlesource.com/gerrit-ci-scripts[Gerrit
-CI Scripts] repository.
+CI Scripts,role=external,window=_blank] repository.
 
 Example of a YAML CI job for plugins:
 
@@ -203,7 +204,7 @@
 
 The plugin follows the same lifecycle as Gerrit Code Review and needs to be
 kept up-to-date with the current active branches, according to the
-link:https://www.gerritcodereview.com/#support[current support policy].
+link:https://www.gerritcodereview.com/#support[current support policy,role=external,window=_blank].
 During the development, the plugin's maintainer can reward contributors
 requesting to be more involved and making them maintainers of his plugin,
 adding them to the list of the project owners.
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 4408d93..c3df396 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Plugin Development
 
 The Gerrit server functionality can be extended by installing plugins.
@@ -36,7 +37,7 @@
 
 To get started with the development of a plugin, take a look at
 the samples in the
-link:https://gerrit.googlesource.com/plugins/examples[examples plugin project].
+link:https://gerrit.googlesource.com/plugins/examples[examples plugin project,role=external,window=_blank].
 
 This is a project that demonstrates the various features of the
 plugin API. It can be taken as an example to develop an own plugin.
@@ -367,7 +368,7 @@
 Plugins are loaded from a single JAR file. If a plugin needs
 additional libraries, it must include those dependencies within
 its own JAR. Plugins built using Maven may be able to use the
-link:http://maven.apache.org/plugins/maven-shade-plugin/[shade plugin]
+link:http://maven.apache.org/plugins/maven-shade-plugin/[shade plugin,role=external,window=_blank]
 to package additional dependencies. Relocating (or renaming) classes
 should not be necessary due to the ClassLoader isolation.
 
@@ -1284,6 +1285,39 @@
 }
 ----
 
+== Trace Event origin
+
+When plugins are installed in a multi-master setups it can be useful to know
+the Gerrit `instanceId` of the server that has generated an Event.
+
+E.g. A plugin that sends an instance message for every comment on a change may
+want to react only if the event is generated on the local Gerrit master, for
+avoiding duplicating the notifications.
+
+If link:config-gerrit.html[instanceId] is set, each Event will contain its
+origin in the `instanceId` field.
+
+Here and example of ref-updated JSON event payload with `instanceId`:
+
+[source,json]
+---
+{
+  "submitter": {
+    "name": "Administrator",
+    "email": "admin@example.com",
+    "username": "admin"
+  },
+  "refUpdate": {
+    "oldRev": "a69fc95c7aad5ad41c618d31548b8af835d2959a",
+    "newRev": "31da6556d638a74e5370b62f83e8007f94abb7c6",
+    "refName": "refs/changes/01/1/meta",
+    "project": "test"
+  },
+  "type": "ref-updated",
+  "eventCreatedOn": 1588849085,
+  "instanceId": "instance1"
+}
+---
 
 [[capabilities]]
 == Plugin Owned Capabilities
@@ -2201,7 +2235,7 @@
 
 Gerrit provides an extension point that enables development of
 link:https://github.com/github/git-lfs/blob/master/docs/api/v1/http-v1-batch.md[
-LFS (Large File Storage)] storage plugins. Gerrit core exposes the default LFS
+LFS (Large File Storage),role=external,window=_blank] storage plugins. Gerrit core exposes the default LFS
 protocol endpoint `<project-name>/info/lfs/objects/batch` and forwards the requests
 to the configured link:config-gerrit.html#lfs[lfs.plugin] plugin which implements
 the LFS protocol. By exposing the default LFS endpoint, the git-lfs client can be
@@ -2259,16 +2293,16 @@
 To send Gerrit's metrics data to an external reporting backend, a plugin can
 get a `MetricRegistry` injected and register an instance of a class that
 implements the `Reporter` interface from link:http://metrics.dropwizard.io/[
-DropWizard Metrics].
+DropWizard Metrics,role=external,window=_blank].
 
 Metric reporting plugin implementations are provided for
-link:https://gerrit.googlesource.com/plugins/metrics-reporter-jmx/[JMX],
-link:https://gerrit.googlesource.com/plugins/metrics-reporter-elasticsearch/[Elastic Search],
-and link:https://gerrit.googlesource.com/plugins/metrics-reporter-graphite/[Graphite].
+link:https://gerrit.googlesource.com/plugins/metrics-reporter-jmx/[JMX,role=external,window=_blank],
+link:https://gerrit.googlesource.com/plugins/metrics-reporter-elasticsearch/[Elastic Search,role=external,window=_blank],
+and link:https://gerrit.googlesource.com/plugins/metrics-reporter-graphite/[Graphite,role=external,window=_blank].
 
 There is also a working example of reporting metrics to the console in the
 link:https://gerrit.googlesource.com/plugins/cookbook-plugin/+/master/src/main/java/com/googlesource/gerrit/plugins/cookbook/ConsoleMetricReporter.java[
-cookbook plugin].
+cookbook plugin,role=external,window=_blank].
 
 === Providing own metrics
 
@@ -2305,7 +2339,7 @@
 
 See the replication metrics in the
 link:https://gerrit.googlesource.com/plugins/replication/+/master/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationMetrics.java[
-replication plugin] for an example of usage.
+replication plugin,role=external,window=_blank] for an example of usage.
 
 [[account-patch-review-store]]
 == AccountPatchReviewStore
@@ -2351,7 +2385,7 @@
 attribute.
 
 Documentation may be written in the Markdown flavor
-link:https://github.com/vsch/flexmark-java[flexmark-java]
+link:https://github.com/vsch/flexmark-java[flexmark-java,role=external,window=_blank]
 if the file name ends with `.md`. Gerrit will automatically convert
 Markdown to HTML if accessed with extension `.html`.
 
@@ -2765,6 +2799,9 @@
 this interface can be used to retry the request instead of failing it
 immediately.
 
+It also allows implementors to group exceptions that have the same
+cause into one metric bucket.
+
 [[mail-soy-template-provider]]
 == MailSoyTemplateProvider
 
diff --git a/Documentation/dev-processes.txt b/Documentation/dev-processes.txt
index 09dcbee..0fe2372 100644
--- a/Documentation/dev-processes.txt
+++ b/Documentation/dev-processes.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Development Processes
 
 [[project-governance]]
@@ -7,7 +8,8 @@
 The Gerrit project has an engineering steering committee (ESC) that is
 in charge of:
 
-* Gerrit core (the `gerrit` project) and the core plugins
+* Gerrit core (the `gerrit` project) and the link:dev-core-plugins.html[core
+  plugins]
 * defining the project vision and the project scope
 * maintaining a roadmap, a release plan and a prioritized backlog
 * ensuring timely design reviews
@@ -29,7 +31,7 @@
   period of 1 year (see link:#steering-committee-election[below])
 
 Refer to the project homepage for the link:https://www.gerritcodereview.com/members.html#engineering-steering-committee[
-list of current committee members].
+list of current committee members,role=external,window=_blank].
 
 The steering committee should act in the interest of the Gerrit project
 and the whole Gerrit community.
@@ -53,18 +55,35 @@
 The election of the non-Google steering committee members happens once
 a year in May. Non-Google link:dev-roles.html#maintainer[maintainers]
 can nominate themselves by posting an informal application on the
-non-public maintainers mailing list by end of April (deadline for 2019
-is Mon 13th of May). By applying to be steering committee member, the
-candidate confirms to be able to dedicate the time that is needed to
-fulfill this role (also see
-link:dev-roles.html#steering-committee-member[steering committee
+non-public mailto:gerritcodereview-community-managers@googlegroups.com[
+community manager mailing list] by end of April (deadline for 2020
+is Thu 30th of April EOD).
+
+The list with all candidates will be published at the beginning of the
+voting period (for 2020 the start of the voting is planned for Mon 4th
+of May).
+
+Keeping the candidates private during the nomination phase and
+publishing all candidates at once only at the start of the voting
+period ensures that:
+
+* people do not start voting before all candidates are known and the
+  voting period has started
+* candidates that announce their candidacy early do not have an
+  advantage
+* people are not discouraged to candidate when there are already other
+  candidates
+
+By applying to be steering committee member, the candidate confirms to
+be able to dedicate the time that is needed to fulfill this role (also
+see link:dev-roles.html#steering-committee-member[steering committee
 member]).
 
 Each non-Google maintainer can vote for 2 candidates. The voting
-happens by posting on the maintainer mailing list. The voting period is
-14 calendar days from the nomination deadline (except for 2019, where
-the initial steering committee should be confirmed during the Munich
-hackathon, the voting period goes from 14th May to 16th May).
+happens by posting on the
+mailto:gerritcodereview-maintainers@googlegroups.com[maintainer mailing
+list]. The voting period is 14 calendar days from the start of the
+voting (for 2020 the voting period ends on Mon 18th May EOD).
 
 Google maintainers do not take part in this vote, because Google
 already has dedicated seats in the steering committee (see section
@@ -83,7 +102,7 @@
 [[versioning]]
 == Semantic versioning
 
-Gerrit follows a light link:https://semver.org/[semantic versioning scheme] MAJOR.MINOR[.PATCH[.HOTFIX]]
+Gerrit follows a light link:https://semver.org/[semantic versioning scheme,role=external,window=_blank] MAJOR.MINOR[.PATCH[.HOTFIX]]
 format:
 
   * MAJOR is incremented when there are substantial incompatible changes and/or
@@ -181,7 +200,7 @@
 
 To report a security vulnerability file a
 link:https://bugs.chromium.org/p/gerrit/issues/entry?template=Security+Issue[
-security issue] in the Gerrit issue tracker. The visibility of issues that are
+security issue,role=external,window=_blank] in the Gerrit issue tracker. The visibility of issues that are
 created with the `Security Issue` template is automatically restricted to
 Gerrit maintainers and a few long-term contributors. This means as a reporter
 you may not be able to see the issue once it is created. Security issues are
@@ -221,7 +240,7 @@
 address the security vulnerability immediately (either by upgrading to a fixed
 release or applying the mitigation). The information about the security
 vulnerability is disclosed via the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss] mailing list.
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank] mailing list.
 
 [[handle-security-issue]]
 === Handling of the Security Vulnerability
@@ -252,7 +271,7 @@
 +
 Instead security fixes should be implemented and reviewed in the non-public
 link:https://gerrit-review.googlesource.com/admin/repos/gerrit-security-fixes[
-gerrit-security-fixes] repository which is only accessible by Gerrit
+gerrit-security-fixes,role=external,window=_blank] repository which is only accessible by Gerrit
 maintainers and Gerrit community members that work on security fixes.
 +
 The change that fixes the security vulnerability should contain an integration
@@ -283,7 +302,7 @@
 Once all releases are ready and tested and the announcement is prepared, the
 releases should be all published at the same time. Immediately after that, the
 announcement should be sent out to the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss] mailing list.
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank] mailing list.
 +
 This ends the embargo and any issue that discusses the security vulnerability
 should be made public.
@@ -292,7 +311,12 @@
 +
 The ESC should discuss if there are any learnings from the security
 vulnerability and define action items to follow up in the
-link:https://bugs.chromium.org/p/gerrit[issue tracker].
+link:https://bugs.chromium.org/p/gerrit[issue tracker,role=external,window=_blank].
+
+[[core-plugins]]
+== Core Plugins
+
+See link:dev-core-plugins.html[here].
 
 [[upgrading-libraries]]
 == Upgrading Libraries
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt
index ad25147..2748413 100644
--- a/Documentation/dev-readme.txt
+++ b/Documentation/dev-readme.txt
@@ -1,10 +1,12 @@
+:linkattrs:
 = Gerrit Code Review: Developer Setup
 
-To build a developer instance, you'll need link:https://bazel.build/[Bazel] to
-compile the code, preferably launched with link:https://github.com/bazelbuild/bazelisk[Bazelisk].
+To build a developer instance, you'll need link:https://bazel.build/[Bazel,role=external,window=_blank] to
+compile the code, preferably launched with link:https://github.com/bazelbuild/bazelisk[Bazelisk,role=external,window=_blank].
 
 == Git Setup
 
+[[clone]]
 === Getting the Source
 
 Create a new client workspace:
@@ -30,7 +32,7 @@
 
 CAUTION: If you store Eclipse or IntelliJ project files in the Gerrit source
 directories, do *_not_* run `git clean -fdx`. Doing so may remove untracked files and damage your project. For more information, see
-link:https://git-scm.com/docs/git-clean[git-clean].
+link:https://git-scm.com/docs/git-clean[git-clean,role=external,window=_blank].
 
 Run the following:
 
@@ -64,7 +66,7 @@
 === End-to-end tests
 
 <<dev-e2e-tests#,This document>> describes how `e2e` (load or functional) test
-scenarios are implemented using link:https://gatling.io/[`Gatling`].
+scenarios are implemented using link:https://gatling.io/[`Gatling`,role=external,window=_blank].
 
 
 == Local server
diff --git a/Documentation/dev-release-deploy-config.txt b/Documentation/dev-release-deploy-config.txt
index 98a3df5..a4ccccf 100644
--- a/Documentation/dev-release-deploy-config.txt
+++ b/Documentation/dev-release-deploy-config.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Deploy Gerrit Artifacts
 
 [[deploy-configuration-setting-maven-central]]
@@ -11,7 +12,7 @@
 be done:
 
 * Create an account on
-link:https://issues.sonatype.org/secure/Signup!default.jspa[Sonatype's Jira].
+link:https://issues.sonatype.org/secure/Signup!default.jspa[Sonatype's Jira,role=external,window=_blank].
 +
 Sonatype is the company that runs Maven Central and you need a Sonatype
 account to be able to upload artifacts to Maven Central.
@@ -30,7 +31,7 @@
 repository on Maven Central:
 +
 Ask for this permission by adding a comment on the
-link:https://issues.sonatype.org/browse/OSSRH-7392[OSSRH-7392] Jira
+link:https://issues.sonatype.org/browse/OSSRH-7392[OSSRH-7392,role=external,window=_blank] Jira
 ticket at Sonatype.
 +
 The request needs to be approved by someone who already has this
@@ -43,7 +44,7 @@
 +
 Generate and publish a PGP key as described in
 link:http://central.sonatype.org/pages/working-with-pgp-signatures.html[
-Working with PGP Signatures]. In addition to the keyserver mentioned
+Working with PGP Signatures,role=external,window=_blank]. In addition to the keyserver mentioned
 there it is recommended to also publish the key to the
 link:https://keyserver.ubuntu.com/[Ubuntu key server].
 +
@@ -51,7 +52,7 @@
 while until it is visible to the Sonatype server.
 +
 Add an entry for the public key in the
-link:https://gerrit.googlesource.com/homepage/+/md-pages/releases/public-keys.md[key list]
+link:https://gerrit.googlesource.com/homepage/+/md-pages/releases/public-keys.md[key list,role=external,window=_blank]
 on the homepage.
 +
 The PGP passphrase can be put in `~/.m2/settings.xml`:
@@ -80,7 +81,7 @@
 
 Gerrit Subproject Artifacts are stored on
 link:https://developers.google.com/storage/[Google Cloud Storage].
-Via the link:https://console.developers.google.com/project/164060093628[Developers Console] the
+Via the link:https://console.developers.google.com/project/164060093628[Developers Console,role=external,window=_blank] the
 Gerrit maintainers have access to the `Gerrit Code Review` project.
 This projects host several buckets for storing Gerrit artifacts:
 
@@ -96,7 +97,7 @@
 To upload artifacts to a bucket the user must authenticate with a
 username and password. The username and password need to be retrieved
 from the link:https://console.cloud.google.com/storage/settings?project=api-project-164060093628[
-Storage Setting in the Google Cloud Platform Console]:
+Storage Setting in the Google Cloud Platform Console,role=external,window=_blank]:
 
 Select the `Interoperability` tab, and if no keys are listed under
 `Interoperable storage access keys`, select 'Create a new key'.
diff --git a/Documentation/dev-release-subproject.txt b/Documentation/dev-release-subproject.txt
index c9369b9..fad1681 100644
--- a/Documentation/dev-release-subproject.txt
+++ b/Documentation/dev-release-subproject.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Making a Release of a Gerrit Subproject
 
 [[make-snapshot]]
diff --git a/Documentation/dev-release.txt b/Documentation/dev-release.txt
index 2131d00..a7240e2 100644
--- a/Documentation/dev-release.txt
+++ b/Documentation/dev-release.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Making a Gerrit Release
 
 [NOTE]
@@ -89,7 +90,8 @@
 === Update homepage links
 
 Upload a change on the link:https://gerrit-review.googlesource.com/admin/repos/homepage[
-homepage project] to change the version numbers to the new version.
+homepage project,role=external,window=_blank] to change the version numbers
+to the new version.
 
 [[update-issues]]
 === Update the Issues
@@ -139,9 +141,10 @@
 ----
 
 If unable to tag, make sure that git is locally
-link:https://medium.com/@rwbutler/signing-commits-using-gpg-on-macos-7210362d15[configured with your user's key].
-These are the macOS instructions but such commands should be portable enough.
-Setting `GPG_TTY` this way or similar might also be necessary:
+link:https://medium.com/@rwbutler/signing-commits-using-gpg-on-macos-7210362d15[
+configured with your user's key,role=external,window=_blank]. These are the
+macOS instructions but such commands should be portable enough. Setting
+`GPG_TTY` this way or similar might also be necessary:
 
 ----
   export GPG_TTY=$(tty)
@@ -210,14 +213,14 @@
 ** SNAPSHOT versions are directly uploaded into the Sonatype snapshots
 repository and no further action is needed:
 +
-https://oss.sonatype.org/content/repositories/snapshots/com/google/gerrit/
+https://oss.sonatype.org/content/repositories/snapshots/com/google/gerrit/[role=external,window=_blank]
 
 ** Release versions are uploaded into a staging repository in the
-link:https://oss.sonatype.org/[Sonatype Nexus Server].
+link:https://oss.sonatype.org/[Sonatype Nexus Server,role=external,window=_blank].
 
 * Verify the staging repository
 
-** Go to the link:https://oss.sonatype.org/[Sonatype Nexus Server] and
+** Go to the link:https://oss.sonatype.org/[Sonatype Nexus Server,role=external,window=_blank] and
 sign in with your Sonatype credentials.
 
 ** Click on 'Build Promotion' in the left navigation bar under
@@ -240,7 +243,7 @@
 ** Test closed staging repository
 +
 Once a repository is closed you can find the URL to it in the `Summary`
-section, e.g. https://oss.sonatype.org/content/repositories/comgooglegerrit-1029.
+section, e.g. https://oss.sonatype.org/content/repositories/comgooglegerrit-1029[role=external,window=_blank].
 +
 Use this URL for further testing of the artifacts in this repository,
 e.g. to try building a plugin against the plugin API in this repository
@@ -259,27 +262,27 @@
 +
 How to release a staging repository is described in the
 link:https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide#SonatypeOSSMavenRepositoryUsageGuide-8.a.2.ReleasingaStagingRepository[
-Sonatype OSS Maven Repository Usage Guide].
+Sonatype OSS Maven Repository Usage Guide,role=external,window=_blank].
 +
 [WARNING]
 Releasing artifacts to Maven Central cannot be undone!
 
 ** Find the closed staging repository in the
-link:https://oss.sonatype.org/[Sonatype Nexus Server], select it and
-click on `Release`.
+link:https://oss.sonatype.org/[Sonatype Nexus Server,role=external,window=_blank],
+select it and click on `Release`.
 
 ** The released artifacts are available in
-https://oss.sonatype.org/content/repositories/releases/com/google/gerrit/.
+https://oss.sonatype.org/content/repositories/releases/com/google/gerrit/[role=external,window=_blank].
 
 ** It may take up to 2 hours until the artifacts appear on Maven
 Central:
 +
-https://repo1.maven.org/maven2/com/google/gerrit/
+https://repo1.maven.org/maven2/com/google/gerrit/[role=external,window=_blank]
 
 * [optional]: View download statistics
 
 ** Sign in to the
-link:https://oss.sonatype.org/[Sonatype Nexus Server].
+link:https://oss.sonatype.org/[Sonatype Nexus Server,role=external,window=_blank].
 
 ** Click on 'Views/Repositories' in the left navigation bar under
 'Central Statistics'.
@@ -290,7 +293,7 @@
 ==== Publish the Gerrit WAR to the Google Cloud Storage
 
 * Go to the link:https://console.cloud.google.com/storage/browser/gerrit-releases/?project=api-project-164060093628[
-gerrit-releases bucket in the Google cloud storage console].
+gerrit-releases bucket in the Google cloud storage console,role=external,window=_blank].
 
 * Make sure you are signed in with your Gmail account.
 
@@ -301,7 +304,7 @@
 
 * Create the stable branch `stable-$version` in the `gerrit` project via the
 link:https://gerrit-review.googlesource.com/admin/repos/gerrit,branches[
-Gerrit Web UI] or by push.
+Gerrit Web UI,role=external,window=_blank] or by push.
 
 * Push the commits done on `stable-$version` to `refs/for/stable-$version` and
 get them merged.
@@ -333,7 +336,7 @@
 * Upload the files manually via web browser to the appropriate folder
 in the
 link:https://console.cloud.google.com/storage/browser/gerrit-documentation/?project=api-project-164060093628[
-gerrit-documentation] storage bucket.
+gerrit-documentation,role=external,window=_blank] storage bucket.
 
 [[finalize-release-notes]]
 === Finalize the Release Notes
@@ -397,7 +400,7 @@
 
 Bazlets is used by gerrit plugins to simplify build process. To allow the
 new released version to be used by gerrit plugins,
-link:https://gerrit.googlesource.com/bazlets/+/master/gerrit_api.bzl#8[gerrit_api.bzl]
+link:https://gerrit.googlesource.com/bazlets/+/master/gerrit_api.bzl#8[gerrit_api.bzl,role=external,window=_blank]
 must reference the new version. Upload a change to bazlets repository with
 api version upgrade.
 
diff --git a/Documentation/dev-roles.txt b/Documentation/dev-roles.txt
index 9dbc450..2ca7f22 100644
--- a/Documentation/dev-roles.txt
+++ b/Documentation/dev-roles.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Supporting Roles
 
 As an open source project Gerrit has a large community of people
@@ -14,19 +15,19 @@
 There are many possibilities to support the project, e.g.:
 
 * get involved in discussions on the
-  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
   mailing list (post your questions, provide feedback, share your
   experiences, help other users)
 * attend community events like user summits (see
   link:https://calendar.google.com/calendar?cid=Z29vZ2xlLmNvbV91YmIxcGxhNmlqNzg1b3FianI2MWg0dmRpc0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t[
-  community calendar])
-* report link:https://bugs.chromium.org/p/gerrit/issues/list[issues]
+  community calendar,role=external,window=_blank])
+* report link:https://bugs.chromium.org/p/gerrit/issues/list[issues,role=external,window=_blank]
   and help to clarify existing issues
 * provide feedback on
   link:https://www.gerritcodereview.com/releases-readme.html[new
-  releases and release candidates]
+  releases and release candidates,role=external,window=_blank]
 * review
-  link:https://gerrit-review.googlesource.com/q/status:open[changes]
+  link:https://gerrit-review.googlesource.com/q/status:open[changes,role=external,window=_blank]
   and help to verify that they work as advertised, comment if you like
   or dislike a feature
 * serve as contact person for a proprietary Gerrit installation and
@@ -35,7 +36,7 @@
 Supporters can:
 
 * post on the
-  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
   mailing list (Please note that the `repo-discuss` mailing list is
   managed to prevent spam posts. This means posts from new participants
   must be approved manually before they appear on the mailing list.
@@ -43,7 +44,7 @@
   participate in mailing list discussions frequently are approved
   automatically)
 * comment on
-  link:https://gerrit-review.googlesource.com/q/status:open[changes]
+  link:https://gerrit-review.googlesource.com/q/status:open[changes,role=external,window=_blank]
   and vote from `-1` to `+1` on the `Code-Review` label (these votes
   are important to understand the interest in a change and to address
   concerns early, however link:#maintainer[maintainers] can
@@ -53,7 +54,7 @@
   permissions to vote on the `Verified` label are granted by request,
   see below)
 * file issues in the link:https://bugs.chromium.org/p/gerrit/issues/list[
-  issue tracker] and comment on existing issues
+  issue tracker,role=external,window=_blank] and comment on existing issues
 * support the
   link:dev-processes.html#design-driven-contribution-process[
   design-driven contribution process] by reviewing incoming
@@ -62,7 +63,7 @@
 
 Supporters who want to engage further can get additional privileges
 on request (ask for it on the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
 mailing list):
 
 * become member of the `gerrit-verifiers` group, which allows to:
@@ -71,10 +72,10 @@
 ** edit topics on all open changes
 ** abandon changes
 * approve posts to the
-  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+  link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
   mailing list
 * administrate issues in the
-  link:https://bugs.chromium.org/p/gerrit/issues/list[issue tracker]
+  link:https://bugs.chromium.org/p/gerrit/issues/list[issue tracker,role=external,window=_blank]
 
 Supporters can become link:#contributor[contributors] by signing a
 contributor license agreement and contributing code to the Gerrit
@@ -87,7 +88,7 @@
 agreement] and who has link:dev-contributing.html[contributed] at least
 one change to any project on
 link:https://gerrit-review.googlesource.com/[
-gerrit-review.googlesource.com] is a contributor.
+gerrit-review.googlesource.com,role=external,window=_blank] is a contributor.
 
 Contributions can be:
 
@@ -123,10 +124,10 @@
 
 Contributors may also be invited to join the Gerrit hackathons which
 happen regularly (e.g. twice a year). Hackathons are announced on the
-link:https://groups.google.com/d/forum/repo-discuss[repo-discuss]
+link:https://groups.google.com/d/forum/repo-discuss[repo-discuss,role=external,window=_blank]
 mailing list (also see
 link:https://calendar.google.com/calendar?cid=Z29vZ2xlLmNvbV91YmIxcGxhNmlqNzg1b3FianI2MWg0dmRpc0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t[
-community calendar]).
+community calendar,role=external,window=_blank]).
 
 Outstanding contributors that are actively engaged in the community, in
 activities outlined above, may be nominated as link:#maintainer[
@@ -138,7 +139,7 @@
 Maintainers are the gatekeepers of the project and are in charge of
 approving and submitting changes. Refer to the project homepage for
 the link:https://www.gerritcodereview.com/members.html#maintainers[
-list of current maintainers].
+list of current maintainers,role=external,window=_blank].
 
 Maintainers should only approve changes that:
 
@@ -185,20 +186,20 @@
   link:dev-processes.html#project-governance[Project Governance]
 * nominate new maintainers and vote on nominations (see below)
 * administrate the link:https://groups.google.com/d/forum/repo-discuss[
-  mailing list], the
-  link:https://bugs.chromium.org/p/gerrit/issues/list[issue tracker]
-  and the link:https://www.gerritcodereview.com/[homepage]
+  mailing list,role=external,window=_blank], the
+  link:https://bugs.chromium.org/p/gerrit/issues/list[issue tracker,role=external,window=_blank]
+  and the link:https://www.gerritcodereview.com/[homepage,role=external,window=_blank]
 * gain permissions to do Gerrit releases and publish release artifacts
 * create new projects and groups on
   link:https://gerrit-review.googlesource.com/[
-  gerrit-review.googlesource.com]
+  gerrit-review.googlesource.com,role=external,window=_blank]
 * administrate the Gerrit projects on
   link:https://gerrit-review.googlesource.com/[
-  gerrit-review.googlesource.com] (e.g. edit ACLs, update project
+  gerrit-review.googlesource.com,role=external,window=_blank] (e.g. edit ACLs, update project
   configuration)
 * create events in the
   link:https://calendar.google.com/calendar?cid=Z29vZ2xlLmNvbV91YmIxcGxhNmlqNzg1b3FianI2MWg0dmRpc0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t[
-  community calendar]
+  community calendar,role=external,window=_blank]
 * discuss with other maintainers on the private maintainers mailing
   list and Slack channel
 
@@ -243,7 +244,7 @@
 Members of the steering committee are expected to act in the interest
 of the Gerrit project and the whole Gerrit community. Refer to the project
 homepage for the link:https://www.gerritcodereview.com/members.html#engineering-steering-committee[
-list of current committee members].
+list of current committee members,role=external,window=_blank].
 
 For those that are familiar with scrum, the steering committee member
 role is similar to the role of an agile product owner.
@@ -254,7 +255,7 @@
 requests in a timely manner.
 
 Community members may submit new items under the
-link:https://bugs.chromium.org/p/gerrit/issues/list?q=component:ESC[ESC component]
+link:https://bugs.chromium.org/p/gerrit/issues/list?q=component:ESC[ESC component,role=external,window=_blank]
 in the issue tracker, or add that component to existing items, to raise them to
 the attention of ESC members.
 
@@ -301,7 +302,7 @@
 Community managers should act as stakeholders for the Gerrit community
 and focus on the health of the community. Refer to the project homepage
 for the link:https://www.gerritcodereview.com/members.html#community-managers[
-list of current community managers].
+list of current community managers,role=external,window=_blank].
 
 Tasks:
 
@@ -315,7 +316,7 @@
 * serve as contact person for community issues
 
 Community members may submit new items under the
-link:https://bugs.chromium.org/p/gerrit/issues/list?q=component:Community[Community component]
+link:https://bugs.chromium.org/p/gerrit/issues/list?q=component:Community[Community component,role=external,window=_blank]
 backlog, for community managers to refine. Only public topics should be
 issued through that backlog.
 
diff --git a/Documentation/dev-starter-projects.txt b/Documentation/dev-starter-projects.txt
index ae40ea6..eef4806 100644
--- a/Documentation/dev-starter-projects.txt
+++ b/Documentation/dev-starter-projects.txt
@@ -1,10 +1,11 @@
+:linkattrs:
 = Gerrit Code Review - Starter Projects
 
 We have created a
-link:https://bugs.chromium.org/p/gerrit/issues/list?can=2&q=label%3AStarterProject[StarterProject]
+link:https://bugs.chromium.org/p/gerrit/issues/list?can=2&q=label%3AStarterProject[StarterProject,role=external,window=_blank]
 category in the issue tracker and try to assign easy hack projects to it. If in
 doubt, do not hesitate to ask on the developer
-link:https://groups.google.com/forum/#!forum/repo-discuss[mailing list].
+link:https://groups.google.com/forum/#!forum/repo-discuss[mailing list,role=external,window=_blank].
 
 GERRIT
 ------
diff --git a/Documentation/error-change-closed.txt b/Documentation/error-change-closed.txt
index a239ef1..ae90d6d 100644
--- a/Documentation/error-change-closed.txt
+++ b/Documentation/error-change-closed.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = change ... closed
 
 With this error message Gerrit rejects to push a commit or submit a
@@ -15,7 +16,7 @@
 new change. To do this you have to remove the Change-Id from the
 commit message as explained link:error-push-fails-due-to-commit-message.html[here] and ideally generate a new Change-Id
 using the link:cmd-hook-commit-msg.html[commit hook] or EGit. Before pushing again it is also
-recommended to do a link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git rebase] to base your commit on the submitted
+recommended to do a link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git rebase,role=external,window=_blank] to base your commit on the submitted
 change. Pushing again should now create a new change in Gerrit.
 
 If the change for which you wanted to upload a new patch set was
diff --git a/Documentation/error-changeid-above-footer.txt b/Documentation/error-changeid-above-footer.txt
index abc0186..65d6620 100644
--- a/Documentation/error-changeid-above-footer.txt
+++ b/Documentation/error-changeid-above-footer.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = commit xxxxxxx: Change-Id must be in message footer
 
 With this error message, Gerrit rejects a push of a commit to a project
@@ -8,7 +9,7 @@
 of a commit message. For details, see link:user-changeid.html[Change-Id Lines].
 
 You can see the commit messages for existing commits in the history
-by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log,role=external,window=_blank].
 
 
 == Change-Id is contained in the commit message but not in the last paragraph
diff --git a/Documentation/error-contains-banned-commit.txt b/Documentation/error-contains-banned-commit.txt
index 13a0eaa..1ed4992 100644
--- a/Documentation/error-contains-banned-commit.txt
+++ b/Documentation/error-contains-banned-commit.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = contains banned commit ...
 
 With this error message Gerrit rejects to push a commit that is
@@ -11,7 +12,7 @@
 error message "contains banned commit ...".
 
 If you have commits that you want to push that are based on a banned
-commit you may want to link:http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html[cherry-pick] them onto a clean base and push
+commit you may want to link:http://www.kernel.org/pub/software/scm/git/docs/git-cherry-pick.html[cherry-pick,role=external,window=_blank] them onto a clean base and push
 them again.
 
 
diff --git a/Documentation/error-has-duplicates.txt b/Documentation/error-has-duplicates.txt
index a520f5d..9f9c8a8 100644
--- a/Documentation/error-has-duplicates.txt
+++ b/Documentation/error-has-duplicates.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = ... has duplicates
 
 With this error message Gerrit rejects to push a commit if its commit
@@ -10,7 +11,7 @@
 
 Since this error should never occur in practice, you should inform
 your Gerrit administrator if you hit this problem and/or
-link:https://bugs.chromium.org/p/gerrit/issues/list[open a Gerrit issue].
+link:https://bugs.chromium.org/p/gerrit/issues/list[open a Gerrit issue,role=external,window=_blank].
 
 In any case to not be blocked with your work, you can simply create a
 new Change-Id for your commit and then push it as new change to
diff --git a/Documentation/error-invalid-author.txt b/Documentation/error-invalid-author.txt
index 5808d4f..d842cb7 100644
--- a/Documentation/error-invalid-author.txt
+++ b/Documentation/error-invalid-author.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = invalid author
 
 For every pushed commit Gerrit verifies that the e-mail address of
@@ -121,7 +122,7 @@
 ----
 
 For further details about git rebase please check the
-link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation].
+link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation,role=external,window=_blank].
 
 
 == Missing privileges to push commits of other users
diff --git a/Documentation/error-invalid-changeid-line.txt b/Documentation/error-invalid-changeid-line.txt
index 9d3d2fc..a0f4b7b 100644
--- a/Documentation/error-invalid-changeid-line.txt
+++ b/Documentation/error-invalid-changeid-line.txt
@@ -1,10 +1,11 @@
+:linkattrs:
 = invalid Change-Id line format in commit message footer
 
 With this error message Gerrit rejects to push a commit if its commit
 message footer contains an invalid Change-Id line.
 
 You can see the commit messages for existing commits in the history
-by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log,role=external,window=_blank].
 
 If it was the intention to rework a change and to push a new patch
 set, find the change in the Gerrit Web UI, copy its Change-Id line and
diff --git a/Documentation/error-invalid-committer.txt b/Documentation/error-invalid-committer.txt
index a669010..c06eba2 100644
--- a/Documentation/error-invalid-committer.txt
+++ b/Documentation/error-invalid-committer.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = invalid committer
 
 For every pushed commit Gerrit verifies that the e-mail address of
@@ -86,7 +87,7 @@
 commits and then confirming all the commit messages). Just picking
 all the changes will not work as in this case the committer is not
 rewritten. For further details about git rebase please check the
-link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation].
+link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation,role=external,window=_blank].
 
 
 == Missing privileges to push commits that were committed by other users
diff --git a/Documentation/error-missing-changeid.txt b/Documentation/error-missing-changeid.txt
index 27bfea5..3494c3f 100644
--- a/Documentation/error-missing-changeid.txt
+++ b/Documentation/error-missing-changeid.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = commit xxxxxxx: missing Change-Id in message footer
 
 With this error message Gerrit rejects to push a commit to a project
@@ -6,7 +7,7 @@
 a Change-Id.
 
 You can see the commit messages for existing commits in the history
-by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log,role=external,window=_blank].
 
 To avoid this error you should use the link:cmd-hook-commit-msg.html[commit hook] or EGit to
 automatically create and insert a unique Change-Id into the commit
diff --git a/Documentation/error-missing-subject.txt b/Documentation/error-missing-subject.txt
index 6ef37a4..af628fa 100644
--- a/Documentation/error-missing-subject.txt
+++ b/Documentation/error-missing-subject.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = commit xxxxxxx: missing subject; Change-Id must be in message footer
 
 With this error message Gerrit rejects to push a commit to a project
@@ -9,7 +10,7 @@
 message.
 
 You can see the commit messages for existing commits in the history
-by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log,role=external,window=_blank].
 
 == Change-Id is the only line in the commit message
 
diff --git a/Documentation/error-multiple-changeid-lines.txt b/Documentation/error-multiple-changeid-lines.txt
index 31567f4..f19ebddd 100644
--- a/Documentation/error-multiple-changeid-lines.txt
+++ b/Documentation/error-multiple-changeid-lines.txt
@@ -1,10 +1,11 @@
+:linkattrs:
 = commit xxxxxxx: multiple Change-Id lines in message footer
 
 With this error message Gerrit rejects to push a commit if the commit
 message footer of the pushed commit contains several Change-Id lines.
 
 You can see the commit messages for existing commits in the history
-by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log,role=external,window=_blank].
 
 If it was the intention to rework a change and to push a new patch
 set, find the change in the Gerrit Web UI, copy its Change-Id line and
diff --git a/Documentation/error-no-new-changes.txt b/Documentation/error-no-new-changes.txt
index 45586c3..6434b2f 100644
--- a/Documentation/error-no-new-changes.txt
+++ b/Documentation/error-no-new-changes.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = no new changes
 
 With this error message Gerrit rejects to push a commit if the pushed
@@ -39,12 +40,12 @@
   link:user-upload.html#base[exception].
 
 If you need to re-push a commit you may rewrite this commit by
-link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[amending]
+link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[amending,role=external,window=_blank]
 it or doing an interactive
-link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git
-rebase], or see link:user-upload.html#base[exception]. By rewriting the
-commit you actually create a new commit (with a new commit ID in
-project scope) which can then be pushed to Gerrit.
+link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git rebase,role=external,window=_blank],
+or see link:user-upload.html#base[exception,role=external,window=_blank].
+By rewriting the commit you actually create a new commit
+(with a new commit ID in project scope) which can then be pushed to Gerrit.
 
 If you are pushing the new change to the same destination branch as
 the old commit (case 1 above), you also need to replace it with a new
diff --git a/Documentation/error-non-fast-forward.txt b/Documentation/error-non-fast-forward.txt
index 923132e..1e9a88f3 100644
--- a/Documentation/error-non-fast-forward.txt
+++ b/Documentation/error-non-fast-forward.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = non-fast forward
 
 With this error message Gerrit rejects a push if the remote branch can't
@@ -28,8 +29,8 @@
 bypassing code review, your push will be rejected with the error
 message 'non-fast forward'. To solve the problem you have to either
 
-. link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[rebase] your commit on the new tip of the remote branch or
-. link:http://www.kernel.org/pub/software/scm/git/docs/git-merge.html[merge] your commit with the new tip of the remote branch.
+. link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[rebase,role=external,window=_blank] your commit on the new tip of the remote branch or
+. link:http://www.kernel.org/pub/software/scm/git/docs/git-merge.html[merge,role=external,window=_blank] your commit with the new tip of the remote branch.
 
 Afterwards the push should be successful.
 
@@ -46,7 +47,7 @@
 Although it is considered bad practice, it is possible to allow
 non-fast forward updates with Git. For this the remote Git repository
 has to be configured to not deny non-fast forward updates (set the
-link:http://www.kernel.org/pub/software/scm/git/docs/git-config.html[Git configuration] parameter 'receive.denyNonFastForwards' to
+link:http://www.kernel.org/pub/software/scm/git/docs/git-config.html[Git configuration,role=external,window=_blank] parameter 'receive.denyNonFastForwards' to
 'false'). Then it is possible to push a non-fast forward update by
 using the '--force' option.
 
diff --git a/Documentation/error-not-allowed-to-upload-merges.txt b/Documentation/error-not-allowed-to-upload-merges.txt
index d025bd0..5ba4c69 100644
--- a/Documentation/error-not-allowed-to-upload-merges.txt
+++ b/Documentation/error-not-allowed-to-upload-merges.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = you are not allowed to upload merges
 
 With this error message Gerrit rejects to push a merge commit if the
@@ -12,7 +13,7 @@
 If one of your changes could not be merged in Gerrit due to conflicts
 and you created the merge commit to resolve the conflicts, you might
 want to revert the merge and instead of this do a
-link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[rebase].
+link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[rebase,role=external,window=_blank].
 
 
 GERRIT
diff --git a/Documentation/error-permission-denied.txt b/Documentation/error-permission-denied.txt
index 879273d..fba1d44 100644
--- a/Documentation/error-permission-denied.txt
+++ b/Documentation/error-permission-denied.txt
@@ -1,10 +1,11 @@
+:linkattrs:
 = Permission denied (publickey)
 
 With this error message an SSH command to Gerrit is rejected if the
 SSH authentication is not successful.
 
-The link:http://en.wikipedia.org/wiki/Secure_Shell[SSH] protocol can use
-link:http://en.wikipedia.org/wiki/Public-key_cryptography[Public-key Cryptography]
+The link:http://en.wikipedia.org/wiki/Secure_Shell[SSH,role=external,window=_blank] protocol can use
+link:http://en.wikipedia.org/wiki/Public-key_cryptography[Public-key Cryptography,role=external,window=_blank]
 for authentication.
 In general configurations, Gerrit will authenticate you by the public keys
 known to you. Optionally, it can be configured by the administrator to allow
diff --git a/Documentation/error-push-fails-due-to-commit-message.txt b/Documentation/error-push-fails-due-to-commit-message.txt
index f6e5c1f..3f992f6 100644
--- a/Documentation/error-push-fails-due-to-commit-message.txt
+++ b/Documentation/error-push-fails-due-to-commit-message.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Push fails due to commit message
 
 If Gerrit rejects pushing a commit it is often the case that there is
@@ -6,7 +7,7 @@
 
 If the commit message of the last commit needs to be fixed you can
 simply amend the last commit (please find a detailed description in
-the link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[Git documentation]):
+the link:http://www.kernel.org/pub/software/scm/git/docs/git-commit.html[Git documentation,role=external,window=_blank]):
 
 ----
   $ git commit --amend
@@ -17,7 +18,7 @@
 rebase for the affected commits. While doing the interactive rebase
 you can e.g. choose 'reword' for those commits for which you want to
 fix the commit messages. For a detailed description of git rebase
-please check the link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation].
+please check the link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation,role=external,window=_blank].
 
 Please use interactive git rebase with care as it rewrites existing
 commits. Generally you should never rewrite commits that have already
diff --git a/Documentation/error-same-change-id-in-multiple-changes.txt b/Documentation/error-same-change-id-in-multiple-changes.txt
index b6aad69..4ff623d 100644
--- a/Documentation/error-same-change-id-in-multiple-changes.txt
+++ b/Documentation/error-same-change-id-in-multiple-changes.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = same Change-Id in multiple changes
 
 With this error message Gerrit rejects to push a commit if it
@@ -64,7 +65,7 @@
 the example above where the last two commits have the same Change-Id,
 this means an interactive rebase for the last two commits should be
 done. For further details about the git rebase command please check
-the link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation for rebase].
+the link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[Git documentation for rebase,role=external,window=_blank].
 
 ----
   $ git rebase -i HEAD~2
@@ -100,7 +101,7 @@
 by using a link:cmd-hook-commit-msg.html[commit hook] or by using EGit) or the Change-Id could be
 removed (not recommended since then amending this commit to create
 subsequent patch sets is more error prone). To change the Change-Id
-of an existing commit do an interactive link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git rebase] and fix the
+of an existing commit do an interactive link:http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html[git rebase,role=external,window=_blank] and fix the
 affected commit messages.
 
 
diff --git a/Documentation/error-upload-denied.txt b/Documentation/error-upload-denied.txt
index 30c5f2d..6638335 100644
--- a/Documentation/error-upload-denied.txt
+++ b/Documentation/error-upload-denied.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Upload denied for project ...
 
 With this error message Gerrit rejects to push a commit if the
@@ -9,7 +10,7 @@
 . contact one of the project owners and request upload permissions
   for the project (access right
   link:access-control.html#category_push['Push'])
-. export your commit as a patch using the link:http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html[git format-patch] command
+. export your commit as a patch using the link:http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html[git format-patch,role=external,window=_blank] command
   and provide the patch file to one of the project owners
 
 
diff --git a/Documentation/images/user-review-ui-change-complex-reply-dialogue.png b/Documentation/images/user-review-ui-change-complex-reply-dialogue.png
new file mode 100644
index 0000000..1286852
--- /dev/null
+++ b/Documentation/images/user-review-ui-change-complex-reply-dialogue.png
Binary files differ
diff --git a/Documentation/images/user-review-ui-change-page-download.png b/Documentation/images/user-review-ui-change-page-download.png
new file mode 100644
index 0000000..63c4ee3
--- /dev/null
+++ b/Documentation/images/user-review-ui-change-page-download.png
Binary files differ
diff --git a/Documentation/images/user-review-ui-change-page-patchset-dropdown.png b/Documentation/images/user-review-ui-change-page-patchset-dropdown.png
new file mode 100644
index 0000000..f71473e
--- /dev/null
+++ b/Documentation/images/user-review-ui-change-page-patchset-dropdown.png
Binary files differ
diff --git a/Documentation/images/user-review-ui-change-relation-chain.png b/Documentation/images/user-review-ui-change-relation-chain.png
new file mode 100644
index 0000000..19942f1
--- /dev/null
+++ b/Documentation/images/user-review-ui-change-relation-chain.png
Binary files differ
diff --git a/Documentation/images/user-review-ui-change-reply-dialogue.png b/Documentation/images/user-review-ui-change-reply-dialogue.png
new file mode 100644
index 0000000..3c95852
--- /dev/null
+++ b/Documentation/images/user-review-ui-change-reply-dialogue.png
Binary files differ
diff --git a/Documentation/index.txt b/Documentation/index.txt
index 4de55a7..8f36ecc 100644
--- a/Documentation/index.txt
+++ b/Documentation/index.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review for Git
 
 == Quickstarts
@@ -9,6 +10,7 @@
 . link:intro-quick.html[Product Overview]
 . link:intro-how-gerrit-works.html[How Gerrit Works]
 . link:intro-gerrit-walkthrough.html[Basic Gerrit Walkthrough]
+. link:intro-gerrit-walkthrough-github.html[Basic Gerrit Walkthrough -- For GitHub Users]
 
 == Contributor Guides
 . link:dev-community.html[Gerrit Community]
@@ -17,7 +19,7 @@
 == User Guides
 . link:intro-user.html[User Guide]
 . link:intro-project-owner.html[Project Owner Guide]
-. link:https://source.android.com/source/developing[Default Android Workflow] (external)
+. link:https://source.android.com/source/developing[Default Android Workflow,role=external,window=_blank] (external)
 
 == Tutorials
 . Web
@@ -44,7 +46,7 @@
 . link:access-control.html[Access Controls]
 . Multi-project management
 .. link:user-submodules.html[Submodules]
-.. link:https://source.android.com/source/using-repo.html[Repo] (external)
+.. link:https://source.android.com/source/using-repo.html[Repo,role=external,window=_blank] (external)
 . Prolog rules
 .. link:prolog-cookbook.html[Prolog Cookbook]
 .. link:prolog-change-facts.html[Prolog Facts for Gerrit Changes]
@@ -86,11 +88,11 @@
 
 == Resources
 * link:licenses.html[Licenses and Notices]
-* link:https://www.gerritcodereview.com/[Homepage]
-* link:https://gerrit-releases.storage.googleapis.com/index.html[Downloads]
-* link:https://bugs.chromium.org/p/gerrit/issues/list[Issue Tracking]
-* link:https://gerrit.googlesource.com/gerrit[Source Code]
-* link:https://www.gerritcodereview.com/about.md[A History of Gerrit Code Review]
+* link:https://www.gerritcodereview.com/[Homepage,role=external,window=_blank]
+* link:https://gerrit-releases.storage.googleapis.com/index.html[Downloads,role=external,window=_blank]
+* link:https://bugs.chromium.org/p/gerrit/issues/list[Issue Tracking,role=external,window=_blank]
+* link:https://gerrit.googlesource.com/gerrit[Source Code,role=external,window=_blank]
+* link:https://www.gerritcodereview.com/about.md[A History of Gerrit Code Review,role=external,window=_blank]
 
 GERRIT
 ------
diff --git a/Documentation/install-j2ee.txt b/Documentation/install-j2ee.txt
index 48751b7..fb78a87 100644
--- a/Documentation/install-j2ee.txt
+++ b/Documentation/install-j2ee.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - J2EE Installation
 
 == Description
@@ -47,7 +48,7 @@
 Download and unzip a release version of Jetty.  From here on we
 call the unpacked directory `$JETTY_HOME`.
 
-* link:http://www.eclipse.org/jetty/downloads.php[Jetty Downloads]
+* link:http://www.eclipse.org/jetty/downloads.php[Jetty Downloads,role=external,window=_blank]
 
 If this is a fresh installation of Jetty, move into the installation
 directory and do some cleanup to remove the sample webapps:
@@ -99,7 +100,7 @@
 
 Excerpt from the
 link:https://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html[
-documentation]:
+documentation,role=external,window=_blank]:
 
 ----
 Property org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH:
diff --git a/Documentation/install.txt b/Documentation/install.txt
index 09ebbba..94a576c 100644
--- a/Documentation/install.txt
+++ b/Documentation/install.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Standalone Daemon Installation Guide
 
 [[prerequisites]]
@@ -5,7 +6,7 @@
 
 To run the Gerrit service, the following requirement must be met on the host:
 
-* JRE, versions 1.8 or 11 http://www.oracle.com/technetwork/java/javase/downloads/index.html[Download]
+* JRE, versions 1.8 or 11 http://www.oracle.com/technetwork/java/javase/downloads/index.html[Download,role=external,window=_blank]
 +
 Gerrit is not yet compatible with Java 13 or newer at this time.
 
@@ -22,8 +23,8 @@
 
 . Download the unlimited strength JCE policy files.
 +
-- link:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[JDK7 JCE policy files]
-- link:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html[JDK8 JCE policy files]
+- link:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html[JDK7 JCE policy files,role=external,window=_blank]
+- link:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html[JDK8 JCE policy files,role=external,window=_blank]
 . Uncompress and extract the downloaded file.
 +
 The downloaded file  contains the following files:
@@ -47,7 +48,7 @@
 
 Current and past binary releases of Gerrit can be obtained from
 the link:https://gerrit-releases.storage.googleapis.com/index.html[
-Gerrit Releases site].
+Gerrit Releases site,role=external,window=_blank].
 
 Download any current `*.war` package. The war will be referred to as
 `gerrit.war` from this point forward, so you may find it easier to
@@ -173,7 +174,7 @@
 
 The `ssh-keygen` command must be available during the init phase to
 generate SSH host keys. If you have
-link:https://git-for-windows.github.io/[Git for Windows] installed,
+link:https://git-for-windows.github.io/[Git for Windows,role=external,window=_blank] installed,
 start Command Prompt and temporary add directory with ssh-keygen to the
 PATH environment variable just before running init command:
 
@@ -197,7 +198,7 @@
 
 To install Gerrit as Windows Service use the
 link:http://commons.apache.org/proper/commons-daemon/procrun.html[Apache
-Commons Daemon Procrun].
+Commons Daemon Procrun,role=external,window=_blank].
 
 Sample install command:
 
@@ -235,7 +236,7 @@
 Gerrit's internal SSH daemon.  See the `git-daemon` documentation
 for details on how to configure this if anonymous access is desired.
 
-* http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[man git-daemon]
+* http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[man git-daemon,role=external,window=_blank]
 
 
 [[plugins]]
@@ -246,7 +247,7 @@
 
 == External Documentation Links
 
-* http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[git-daemon]
+* http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[git-daemon,role=external,window=_blank]
 
 
 [[backup]]
diff --git a/Documentation/intro-gerrit-walkthrough-github.txt b/Documentation/intro-gerrit-walkthrough-github.txt
new file mode 100644
index 0000000..f16155b
--- /dev/null
+++ b/Documentation/intro-gerrit-walkthrough-github.txt
@@ -0,0 +1,264 @@
+:linkattrs:
+= Basic Gerrit Walkthrough -- For GitHub Users
+
+
+[NOTE]
+====
+This document aims to provide a concise description of the core principles of
+code review in Gerrit for people that were previously using Pull Requests on
+Github or similar concepts. Nothing in this document is meant to state that
+one or the other might be better, but only aims to help new users understand
+Gerrit more readily. We use Github as the point of comparison since it seems
+to be the most popular service.
+====
+
+To illustrate the differences in a meaningful order, we will walk you through
+the process of cloning a repo, making a change, asking for code review,
+iterating on the code and finally having it submitted to the code base. This
+document also does not aim to describe all features of Gerrit. Please refer to
+the link:intro-gerrit-walkthrough.html[Basic Gerrit Walkthrough] or
+link:index.html[the rest of the documentation] for a more complete overview and additional pointers.
+
+[[tldr]]
+== tl;dr
+
+Here’s how getting code reviewed and submitted with Gerrit is different from
+doing the same with GitHub:
+
+* You need the add a commit-msg hook script when you clone a repo for the first
+time using a snippet you can find e.g. https://gerrit-review.googlesource.com/admin/repos/gerrit[here,role=external,window=_blank];
+* Your review will be on a single commit instead of a branch. You use
+`git commit --amend` to modify a code change.
+* Instead of using the Web UI to create a pull request, you use
+`git push origin HEAD:refs/for/master` to upload new local commits that are
+ready for review to Gerrit. You will find the URL to the review in the output of
+the push command.
+* As a reviewer, Gerrit offers a number of so-called labels to vote on, one of
+which is Code-Review. You indicate a negative, neutral or positive review using
+a -1, 0 or +1 vote.
+* To be able to submit (== merge) a change, you usually need a +2 Code-Review
+vote and possibly additional positive votes, depending on the configuration of
+the project you are contributing to.
+
+[[clone]]
+== 1. Cloning a Repository
+
+[NOTE]
+====
+Both GitHub and Gerrit provide simple Git repository hosting (of course both can
+do much more). In the simplest setup, you could just use both as such without
+any code review to push code. We will assume that this is not what you want to
+do and focus on the use case where your change requires a review.
+====
+
+The first step to working with the code is to clone the repo. For both, Gerrit
+and GitHub, you can simply use the `git clone` command.
+
+For Gerrit, there is an additional step before you can start making changes. For
+reasons we explain below, you’ll have to add a https://gerrit-review.googlesource.com/Documentation/user-changeid.html[commit-msg hook,role=external,window=_blank] script. This will
+append the Gerrit Change-Id to every commit message such that Gerrit can track
+commits through the review process. To make this process a little easier in
+Gerrit, you can find a command snippet for cloning and adding the commit-msg
+hook on the repository page (e.g. https://gerrit-review.googlesource.com/admin/repos/gerrit[here,role=external,window=_blank]).
+
+[[create-change]]
+== 2. Making a Change
+
+*Branches*
+
+Now that you have the code in the git repo on your machine, you can start making
+changes. With GitHub, you would usually create a new branch and then start
+committing to it. This branch would then contain all the changes you share with
+your code reviewers in the next step. Your local branch will usually also be
+pushed to the remote server. This can be handy to back up your work or hand-off
+work to another device or developer.
+
+With Gerrit, you can also create a new local branch to develop in. While not
+required, it can be considered a best practice to sandbox this change from other
+changes you might be making. In contrast to the GitHub model, your local branch
+will not have to be pushed to the remote in Gerrit, at least not for the
+purposes of code review.
+
+*Commits*
+In Gerrit, a single commit is the unit of code that will be reviewed. With
+GitHub, you can commit to your branch as much as you like and the sum of all
+your commits on that branch will get reviewed. As a single commit gets reviewed
+in Gerrit, you need to `git commit --amend` when you iterate on the same change as
+opposed to only using `git commit` with GitHub (see Section 5 for more). You can,
+however, also add another commit on top of your existing commit in Gerrit, which
+will create a second change (and thus another review) that is based on your
+first change. Gerrit will show the relationship between these two changes as a
+so-called relation chain. This also means that your second change can only be
+submitted after the first was successfully merged. In many basic use cases, this
+situation is however not what you want.
+
+image::images/user-review-ui-change-relation-chain.png[Relation chain display on the change page.]
+
+With GitHub, you may be pushing your branch to the remote for non-code-review
+purposes, as mentioned above. You usually do not do this with Gerrit, as
+Gerrit-managed repos often only have one or a few branches on the server that
+can only be merged into via code review.
+
+[[request-review]]
+== 3. Asking for Code Review
+
+After you are satisfied with the changes you made, you’ll usually want/need to
+get your code reviewed. In GitHub, you would push your branch to the remote, go
+to the Web UI and create a pull request. In Gerrit, you need to push your commit
+(or the series of changes/commits) to the remote first, since you usually
+develop in a local branch only. While you can often just use git push with
+GitHub, you need to do a slightly different thing for Gerrit. Gerrit uses a
+“magic” branch that tells the server that this code is supposed to be reviewed.
+To send the changes you made on your local branch to review and being eventually
+merged into the remote’s master branch, you use
+`git push origin HEAD:refs/for/master`. There are also link:user-upload.html#_git_push[a number of Gerrit change
+options] you can trigger from the CLI this way.
+
+After successfully pushing your change to Gerrit, you will already find the URL
+for viewing your change in Gerrit’s Web UI in the response you get from the
+server. The description of the Gerrit code review that was just created is equal
+to the commit message of that one commit the change is based on. In GitHub, you
+might have described your change in the message you can create when creating the
+pull request in the GitHub Web UI.
+
+Next, you would go and visit your Gerrit change in the Web UI to get your change
+ready for review (choose reviewers, cc people, check for failing CI builds or
+tests, etc.), very similar to what you do on Github. Reviewers will be notified
+via email once you add them. By default, anyone can add reviewers to a Gerrit
+change. In GitHub, this ability is reserved for certain users, so you may have
+relied on others adding reviewers for you before. This can be the case in a
+Gerrit project, but it is also often expected that the change owner (usually the
+creator of the change) adds reviewers to get the review process started.
+
+[[reviewing]]
+== 4. Reviewing a Change
+
+Switching perspectives briefly, reviewing a change is fairly similar between
+GitHub and Gerrit. You, as a reviewer, will be notified of a change you have
+been added to via email or see an “incoming” change on your Gerrit dashboard.
+The dashboard is the central overview of changes going on within a Gerrit
+instance. By default, the dashboard shows changes that you are involved in, in
+any way. You can also see all changes on a Gerrit server by using the top menu
+(“Changes” -> “Open”). This view is more similar to what you see on Github, when
+you navigate to the Pull Requests tab of the project/repository you are working
+on. Note, however, that a single Gerrit instance can host multiple projects
+(also referred to as repositories; a list can be found, for example, https://gerrit-review.googlesource.com/admin/repos[here,role=external,window=_blank]). Your
+dashboard and other lists of changes will show all changes across the
+projects/repositories by default.
+
+Back to your dashboard, you can click on the change you want to review. You can
+also access this from the email you received. You will see the same view that
+you saw as an author. In the middle of the change page, you can find the list of
+files that have been modified, just like what you find in the “Files changed”
+tab of GitHub. Also similarly, you can leave comments by highlighting a piece of
+the code and pressing ‘c’. All comments you make are in a draft state and thus
+only visible to you, like on GitHub. When you are done with your review, you
+need to click the “Reply” button at the top of the change page to send your
+assessment to the change owner alongside a “change message” summarizing your
+findings and/or adding higher level comments. Replying to a change makes your
+draft comments and the change message visible on the change page for everyone
+that has view access to this change. This again is fairly similar to GitHub,
+except for Gerrit’s voting labels.
+
+image::images/user-review-ui-change-reply-dialogue.png[Reply dialogue for a Gerrit change.]
+
+As you can see in the screenshot of the reply dialogue, the voting labels are in
+the bottom part of the dialogue. They can be fairly simple as in this case, but
+there can also be a larger number of labels you might be able to vote on. Labels
+can be used to distinguish different aspects of a review (e.g. whether or not
+the licensing of included libraries is okay), outcome of CI systems (e.g.
+whether or not a format checker passed, a build completed successfully, etc.) or
+as a flag that is read by bots to do something with a change. An example of a
+more complex label setup can be seen in this screenshot from the Android Gerrit
+instance.
+
+image::images/user-review-ui-change-complex-reply-dialogue.png[Reply dialogue for a change on the Android project.]
+
+In the simplest case shown above, voting -1 on the Code-Review label equals
+requesting changes on a GitHub pull request, 0 equals just having comments and
++1 means that you think this change looks good. Usually, Gerrit changes require
+a +2 vote on the Code-Review label to be submitted (merged in GitHub terms, see
+Section 6 below). Being able to vote +2 on Code-Review is often restricted to
+maintainers of a given project, so they can have a final say on a change. These
+practices can however vary between projects, as labels and voting permissions
+are configurable.
+
+[[iterate]]
+== 5. Iterating on the Change
+
+After your reviewers got back to you as a change owner, you realize that you
+need to make a few updates to the code in your change. As mentioned in Section 2
+(Making a Change), you’ll have to amend the commit that this review was based
+on. To do that, you might have to checkout the respective commit first if it is
+not at the tip of your local branch, for example if you stacked multiple changes
+on top of each other. Another common use case is to not have a local branch but
+to work in the so-called https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit["detached HEAD",role=external,window=_blank] mode. In that case you can use the
+“Download” button on the files tab to copy a command that fetches and checks out
+the commit underlying your change. Make sure to select the latest patchset,
+though!
+
+image::images/user-review-ui-change-page-download.png[Using the “Download” button to copy a command that checks out a given patchset for a change.]
+
+After checking out the commit, you then make the changes as usual. When you
+think you are done, you can commit with the `--amend` flag to change the commit
+you currently have checked out.
+
+When you `git commit --amend` to iterate on your change, you might be worried that
+you are changing your previous commit and may thus lose that state of your work.
+However, here the Change-Id appended to your commit message comes into play.
+While the SHA1 hash of your change (the commit ID used by Git) might change, the
+Change-Id stays the same (in fact it is the SHA1 hash of the very first version
+of that commit). When this amended commit is uploaded to the Gerrit server,
+Gerrit knows that this commit is really an iteration of that previous commit
+(and the associated review) and will preserve both, the old and the new state.
+All previous states of your commit will be visible in the Gerrit UI as so-called
+patchsets (and link:intro-user.html#change-ref[from the Git repo]).
+
+image::images/user-review-ui-change-page-patchset-dropdown.png[Screenshot of the patchset dropdown above the file list, showing all iterations a commit went through.]
+
+After iterating as much as needed, your reviewers will finally be satisfied.
+With GitHub, you would have a string of additional commits in the branch you
+used for opening the pull request. In Gerrit, you still only have that one
+commit in your local branch. All the iterations are available as patchsets in
+the Web UI as well as from the special branch mentioned above.
+
+[[submit]]
+== 6. Submitting a Change
+
+Finally, it is time to submit your change. As mentioned above, the precondition
+for this in Gerrit is usually at least a +2 vote on the Code-Review label. With
+GitHub, an authorized person must have given an “Approve” vote. Once this
+precondition has been met, anyone with submit permission can submit the change
+in Gerrit. To do that, you click the “Submit” button in the Gerrit Web UI just
+as you would click the “Merge Pull Request” button in GitHub. Both, Gerrit and
+GitHub, allow different merge strategies, that can be enabled by project
+administrators. In Gerrit, a merge strategy is configured for each project and
+cannot be changed at submit time while this may be possible with GitHub,
+depending on project configuration.
+
+A merge can fail due to conflicts with competing edits on the target branch.
+With GitHub, you may be able to resolve some simple conflicts directly from the
+Web UI. In Gerrit, you can attempt to rebase a change from the Web UI. If there
+are no conflicts, a new patchset will automatically appear. Otherwise, similar
+to GitHub, you need to resolve conflicts on the command line with your local
+clone of the repository. While you resolve conflicts that arise from a
+`git merge` for GitHub, you will need to link:intro-user.html#rebase[use `git rebase` with your change] on
+Gerrit.
+
+After resolving locally, with GitHub, you end up with another commit on your
+pull request branch and push it to the server, which should then allow you to
+finish merging the change. With Gerrit, resolving the conflict through rebasing
+your commit/change results in another amended version of that same commit and
+you upload it to Gerrit, resulting in a new patchset just like your previous
+iterations addressing reviewer comments. This new patchset will usually require
+another round of reviewer votes, as Gerrit will not copy votes from a previous
+patchset by default.
+
+
+GERRIT
+------
+
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/intro-gerrit-walkthrough.txt b/Documentation/intro-gerrit-walkthrough.txt
index b4f799c2..92732d0 100644
--- a/Documentation/intro-gerrit-walkthrough.txt
+++ b/Documentation/intro-gerrit-walkthrough.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Working with Gerrit: An example
 
 To understand how Gerrit works, let's follow a change through its entire
@@ -130,7 +131,7 @@
 while the *Verified* check is done by an automated build server, through a
 mechanism such as the
 link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[Gerrit Trigger
-Jenkins Plugin].
+Jenkins Plugin,role=external,window=_blank].
 
 IMPORTANT: The Code-Review and Verified checks require different permissions
 in Gerrit. This requirement allows teams to separate these tasks. For example,
@@ -186,6 +187,7 @@
 
 * Check out the commit
 * Amend the commit
+* Rebase the commit if needed
 * Push the commit to Gerrit
 
 ----
@@ -195,6 +197,20 @@
 [master 30a6f44] Change to a proper, yeast based pizza dough.
  Date: Fri Jun 8 16:28:23 2018 +0200
  1 file changed, 10 insertions(+), 5 deletions(-)
+----
+
+At this point Max wants to make sure that his change is on top of the branch.
+
+----
+$ git fetch
+$
+----
+
+Max got no output from the fetch command, which is good news.
+This means that the master branch has not progressed and there is no need for link:intro-user.html#rebase[*rebase*].
+Max is now ready to push his change:
+
+----
 $ git push origin HEAD:refs/for/master
 Counting objects: 3, done.
 Delta compression using up to 8 threads.
@@ -237,7 +253,7 @@
 can add custom checks or even remove the Verified check entirely.
 
 Verification is typically an automated process using the
-link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[Gerrit Trigger Jenkins Plugin]
+link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[Gerrit Trigger Jenkins Plugin,role=external,window=_blank]
 or a similar mechanism. However, there are still times when a change requires
 manual verification, or a reviewer needs to check how or if a change works.
 To accommodate these and other similar circumstances, Gerrit exposes each change
diff --git a/Documentation/intro-project-owner.txt b/Documentation/intro-project-owner.txt
index f7aed5e..7f932da 100644
--- a/Documentation/intro-project-owner.txt
+++ b/Documentation/intro-project-owner.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Project Owner Guide
 
 This is a Gerrit guide that is dedicated to project owners. It
@@ -181,7 +182,7 @@
 to be prefixed with `ldap/`.
 
 If the link:https://gerrit-review.googlesource.com/admin/repos/plugins/singleusergroup[
-singleusergroup] plugin is installed you can also directly assign
+singleusergroup,role=external,window=_blank] plugin is installed you can also directly assign
 access rights to users, by prefixing the username with `user/` or the
 user's account ID by `userid/`.
 
@@ -374,10 +375,10 @@
 systems. The most commonly used are:
 
 - link:https://wiki.jenkins-ci.org/display/JENKINS/Gerrit+Trigger[
-  Gerrit Trigger] plugin for link:http://jenkins-ci.org/[Jenkins]
+  Gerrit Trigger,role=external,window=_blank] plugin for link:http://jenkins-ci.org/[Jenkins,role=external,window=_blank]
 
 - link:http://www.mediawiki.org/wiki/Continuous_integration/Zuul[
-  Zuul] for link:http://jenkins-ci.org/[Jenkins]
+  Zuul,role=external,window=_blank] for link:http://jenkins-ci.org/[Jenkins,role=external,window=_blank]
 
 For the integration with the continuous integration system you must
 have a service user that is able to access Gerrit. To create a service
@@ -387,7 +388,7 @@
 a Gerrit administrator to create the service user.
 
 If the link:https://gerrit-review.googlesource.com/admin/repos/plugins/serviceuser[
-serviceuser] plugin is installed you can also create new service users
+serviceuser,role=external,window=_blank] plugin is installed you can also create new service users
 in the Gerrit Web UI under `People` > `Create Service User`. For this
 the `Create Service User` global capability must be assigned.
 
@@ -407,7 +408,7 @@
 
 Gerrit provides an
 link:https://gerrit-review.googlesource.com/Documentation/config-validation.html#new-commit-validation[
-extension point to do validation of new commits]. A Gerrit plugin
+extension point to do validation of new commits,role=external,window=_blank]. A Gerrit plugin
 implementing this extension point can perform validation checks when
 new commits are pushed to Gerrit. The plugin can either provide a
 message to the client or reject the commit and cause the push to fail.
@@ -415,13 +416,13 @@
 There are some plugins available that provide commit validation:
 
 - link:https://gerrit-review.googlesource.com/admin/repos/plugins/uploadvalidator[
-  uploadvalidator]:
+  uploadvalidator,role=external,window=_blank]:
 +
 The `uploadvalidator` plugin allows project owners to configure blocked
 file extensions, required footers and a maximum allowed path length.
 
 - link:https://gerrit-review.googlesource.com/admin/repos/plugins/commit-message-length-validator[
-  commit-message-length-validator]
+  commit-message-length-validator,role=external,window=_blank]
 +
 The `commit-message-length-validator` core plugin validates that commit
 messages conform to line length limits.
@@ -501,9 +502,9 @@
 - Issue Tracker System Plugins
 +
 There are Gerrit plugins for a tight integration with
-link:https://gerrit-review.googlesource.com//admin/repos/plugins/its-jira[Jira],
-link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-bugzilla[Bugzilla] and
-link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-rtc[IBM Rational Team Concert].
+link:https://gerrit-review.googlesource.com//admin/repos/plugins/its-jira[Jira,role=external,window=_blank],
+link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-bugzilla[Bugzilla,role=external,window=_blank] and
+link:https://gerrit-review.googlesource.com/admin/repos/plugins/its-rtc[IBM Rational Team Concert,role=external,window=_blank].
 If installed, these plugins can e.g. be used to automatically add links
 to Gerrit changes to the issues in the issue tracker system or to
 automatically close an issue if the corresponding change is merged.
@@ -551,15 +552,15 @@
 Gerrit will then notify this person by email about the review request.
 
 With the link:https://gerrit-review.googlesource.com/admin/repos/plugins/reviewers[
-reviewers] plugin it is possible to configure default reviewers who
+reviewers,role=external,window=_blank] plugin it is possible to configure default reviewers who
 will be automatically added to each change. The default reviewers can
 be configured in the Gerrit Web UI under `Projects` > `List` >
 <your project> > `General` in the `reviewers Plugin` section.
 
 The link:https://gerrit-review.googlesource.com/admin/repos/plugins/reviewers-by-blame[
-reviewers-by-blame] plugin can automatically add reviewers to changes
+reviewers-by-blame,role=external,window=_blank] plugin can automatically add reviewers to changes
 based on the link:https://www.kernel.org/pub/software/scm/git/docs/git-blame.html[
-git blame] computation on the changed files. This means that the plugin
+git blame,role=external,window=_blank] computation on the changed files. This means that the plugin
 will add those users as reviewer that authored most of the lines
 touched by the change, since these users should be familiar with the
 code and can most likely review the change. How many reviewers the
@@ -578,7 +579,7 @@
 plugins:
 
 - link:https://gerrit-review.googlesource.com/admin/repos/plugins/download-commands[
-  download-commands] plugin:
+  download-commands,role=external,window=_blank] plugin:
 +
 The `download-commands` plugin provides the default download commands
 (`Checkout`, `Cherry Pick`, `Format Patch` and `Pull`).
@@ -587,7 +588,7 @@
 the change screen.
 
 - link:https://gerrit-review.googlesource.com/admin/repos/plugins/project-download-commands[
-  project-download-commands] plugin:
+  project-download-commands,role=external,window=_blank] plugin:
 +
 The `project-download-commands` plugin enables project owners to
 configure project-specific download commands. For example, a
@@ -671,14 +672,14 @@
 contains this history. If your existing codebase is in another VCS you
 must migrate it to Git first. For Subversion you can use the
 link:http://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion[
-git svn] command as described in the
+git svn,role=external,window=_blank] command as described in the
 link:http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git#Subversion[
-Subversion migration guide]. An importer for Perforce is available in
+Subversion migration guide,role=external,window=_blank]. An importer for Perforce is available in
 the `contrib` section of the Git source code; how to use
-link:http://git-scm.com/docs/git-p4[git p4] to do the import from
+link:http://git-scm.com/docs/git-p4[git p4,role=external,window=_blank] to do the import from
 Perforce is described in the
 link:http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git#Perforce[
-Perforce migration guide].
+Perforce migration guide,role=external,window=_blank].
 
 To import an existing history into a Gerrit project you bypass code
 review and push it directly to `refs/heads/<branch>`. For this you must
@@ -692,7 +693,7 @@
 link:access-control.html#category_forge_committer[Forge Committer]
 access right globally. In this case you must use the
 link:https://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html[
-git filter-branch] command to rewrite the committer information for all
+git filter-branch,role=external,window=_blank] command to rewrite the committer information for all
 commits (the author information that records who was writing the code
 stays intact; signed tags will lose their signature):
 
@@ -734,7 +735,7 @@
 Gerrit core does not support the deletion of projects.
 
 If the link:https://gerrit-review.googlesource.com/admin/repos/plugins/delete-project[
-delete-project] plugin is installed, projects can be deleted from the
+delete-project,role=external,window=_blank] plugin is installed, projects can be deleted from the
 Gerrit Web UI under `Projects` > `List` > <project> > `General` by
 clicking on the `Delete` command under `Project Commands`. The `Delete`
 command is only available if you have the `Delete Projects` global
diff --git a/Documentation/intro-quick.txt b/Documentation/intro-quick.txt
index 11d5052..b8670ed 100644
--- a/Documentation/intro-quick.txt
+++ b/Documentation/intro-quick.txt
@@ -1,7 +1,8 @@
+:linkattrs:
 = Gerrit Code Review Product Overview
 
 Gerrit Code Review is a web-based code review tool built on
-https://git-scm.com/[Git version control].
+https://git-scm.com/[Git version control,role=external,window=_blank].
 
 == What is Gerrit Code Review?
 
@@ -45,7 +46,7 @@
 
 . link:intro-user.html[User Guide]
 . link:intro-project-owner.html[Project Owner Guide]
-. link:https://source.android.com/source/life-of-a-patch[Default Android Workflow] (external)
+. link:https://source.android.com/source/life-of-a-patch[Default Android Workflow,role=external,window=_blank] (external)
 
 GERRIT
 ------
diff --git a/Documentation/intro-rockstar.txt b/Documentation/intro-rockstar.txt
index 0b67950..4a7167b 100644
--- a/Documentation/intro-rockstar.txt
+++ b/Documentation/intro-rockstar.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Use Gerrit to Be a Rockstar Programmer
 
 == Overview
@@ -42,7 +43,7 @@
 
 * git cherry-pick
 
-* link:https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html[git bisect]
+* link:https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html[git bisect,role=external,window=_blank]
 
 
 [[amending]]
@@ -59,8 +60,8 @@
 
 At least two well-known open source projects insist on these practices:
 
-* link:http://git-scm.com/[Git]
-* link:http://www.kernel.org/category/about.html[Linux Kernel]
+* link:http://git-scm.com/[Git,role=external,window=_blank]
+* link:http://www.kernel.org/category/about.html[Linux Kernel,role=external,window=_blank]
 
 However, contributors to these projects don’t refine and polish their changes
 in private until they’re perfect. Instead, polishing code is part of a review
diff --git a/Documentation/intro-user.txt b/Documentation/intro-user.txt
index a54774b..eb2025c 100644
--- a/Documentation/intro-user.txt
+++ b/Documentation/intro-user.txt
@@ -1,10 +1,11 @@
+:linkattrs:
 = User Guide
 
 This is a Gerrit guide that is dedicated to Gerrit end-users. It
 explains the standard Gerrit workflows and how a user can adapt Gerrit
 to personal preferences.
 
-It is expected that readers know about link:http://git-scm.com/[Git]
+It is expected that readers know about link:http://git-scm.com/[Git,role=external,window=_blank]
 and that they are familiar with basic git commands and workflows.
 
 [[gerrit]]
@@ -21,20 +22,20 @@
 
 Gerrit uses the git protocol. This means in order to work with Gerrit
 you do *not* need to install any Gerrit client, but having a regular
-git client, such as the link:http://git-scm.com/[git command line] or
-link:http://eclipse.org/egit/[EGit] in Eclipse, is sufficient.
+git client, such as the link:http://git-scm.com/[git command line,role=external,window=_blank] or
+link:http://eclipse.org/egit/[EGit,role=external,window=_blank] in Eclipse, is sufficient.
 
 Still there are some client-side tools for Gerrit, which can be used
 optionally:
 
-* link:http://eclipse.org/mylyn/[Mylyn Gerrit Connector]: Gerrit
+* link:http://eclipse.org/mylyn/[Mylyn Gerrit Connector,role=external,window=_blank]: Gerrit
   integration with Mylyn
 * link:https://github.com/uwolfer/gerrit-intellij-plugin[Gerrit
-  IntelliJ Plugin]: Gerrit integration with the
-  link:http://www.jetbrains.com/idea/[IntelliJ Platform]
+  IntelliJ Plugin,role=external,window=_blank]: Gerrit integration with the
+  link:http://www.jetbrains.com/idea/[IntelliJ Platform,role=external,window=_blank]
 * link:https://play.google.com/store/apps/details?id=com.jbirdvegas.mgerrit[
-  mGerrit]: Android client for Gerrit
-* link:https://github.com/stackforge/gertty[Gertty]: Console-based
+  mGerrit,role=external,window=_blank]: Android client for Gerrit
+* link:https://github.com/stackforge/gertty[Gertty,role=external,window=_blank]: Console-based
   interface for Gerrit
 
 [[clone]]
@@ -120,7 +121,7 @@
 A change ref has the format `refs/changes/X/Y/Z` where `X` is the last
 two digits of the change number, `Y` is the entire change number, and `Z`
 is the patch set. For example, if the change number is
-link:https://gerrit-review.googlesource.com/c/gerrit/+/263270[263270],
+link:https://gerrit-review.googlesource.com/c/gerrit/+/263270[263270,role=external,window=_blank],
 the ref would be `refs/changes/70/263270/2` for the second patch set.
 
 [[fetch-change]]
@@ -212,7 +213,7 @@
 Instead of manually installing the `commit-msg` hook for each git
 repository, you can copy it into the
 link:http://git-scm.com/docs/git-init#_template_directory[git template
-directory]. Then it is automatically copied to every newly cloned
+directory,role=external,window=_blank]. Then it is automatically copied to every newly cloned
 repository.
 
 [[review-change]]
@@ -472,6 +473,15 @@
 Abandoned changes can be link:user-review-ui.html#restore[restored] if
 later they are needed again.
 
+[[cherrypickof]]
+== Cherry-Pick changes of a Change
+
+When a change is created/updated using the 'cherry-pick' functionalty,
+the original change and patchset details are recorded in the Change's
+cherrypick field. This field cannot be set or updated by the user in
+any way. It is set automatically after the cherry-pick operation completes
+successfully.
+
 [[topics]]
 == Using Topics
 
@@ -565,7 +575,19 @@
 ----
   $ git push origin HEAD:refs/for/master%ready
 ----
-Alternatively, click *Start Review* from the Change screen.
+There are two options for marking the change ready for review from the Change
+screen:
+
+1. Click *Start Review* (the primary action *Reply* is renamed when in WIP
+state).
++
+This will open the reply-modal and allow you to add reviewers and/or CC
+before you start review.
+
+2. Click button *Mark As Active*.
++
+This will only change the state from WIP to ready, without opening the
+reply-modal.
 
 Change owners, project owners, site administrators and members of a group that
 was granted link:access-control.html#category_toggle_work_in_progress_state[
diff --git a/Documentation/js-api.txt b/Documentation/js-api.txt
index 030541d..893ab36 100644
--- a/Documentation/js-api.txt
+++ b/Documentation/js-api.txt
@@ -150,6 +150,13 @@
 parameter the URL of the plugin is returned. If passed a string
 the argument is appended to the plugin URL.
 
+A plugin's URL is where this plugin is loaded, it doesn't
+necessary to be the same as the Gerrit host. Use `window.location`
+if you need to access the Gerrit host info.
+
+For preloaded plugins, the plugin url is based on a global
+configuration of where to load all plugins, default to current host.
+
 [source,javascript]
 ----
 self.url();                    // "https://gerrit-review.googlesource.com/plugins/demo/"
diff --git a/Documentation/js_licenses.txt b/Documentation/js_licenses.txt
index c2bdfbb3..4bc386a 100644
--- a/Documentation/js_licenses.txt
+++ b/Documentation/js_licenses.txt
@@ -3,7 +3,6 @@
 Apache2.0
 
 * fonts:robotofonts
-* polymer_externs:polymer_closure
 
 [[Apache2_0_license]]
 ----
@@ -213,10 +212,45 @@
 ----
 
 
+[[highlightjs]]
+highlightjs
+
+* js:highlightjs
+
+[[highlightjs_license]]
+----
+Copyright (c) 2006, Ivan Sagalaev
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of highlight.js nor the names of its contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
 [[ba-linkify]]
 ba-linkify
 
-* js:ba-linkify
+* ba-linkify
 
 [[ba-linkify_license]]
 ----
@@ -249,7 +283,7 @@
 [[es6-promise]]
 es6-promise
 
-* js:es6-promise
+* es6-promise
 
 [[es6-promise_license]]
 ----
@@ -276,80 +310,46 @@
 ----
 
 
-[[fetch]]
-fetch
+[[isarray]]
+isarray
 
-* js:fetch
+* isarray
 
-[[fetch_license]]
+[[isarray_license]]
 ----
-Copyright (c) 2014-2016 GitHub, Inc.
+(MIT)
 
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
+Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>;
 
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
 
-----
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
 
-
-[[highlightjs]]
-highlightjs
-
-* js:highlightjs
-* js:highlightjs_files
-
-[[highlightjs_license]]
-----
-Copyright (c) 2006, Ivan Sagalaev
-All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * Neither the name of highlight.js nor the names of its contributors
-      may be used to endorse or promote products derived from this software
-      without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----
 
 
 [[moment]]
 moment
 
-* js:moment
+* moment
 
 [[moment_license]]
 ----
-Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors
+Copyright (c) JS Foundation and other contributors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -375,77 +375,88 @@
 ----
 
 
-[[page_js]]
-page.js
+[[page]]
+page
 
-* js:page
+* page
 
-[[page_js_license]]
+[[page_license]]
 ----
 (The MIT License)
 
 Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the 'Software'), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
 
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 ----
 
 
-[[polymer]]
-polymer
+[[path-to-regexp]]
+path-to-regexp
 
-* js:font-roboto-local
-* js:iron-a11y-announcer
-* js:iron-a11y-keys-behavior
-* js:iron-autogrow-textarea
-* js:iron-behaviors
-* js:iron-checked-element-behavior
-* js:iron-dropdown
-* js:iron-fit-behavior
-* js:iron-flex-layout
-* js:iron-form-element-behavior
-* js:iron-icon
-* js:iron-iconset-svg
-* js:iron-input
-* js:iron-menu-behavior
-* js:iron-meta
-* js:iron-overlay-behavior
-* js:iron-resizable-behavior
-* js:iron-selector
-* js:iron-validatable-behavior
-* js:neon-animation
-* js:paper-behaviors
-* js:paper-button
-* js:paper-icon-button
-* js:paper-input
-* js:paper-item
-* js:paper-listbox
-* js:paper-ripple
-* js:paper-styles
-* js:paper-tabs
-* js:paper-toggle-button
-* js:polymer
-* js:polymer-resin
-* js:webcomponentsjs
+* path-to-regexp
 
-[[polymer_license]]
+[[path-to-regexp_license]]
 ----
-Copyright (c) 2014 The Polymer Authors. All rights reserved.
+The MIT License (MIT)
+
+Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+----
+
+
+[[Polymer-2018]]
+Polymer-2018
+
+* @webcomponents/webcomponentsjs
+* polymer-bridges
+* polymer-resin
+
+[[Polymer-2018_license]]
+----
+Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -476,33 +487,878 @@
 ----
 
 
-[[shadycss]]
-shadycss
+[[shadow-selection-polyfill]]
+shadow-selection-polyfill
 
-* js:shadycss
+* shadow-selection-polyfill
 
-[[shadycss_license]]
+[[shadow-selection-polyfill_license]]
 ----
-# License
 
-Everything in this repo is BSD style license unless otherwise specified.
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
 
-Copyright (c) 2015 The Polymer Authors. All rights reserved.
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+   1. Definitions.
 
-* Redistributions of source code must retain the above copyright
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[whatwg-fetch]]
+whatwg-fetch
+
+* whatwg-fetch
+
+[[whatwg-fetch_license]]
+----
+Copyright (c) 2014-2016 GitHub, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+----
+
+
+[[Polymer-2015]]
+Polymer-2015
+
+* @polymer/font-roboto
+* @polymer/font-roboto-local - only the following file(s):
+** README.md
+** bower.json
+** demo/index.d.ts
+** demo/index.html
+** fonts/roboto/DESCRIPTION.en_us.html
+** fonts/robotomono/DESCRIPTION.en_us.html
+** generate-style.js
+** manifest.json
+** package.json
+** roboto.js
+** update-fonts.sh
+* @polymer/iron-a11y-announcer
+* @polymer/iron-a11y-keys-behavior
+* @polymer/iron-autogrow-textarea
+* @polymer/iron-behaviors
+* @polymer/iron-checked-element-behavior
+* @polymer/iron-dropdown
+* @polymer/iron-fit-behavior
+* @polymer/iron-flex-layout
+* @polymer/iron-form-element-behavior
+* @polymer/iron-icon
+* @polymer/iron-iconset-svg
+* @polymer/iron-input
+* @polymer/iron-menu-behavior
+* @polymer/iron-meta
+* @polymer/iron-overlay-behavior
+* @polymer/iron-resizable-behavior
+* @polymer/iron-selector
+* @polymer/iron-validatable-behavior
+* @polymer/neon-animation
+* @polymer/paper-behaviors
+* @polymer/paper-button
+* @polymer/paper-dialog
+* @polymer/paper-dialog-behavior
+* @polymer/paper-dialog-scrollable
+* @polymer/paper-icon-button
+* @polymer/paper-input
+* @polymer/paper-item
+* @polymer/paper-listbox
+* @polymer/paper-tabs
+* @polymer/paper-toggle-button
+
+[[Polymer-2015_license]]
+----
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above
+   * Redistributions in binary form must reproduce the above
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
-* Neither the name of Google Inc. nor the names of its
+   * Neither the name of Google Inc. nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+----
+
+
+[[font-roboto-local-fonts-roboto]]
+font-roboto-local-fonts-roboto
+
+* @polymer/font-roboto-local - only the following file(s):
+** fonts/roboto/COPYRIGHT.txt
+** fonts/roboto/LICENSE.txt
+** fonts/roboto/METADATA.json
+** fonts/roboto/Roboto-Black.ttf
+** fonts/roboto/Roboto-BlackItalic.ttf
+** fonts/roboto/Roboto-Bold.ttf
+** fonts/roboto/Roboto-BoldItalic.ttf
+** fonts/roboto/Roboto-Italic.ttf
+** fonts/roboto/Roboto-Light.ttf
+** fonts/roboto/Roboto-LightItalic.ttf
+** fonts/roboto/Roboto-Medium.ttf
+** fonts/roboto/Roboto-MediumItalic.ttf
+** fonts/roboto/Roboto-Regular.ttf
+** fonts/roboto/Roboto-Thin.ttf
+** fonts/roboto/Roboto-ThinItalic.ttf
+
+[[font-roboto-local-fonts-roboto_license]]
+----
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[font-roboto-local-fonts-robotomono]]
+font-roboto-local-fonts-robotomono
+
+* @polymer/font-roboto-local - only the following file(s):
+** fonts/robotomono/LICENSE.txt
+** fonts/robotomono/METADATA.json
+** fonts/robotomono/RobotoMono-Bold.ttf
+** fonts/robotomono/RobotoMono-BoldItalic.ttf
+** fonts/robotomono/RobotoMono-Italic.ttf
+** fonts/robotomono/RobotoMono-Light.ttf
+** fonts/robotomono/RobotoMono-LightItalic.ttf
+** fonts/robotomono/RobotoMono-Medium.ttf
+** fonts/robotomono/RobotoMono-MediumItalic.ttf
+** fonts/robotomono/RobotoMono-Regular.ttf
+** fonts/robotomono/RobotoMono-Thin.ttf
+** fonts/robotomono/RobotoMono-ThinItalic.ttf
+
+[[font-roboto-local-fonts-robotomono_license]]
+----
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[Polymer-2014]]
+Polymer-2014
+
+* @polymer/paper-ripple
+* @polymer/paper-styles
+
+[[Polymer-2014_license]]
+----
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
+[[Polymer-2017]]
+Polymer-2017
+
+* @polymer/polymer
+* @webcomponents/shadycss
+
+[[Polymer-2017_license]]
+----
+Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----
 
diff --git a/Documentation/licenses.txt b/Documentation/licenses.txt
index 9f7bd99..4a2630a 100644
--- a/Documentation/licenses.txt
+++ b/Documentation/licenses.txt
@@ -65,7 +65,6 @@
 * httpcomponents:httpcore
 * httpcomponents:httpcore-nio
 * jackson:jackson-core
-* jetty:continuation
 * jetty:http
 * jetty:io
 * jetty:jmx
@@ -74,8 +73,6 @@
 * jetty:servlet
 * jetty:util
 * jetty:util-ajax
-* log:json-smart
-* log:jsonevent-layout
 * log:log4j
 * lucene:lucene-analyzers-common
 * lucene:lucene-core-and-backward-codecs-merged
@@ -88,7 +85,6 @@
 * openid:consumer
 * openid:nekohtml
 * openid:xerces
-* polymer_externs:polymer_closure
 * blame-cache
 * caffeine
 * caffeine-guava
@@ -1069,39 +1065,6 @@
 ----
 
 
-[[ba-linkify]]
-ba-linkify
-
-* js:ba-linkify
-
-[[ba-linkify_license]]
-----
-Copyright (c) 2009 "Cowboy" Ben Alman
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
 [[bouncycastle]]
 bouncycastle
 
@@ -1152,67 +1115,6 @@
 ----
 
 
-[[es6-promise]]
-es6-promise
-
-* js:es6-promise
-
-[[es6-promise_license]]
-----
-Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-----
-
-
-[[fetch]]
-fetch
-
-* js:fetch
-
-[[fetch_license]]
-----
-Copyright (c) 2014-2016 GitHub, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
 [[flexmark]]
 flexmark
 
@@ -1999,7 +1901,6 @@
 highlightjs
 
 * js:highlightjs
-* js:highlightjs_files
 
 [[highlightjs_license]]
 ----
@@ -2027,6 +1928,7 @@
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 ----
 
 
@@ -2545,39 +2447,6 @@
 ----
 
 
-[[moment]]
-moment
-
-* js:moment
-
-[[moment_license]]
-----
-Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
 [[ow2]]
 ow2
 
@@ -2622,107 +2491,6 @@
 ----
 
 
-[[page_js]]
-page.js
-
-* js:page
-
-[[page_js_license]]
-----
-(The MIT License)
-
-Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the 'Software'), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
-[[polymer]]
-polymer
-
-* js:font-roboto-local
-* js:iron-a11y-announcer
-* js:iron-a11y-keys-behavior
-* js:iron-autogrow-textarea
-* js:iron-behaviors
-* js:iron-checked-element-behavior
-* js:iron-dropdown
-* js:iron-fit-behavior
-* js:iron-flex-layout
-* js:iron-form-element-behavior
-* js:iron-icon
-* js:iron-iconset-svg
-* js:iron-input
-* js:iron-menu-behavior
-* js:iron-meta
-* js:iron-overlay-behavior
-* js:iron-resizable-behavior
-* js:iron-selector
-* js:iron-validatable-behavior
-* js:neon-animation
-* js:paper-behaviors
-* js:paper-button
-* js:paper-icon-button
-* js:paper-input
-* js:paper-item
-* js:paper-listbox
-* js:paper-ripple
-* js:paper-styles
-* js:paper-tabs
-* js:paper-toggle-button
-* js:polymer
-* js:polymer-resin
-* js:webcomponentsjs
-
-[[polymer_license]]
-----
-Copyright (c) 2014 The Polymer Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-   * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-   * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-----
-
-
 [[prologcafe]]
 prologcafe
 
@@ -3374,37 +3142,6 @@
 ----
 
 
-[[shadycss]]
-shadycss
-
-* js:shadycss
-
-[[shadycss_license]]
-----
-# License
-
-Everything in this repo is BSD style license unless otherwise specified.
-
-Copyright (c) 2015 The Polymer Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-* Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-----
-
-
 [[slf4j]]
 slf4j
 
@@ -3453,6 +3190,1122 @@
 ----
 
 
+[[ba-linkify]]
+ba-linkify
+
+* ba-linkify
+
+[[ba-linkify_license]]
+----
+Copyright (c) 2009 "Cowboy" Ben Alman
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+----
+
+
+[[es6-promise]]
+es6-promise
+
+* es6-promise
+
+[[es6-promise_license]]
+----
+Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+----
+
+
+[[isarray]]
+isarray
+
+* isarray
+
+[[isarray_license]]
+----
+(MIT)
+
+Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>;
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+----
+
+
+[[moment]]
+moment
+
+* moment
+
+[[moment_license]]
+----
+Copyright (c) JS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+----
+
+
+[[page]]
+page
+
+* page
+
+[[page_license]]
+----
+(The MIT License)
+
+Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+----
+
+
+[[path-to-regexp]]
+path-to-regexp
+
+* path-to-regexp
+
+[[path-to-regexp_license]]
+----
+The MIT License (MIT)
+
+Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+----
+
+
+[[Polymer-2018]]
+Polymer-2018
+
+* @webcomponents/webcomponentsjs
+* polymer-bridges
+* polymer-resin
+
+[[Polymer-2018_license]]
+----
+Copyright (c) 2018 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
+[[shadow-selection-polyfill]]
+shadow-selection-polyfill
+
+* shadow-selection-polyfill
+
+[[shadow-selection-polyfill_license]]
+----
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[whatwg-fetch]]
+whatwg-fetch
+
+* whatwg-fetch
+
+[[whatwg-fetch_license]]
+----
+Copyright (c) 2014-2016 GitHub, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+----
+
+
+[[Polymer-2015]]
+Polymer-2015
+
+* @polymer/font-roboto
+* @polymer/font-roboto-local - only the following file(s):
+** README.md
+** bower.json
+** demo/index.d.ts
+** demo/index.html
+** fonts/roboto/DESCRIPTION.en_us.html
+** fonts/robotomono/DESCRIPTION.en_us.html
+** generate-style.js
+** manifest.json
+** package.json
+** roboto.js
+** update-fonts.sh
+* @polymer/iron-a11y-announcer
+* @polymer/iron-a11y-keys-behavior
+* @polymer/iron-autogrow-textarea
+* @polymer/iron-behaviors
+* @polymer/iron-checked-element-behavior
+* @polymer/iron-dropdown
+* @polymer/iron-fit-behavior
+* @polymer/iron-flex-layout
+* @polymer/iron-form-element-behavior
+* @polymer/iron-icon
+* @polymer/iron-iconset-svg
+* @polymer/iron-input
+* @polymer/iron-menu-behavior
+* @polymer/iron-meta
+* @polymer/iron-overlay-behavior
+* @polymer/iron-resizable-behavior
+* @polymer/iron-selector
+* @polymer/iron-validatable-behavior
+* @polymer/neon-animation
+* @polymer/paper-behaviors
+* @polymer/paper-button
+* @polymer/paper-dialog
+* @polymer/paper-dialog-behavior
+* @polymer/paper-dialog-scrollable
+* @polymer/paper-icon-button
+* @polymer/paper-input
+* @polymer/paper-item
+* @polymer/paper-listbox
+* @polymer/paper-tabs
+* @polymer/paper-toggle-button
+
+[[Polymer-2015_license]]
+----
+Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
+[[font-roboto-local-fonts-roboto]]
+font-roboto-local-fonts-roboto
+
+* @polymer/font-roboto-local - only the following file(s):
+** fonts/roboto/COPYRIGHT.txt
+** fonts/roboto/LICENSE.txt
+** fonts/roboto/METADATA.json
+** fonts/roboto/Roboto-Black.ttf
+** fonts/roboto/Roboto-BlackItalic.ttf
+** fonts/roboto/Roboto-Bold.ttf
+** fonts/roboto/Roboto-BoldItalic.ttf
+** fonts/roboto/Roboto-Italic.ttf
+** fonts/roboto/Roboto-Light.ttf
+** fonts/roboto/Roboto-LightItalic.ttf
+** fonts/roboto/Roboto-Medium.ttf
+** fonts/roboto/Roboto-MediumItalic.ttf
+** fonts/roboto/Roboto-Regular.ttf
+** fonts/roboto/Roboto-Thin.ttf
+** fonts/roboto/Roboto-ThinItalic.ttf
+
+[[font-roboto-local-fonts-roboto_license]]
+----
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[font-roboto-local-fonts-robotomono]]
+font-roboto-local-fonts-robotomono
+
+* @polymer/font-roboto-local - only the following file(s):
+** fonts/robotomono/LICENSE.txt
+** fonts/robotomono/METADATA.json
+** fonts/robotomono/RobotoMono-Bold.ttf
+** fonts/robotomono/RobotoMono-BoldItalic.ttf
+** fonts/robotomono/RobotoMono-Italic.ttf
+** fonts/robotomono/RobotoMono-Light.ttf
+** fonts/robotomono/RobotoMono-LightItalic.ttf
+** fonts/robotomono/RobotoMono-Medium.ttf
+** fonts/robotomono/RobotoMono-MediumItalic.ttf
+** fonts/robotomono/RobotoMono-Regular.ttf
+** fonts/robotomono/RobotoMono-Thin.ttf
+** fonts/robotomono/RobotoMono-ThinItalic.ttf
+
+[[font-roboto-local-fonts-robotomono_license]]
+----
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+----
+
+
+[[Polymer-2014]]
+Polymer-2014
+
+* @polymer/paper-ripple
+* @polymer/paper-styles
+
+[[Polymer-2014_license]]
+----
+Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
+[[Polymer-2017]]
+Polymer-2017
+
+* @polymer/polymer
+* @webcomponents/shadycss
+
+[[Polymer-2017_license]]
+----
+Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
+
+This code may only be used under the BSD style license found at
+http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
+http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
+found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
+part of the polymer project is also subject to an additional IP rights grant
+found at http://polymer.github.io/PATENTS.txt
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----
+
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/linux-quickstart.txt b/Documentation/linux-quickstart.txt
index 643bde0..29bb409 100644
--- a/Documentation/linux-quickstart.txt
+++ b/Documentation/linux-quickstart.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Quickstart for Installing Gerrit on Linux
 
 This content explains how to install a basic instance of Gerrit on a Linux
@@ -29,7 +30,7 @@
 . Download the desired Gerrit archive.
 
 To view previous archives, see
-link:https://gerrit-releases.storage.googleapis.com/index.html[Gerrit Code Review: Releases]. The steps below install Gerrit 3.1.3:
+link:https://gerrit-releases.storage.googleapis.com/index.html[Gerrit Code Review: Releases,role=external,window=_blank]. The steps below install Gerrit 3.1.3:
 
 ....
 wget https://gerrit-releases.storage.googleapis.com/gerrit-3.1.3.war
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index e64d1de..5eadc74 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -194,10 +194,10 @@
 
 === NoteDb
 
-* `notedb/update_latency`: NoteDb update latency by table.
-* `notedb/stage_update_latency`: Latency for staging updates to NoteDb by table.
-* `notedb/read_latency`: NoteDb read latency by table.
-* `notedb/parse_latency`: NoteDb parse latency by table.
+* `notedb/update_latency`: NoteDb update latency for changes.
+* `notedb/stage_update_latency`: Latency for staging change updates to NoteDb.
+* `notedb/read_latency`: NoteDb read latency for changes.
+* `notedb/parse_latency`: NoteDb parse latency for changes.
 * `notedb/external_id_cache_load_count`: Total number of times the external ID
   cache loader was called.
 * `notedb/external_id_partial_read_latency`: Latency for generating a new external ID
@@ -205,11 +205,13 @@
 * `notedb/external_id_update_count`: Total number of external ID updates.
 * `notedb/read_all_external_ids_latency`: Latency for reading all
 external ID's from NoteDb.
+* `notedb/read_single_account_config_latency`: Latency for reading a single
+account config from NoteDb.
+* `notedb/read_single_external_id_latency`: Latency for reading a single
+external ID from NoteDb.
 
 === Permissions
 
-* `permissions/project_state/computation_latency`: Latency to compute current access
-sections on a project by traversing it's parents.
 * `permissions/permission_collection/filter_latency`: Latency to filter access sections
 by user and ref.
 * `permissions/ref_filter/full_filter_count`: Rate of full ref filter operations
diff --git a/Documentation/note-db.txt b/Documentation/note-db.txt
index 0bacca4..a13cbfb 100644
--- a/Documentation/note-db.txt
+++ b/Documentation/note-db.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - NoteDb Backend
 
 NoteDb is the storage backend for code review metadata. It is based on
@@ -191,5 +192,5 @@
 
 In case of rollback from NoteDB to ReviewDB, all the meta refs and the
 sequence ref need to be removed.
-The [remove-notedb-refs.sh](https://gerrit.googlesource.com/gerrit/+/refs/heads/master/contrib/remove-notedb-refs.sh)
+The [remove-notedb-refs.sh,role=external,window=_blank](https://gerrit.googlesource.com/gerrit/+/refs/heads/master/contrib/remove-notedb-refs.sh)
 script has been written to automate this process.
diff --git a/Documentation/pg-plugin-dev.txt b/Documentation/pg-plugin-dev.txt
index d901851..1ce1d61 100644
--- a/Documentation/pg-plugin-dev.txt
+++ b/Documentation/pg-plugin-dev.txt
@@ -1,8 +1,9 @@
+:linkattrs:
 = Gerrit Code Review - PolyGerrit Plugin Development
 
 CAUTION: Work in progress. Hard hat area. Please
 link:https://bugs.chromium.org/p/gerrit/issues/entry?template=PolyGerrit%20plugins[send
-feedback] if something's not right.
+feedback,role=external,window=_blank] if something's not right.
 
 For migrating existing GWT UI plugins, please check out the
 link:pg-plugin-migration.html#migration[migration guide].
@@ -11,7 +12,7 @@
 == Plugin loading and initialization
 
 link:js-api.html#_entry_point[Entry point] for the plugin and the loading method
-is based on link:http://w3c.github.io/webcomponents/spec/imports/[HTML Imports]
+is based on link:http://w3c.github.io/webcomponents/spec/imports/[HTML Imports,role=external,window=_blank]
 spec.
 
 * The plugin provides pluginname.html, and can be a standalone file or a static
@@ -103,7 +104,7 @@
 
 A plugin may provide Polymer's
 https://www.polymer-project.org/2.0/docs/devguide/style-shadow-dom#style-modules[style
-modules] to style individual endpoints using
+modules,role=external,window=_blank] to style individual endpoints using
 `plugin.registerStyleModule(endpointName, moduleName)`. A style must be defined
 as a standalone `<dom-module>` defined in the same .html file.
 
@@ -152,7 +153,7 @@
 
 Alternative for
 link:https://www.polymer-project.org/1.0/docs/devguide/data-binding[Polymer data
-binding] for plugins that don't use Polymer. Can be used to bind element
+binding,role=external,window=_blank] for plugins that don't use Polymer. Can be used to bind element
 attribute changes to callbacks.
 
 See `samples/bind-parameters.html` for examples on both Polymer data bindings
@@ -210,11 +211,6 @@
 
 Note: TODO
 
-=== changeView
-`plugin.changeView()`
-
-Note: TODO
-
 === delete
 `plugin.delete(url, opt_callback)`
 
diff --git a/Documentation/pg-plugin-migration.txt b/Documentation/pg-plugin-migration.txt
index 3ddceed..bca4b7a 100644
--- a/Documentation/pg-plugin-migration.txt
+++ b/Documentation/pg-plugin-migration.txt
@@ -1,8 +1,9 @@
+:linkattrs:
 = Gerrit Code Review - PolyGerrit Plugin Development
 
 CAUTION: Work in progress. Hard hat area. Please
 link:https://bugs.chromium.org/p/gerrit/issues/entry?template=PolyGerrit%20plugins[send
-feedback] if something's not right.
+feedback,role=external,window=_blank] if something's not right.
 
 [[migration]]
 == Incremental migration of existing GWT UI plugins
diff --git a/Documentation/pg-plugin-styling.txt b/Documentation/pg-plugin-styling.txt
index 2453bad..f600376 100644
--- a/Documentation/pg-plugin-styling.txt
+++ b/Documentation/pg-plugin-styling.txt
@@ -1,20 +1,21 @@
+:linkattrs:
 = Gerrit Code Review - PolyGerrit Plugin Styling
 
 == Plugin styles
 
 Plugins may provide
 link:https://www.polymer-project.org/2.0/docs/devguide/style-shadow-dom#style-modules[Polymer
-style modules] for UI CSS-based customization.
+style modules,role=external,window=_blank] for UI CSS-based customization.
 
 PolyGerrit UI implements number of styling endpoints, which apply CSS mixins
-link:https://tabatkins.github.io/specs/css-apply-rule/[using @apply] to its
+link:https://tabatkins.github.io/specs/css-apply-rule/[using @apply,role=external,window=_blank] to its
 direct contents.
 
 NOTE: Only items (i.e. CSS properties and mixin targets) documented here are
 guaranteed to work in the long term, since they are covered by integration
 tests. + When there is a need to add new property or endpoint, please
 link:https://bugs.chromium.org/p/gerrit/issues/entry?template=PolyGerrit%20Issue[file
-a bug] stating your use case to track and maintain for future releases.
+a bug,role=external,window=_blank] stating your use case to track and maintain for future releases.
 
 Plugins should be html-based and imported following PolyGerrit's
 link:pg-plugin-dev.html#loading[dev guide].
@@ -64,7 +65,7 @@
 
 Following CSS properties have
 link:https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata-it_test.html[long-term
-support via integration test]:
+support via integration test,role=external,window=_blank]:
 
 * `display`
 +
diff --git a/Documentation/pgm-LocalUsernamesToLowerCase.txt b/Documentation/pgm-LocalUsernamesToLowerCase.txt
index 53081a1..a526647 100644
--- a/Documentation/pgm-LocalUsernamesToLowerCase.txt
+++ b/Documentation/pgm-LocalUsernamesToLowerCase.txt
@@ -28,10 +28,14 @@
 Please be aware that the conversion of the local usernames to lower
 case can't be undone.
 
-The program will produce errors if there are accounts that have the
+The program will produce errors if there are accounts with a different
+account-id or other properties (e.g. email, password) that have the
 same local username, but with different case. In this case the local
 username for these accounts is not converted to lower case.
 
+The program will automatically remove duplicates where the username
+differs only in case but all other attributes are identical.
+
 After all usernames have been migrated, the link:pgm-reindex.html[
 reindex] program is automatically invoked to reindex all accounts.
 
diff --git a/Documentation/pgm-MigrateAccountPatchReviewDb.txt b/Documentation/pgm-MigrateAccountPatchReviewDb.txt
index c8ab193..64a1008 100644
--- a/Documentation/pgm-MigrateAccountPatchReviewDb.txt
+++ b/Documentation/pgm-MigrateAccountPatchReviewDb.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = MigrateAccountPatchReviewDb
 
 == NAME
@@ -30,7 +31,7 @@
 [NOTE]
 When using MySQL, the file_name column length in the account_patch_reviews table will be shortened
 from the standard 4096 characters down to 255 characters. This is due to a
-link:https://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html[MySQL limitation]
+link:https://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html[MySQL limitation,role=external,window=_blank]
 on the max size of 767 bytes for each column in an index.
 
 == OPTIONS
diff --git a/Documentation/prolog-cookbook.txt b/Documentation/prolog-cookbook.txt
index f291920..21b8c9f 100644
--- a/Documentation/prolog-cookbook.txt
+++ b/Documentation/prolog-cookbook.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Prolog Submit Rules Cookbook
 
 [[SubmitRule]]
@@ -23,10 +24,10 @@
 link:config-gerrit.html#_a_id_rules_a_section_rules[rules section])
 
 link:https://groups.google.com/d/topic/repo-discuss/wJxTGhlHZMM/discussion[This
-discussion thread] explains why Prolog was chosen for the purpose of writing
+discussion thread,role=external,window=_blank] explains why Prolog was chosen for the purpose of writing
 project specific submit rules.
 link:http://gerrit-documentation.googlecode.com/svn/ReleaseNotes/ReleaseNotes-2.2.2.html[Gerrit
-2.2.2 ReleaseNotes] introduces Prolog support in Gerrit.
+2.2.2 ReleaseNotes,role=external,window=_blank] introduces Prolog support in Gerrit.
 
 [[SubmitType]]
 == Submit Type
@@ -58,14 +59,14 @@
 
 == Prolog Language
 This document is not a complete Prolog tutorial.
-link:http://en.wikipedia.org/wiki/Prolog[This Wikipedia page on Prolog] is a
+link:http://en.wikipedia.org/wiki/Prolog[This Wikipedia page on Prolog,role=external,window=_blank] is a
 good starting point for learning the Prolog language. This document will only
 explain some elements of Prolog that are necessary to understand the provided
 examples.
 
 == Prolog in Gerrit
-Gerrit uses its own link:https://gerrit.googlesource.com/prolog-cafe/[fork] of the
-original link:http://kaminari.istc.kobe-u.ac.jp/PrologCafe/[prolog-cafe]
+Gerrit uses its own link:https://gerrit.googlesource.com/prolog-cafe/[fork,role=external,window=_blank] of the
+original link:http://kaminari.istc.kobe-u.ac.jp/PrologCafe/[prolog-cafe,role=external,window=_blank]
 project. Gerrit embeds the prolog-cafe library and can interpret Prolog programs
 at runtime.
 
@@ -75,7 +76,7 @@
 Prolog interpreter shell.
 
 For batch or unit tests, see the examples in Gerrit source directory
-link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/prologtests/examples/[prologtests/examples].
+link:https://gerrit.googlesource.com/gerrit/+/refs/heads/master/prologtests/examples/[prologtests/examples,role=external,window=_blank].
 
 [NOTE]
 The interactive shell is just a prolog shell, it does not load
@@ -84,7 +85,7 @@
 
 == SWI-Prolog
 Instead of using the link:pgm-prolog-shell.html[prolog-shell] program one can
-also use the link:http://www.swi-prolog.org/[SWI-Prolog] environment. It
+also use the link:http://www.swi-prolog.org/[SWI-Prolog,role=external,window=_blank] environment. It
 provides a better shell interface and a graphical source-level debugger.
 
 [[RulesFile]]
diff --git a/Documentation/quota.txt b/Documentation/quota.txt
index a647e33..475ae72 100644
--- a/Documentation/quota.txt
+++ b/Documentation/quota.txt
@@ -1,9 +1,10 @@
+:linkattrs:
 = Gerrit Code Review - Quota
 
 Gerrit does not provide out of the box quota enforcement. However, it does
 support an extension mechanism for plugins to hook into to provide this
 functionality. The most prominent plugin is the
-link:https://gerrit.googlesource.com/plugins/quota/[Quota Plugin].
+link:https://gerrit.googlesource.com/plugins/quota/[Quota Plugin,role=external,window=_blank].
 
 This documentation is intended to be read by plugin developers. It contains all
 quota requests implemented in Gerrit-core as well as the metadata that they have
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 6f0d828..6fbedb0 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - /accounts/ REST API
 
 This page describes the account related REST endpoints.
@@ -58,8 +59,8 @@
 
 [[details]]
 --
-* `DETAILS`: Includes full name, preferred email, username, avatars,
-status and state for each account.
+* `DETAILS`: Includes full name, preferred email, username, display
+name, avatars, status and state for each account.
 --
 
 [[all-emails]]
@@ -99,12 +100,14 @@
       "name": "John Doe",
       "email": "john.doe@example.com",
       "username": "john"
+      "display_name": "John D"
     },
     {
       "_account_id": 1001439,
       "name": "John Smith",
       "email": "john.smith@example.com",
       "username": "jsmith"
+      "display_name": "Johnny"
     },
   ]
 ----
@@ -134,6 +137,7 @@
     "name": "John Doe",
     "email": "john.doe@example.com",
     "username": "john"
+    "display_name": "Super John"
   }
 ----
 
@@ -155,6 +159,7 @@
 
   {
     "name": "John Doe",
+    "display_name": "Super John",
     "email": "john.doe@example.com",
     "ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0T...YImydZAw==",
     "http_password": "19D9aIn7zePb",
@@ -208,6 +213,7 @@
     "name": "John Doe",
     "email": "john.doe@example.com",
     "username": "john"
+    "display_name": "Super John"
   }
 ----
 
@@ -401,6 +407,27 @@
 
 As response the new username is returned.
 
+[[set-display-name]]
+=== Set Display Name
+--
+'PUT /accounts/link:#account-id[\{account-id\}]/displayname'
+--
+
+The new display name must be provided in the request body inside
+a link:#display-name-input[DisplayNameInput] entity.
+
+.Request
+----
+  PUT /accounts/self/displayname HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "display_name": "John"
+  }
+----
+
+As response the new display name is returned.
+
 [[get-active]]
 === Get Active
 --
@@ -569,6 +596,9 @@
 
 Returns the email addresses that are configured for the specified user.
 
+link:access-control.html#capability_modifyAccount[ModifyAccount]
+capability is required to view emails of other users.
+
 .Request
 ----
   GET /accounts/self/emails HTTP/1.0
@@ -1705,6 +1735,10 @@
 
 Retrieves the external ids of a user account.
 
+Only external ids belonging to the caller may be requested. Users that have
+link:access-control.html#capability_modifyAccount[Modify Account] can request
+external ids that belong to other accounts.
+
 .Request
 ----
   GET /a/accounts/self/external.ids HTTP/1.0
@@ -1738,7 +1772,9 @@
 Delete a list of external ids for a user account. The target external ids must
 be provided as a list in the request body.
 
-Only external ids belonging to the caller may be deleted.
+Only external ids belonging to the caller may be deleted. Users that have
+link:access-control.html#capability_modifyAccount[Modify Account] can delete
+external ids that belong to other accounts.
 
 .Request
 ----
@@ -2231,6 +2267,11 @@
 See option link:rest-api-changes.html#detailed-accounts[
 DETAILED_ACCOUNTS] for change queries +
 and option link:#details[DETAILS] for account queries.
+|`display_name`    |optional|The display name of the user. +
+Only set if detailed account information is requested. +
+See option link:rest-api-changes.html#detailed-accounts[
+DETAILED_ACCOUNTS] for change queries +
+and option link:#details[DETAILS] for account queries.
 |`email`           |optional|
 The email address the user prefers to be contacted through. +
 Only set if detailed account information is requested. +
@@ -2271,6 +2312,7 @@
 |`username`     |optional|
 The user name. If provided, must match the user name from the URL.
 |`name`         |optional|The full name of the user.
+|`display_name` |optional|The display name of the user.
 |`email`        |optional|The email address of the user.
 |`ssh_key`      |optional|The public SSH key of the user.
 |`http_password`|optional|The HTTP password of the user.
@@ -2383,13 +2425,18 @@
 The `ContributorAgreementInfo` entity contains information about a
 contributor agreement.
 
-[options="header",cols="1,6"]
-|=================================
-|Field Name                 |Description
-|`name`                     |The name of the agreement.
-|`description`              |The description of the agreement.
-|`url`                      |The URL of the agreement.
-|=================================
+[options="header",cols="1,^1,5"]
+|================================
+|Field Name         ||Description
+|`name`             ||The unique name of the contributor agreement.
+|`description`      ||The description of the contributor agreement.
+|`url`              ||The URL of the contributor agreement.
+|`auto_verify_group`|optional|
+The group to which a user that signs the contributor agreement online
+is added automatically as a link:rest-api-groups.html#group-info[
+GroupInfo] entity. If not set, users cannot sign the contributor
+agreement online.
+|================================
 
 [[contributor-agreement-input]]
 === ContributorAgreementInput
@@ -2426,8 +2473,8 @@
 |Field Name                 |Description
 |`change`                   |
 link:rest-api-changes.html#change-info[ChangeInfo] entity describing the change
-on which one or more comments was deleted. Populated with only the
-link:rest-api-changes.html#skip_mergeable[SKIP_MERGEABLE] option.
+on which one or more comments was deleted. Populated with no change list
+options.
 |`deleted`                  |
 List of link:rest-api-changes.html#comment-info[CommentInfo] entities for each
 comment that was deleted.
@@ -2644,7 +2691,7 @@
 |`id`         |Not set in map context|The 8-char hex GPG key ID.
 |`fingerprint`|Not set for deleted keys|The 40-char (plus spaces) hex GPG key fingerprint.
 |`user_ids`   |Not set for deleted keys|
-link:https://tools.ietf.org/html/rfc4880#section-5.11[OpenPGP User IDs]
+link:https://tools.ietf.org/html/rfc4880#section-5.11[OpenPGP User IDs,role=external,window=_blank]
 associated with the public key.
 |`key`        |Not set for deleted keys|ASCII armored public key material.
 |`status`     |Not set for deleted keys|
@@ -2868,6 +2915,17 @@
 |`username` |The new username of the account.
 |=======================
 
+[[display-name-input]]
+=== DisplayNameInput
+The `DisplayNameInput` entity contains information for setting the
+display name for an account.
+
+[options="header",cols="1,6"]
+|=======================
+|Field Name     |Description
+|`display_name` |The new display name of the account.
+|=======================
+
 [[project-watch-info]]
 === ProjectWatchInfo
 The `WatchedProjectsInfo` entity contains information about a project watch
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index e39355c..e9a4caf 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - /changes/ REST API
 
 This page describes the change related REST endpoints.
@@ -72,7 +73,9 @@
 Queries changes visible to the caller. The
 link:user-search.html#_search_operators[query string] must be provided
 by the `q` parameter. The `n` parameter can be used to limit the
-returned results.
+returned results. The `no-limit` parameter can be used remove the default
+limit on queries and return all results. This might not be supported by
+all index backends.
 
 As result a list of link:#change-info[ChangeInfo] entries is returned.
 The change output is sorted by the last update time, most recently
@@ -309,21 +312,6 @@
     from the change owner, i.e. this change would show up in the results of
     link:user-search.html#reviewedby[reviewedby:self].
 --
-
-[[skip_mergeable]]
---
-* `SKIP_MERGEABLE`: skip the `mergeable` field in
-link:#change-info[ChangeInfo]. For fast moving projects, this field must
-be recomputed often, which is slow for projects with big trees.
-+
-When link:config-gerrit.html#change.api.excludeMergeableInChangeInfo[
-`change.api.excludeMergeableInChangeInfo`] is set in the `gerrit.config`,
-the `mergeable` field will always be omitted and `SKIP_MERGEABLE` has no
-effect.
-+
-A change's mergeability can be requested separately by calling the
-link:#get-mergeable[get-mergeable] endpoint.
---
 [[skip_diffstat]]
 --
 * `SKIP_DIFFSTAT`: skip the 'insertions' and 'deletions' field in link:#change-info[ChangeInfo].
@@ -369,11 +357,6 @@
   as link:#tracking-id-info[TrackingIdInfo].
 --
 
-[[no-limit]]
---
-* `NO-LIMIT`: Return all results
---
-
 .Request
 ----
   GET /changes/?q=97&o=CURRENT_REVISION&o=CURRENT_COMMIT&o=CURRENT_FILES&o=DOWNLOAD_COMMANDS HTTP/1.0
@@ -1455,6 +1438,10 @@
 
 Reverts a change.
 
+The subject of the newly created change will be
+'Revert "<subject-of-reverted-change>"'. If the subject of the change reverted is
+above 63 characters, it will be cut down to 59 characters with "..." in the end.
+
 The request body does not need to include a link:#revert-input[
 RevertInput] entity if no review comment is added.
 
@@ -1492,9 +1479,126 @@
   }
 ----
 
+If the user doesn't have revert permission on the change or upload permission on
+the destination branch, the response is "`403 Forbidden`", and the error message is
+contained in the response body.
+
 If the change cannot be reverted because the change state doesn't
-allow reverting the change, the response is "`409 Conflict`" and
-the error message is contained in the response body.
+allow reverting the change the response is "`409 Conflict`", and the error
+message is contained in the response body.
+
+.Response
+----
+  HTTP/1.1 409 Conflict
+  Content-Disposition: attachment
+  Content-Type: text/plain; charset=UTF-8
+
+  change is new
+----
+
+[[revert-submission]]
+=== Revert Submission
+--
+'POST /changes/link:#change-id[\{change-id\}]/revert_submission'
+--
+
+Creates open revert changes for all of the changes of a certain submission.
+
+The subject of each revert change will be 'Revert "<subject-of-reverted-change"'.
+If the subject is above 60 characters, the subject will be cut to 56 characters
+with "..." in the end. However, whenever reverting the submission of a revert
+submission, the subject will be shortened from
+'Revert "Revert "<subject-of-reverted-change""' to
+'Revert^2 "<subject-of-reverted-change"'. Also, for every future revert submission,
+the only difference in the subject will be the number of the revert (instead of
+Revert^2 the subject will change to Revert^3 and so on).
+There are no guarantees about the subjects if the users change the default subjects.
+
+Details for the revert can be specified in the request body inside a link:#revert-input[
+RevertInput] The topic of all created revert changes will be
+`revert-{submission_id}-{random_string_of_size_10}`.
+
+The changes will not be rebased on onto the destination branch so the users may still
+have to manually rebase them to resolve conflicts and make them submittable.
+
+However, the changes that have the same project and branch will be rebased on top
+of each other. E.g, the first revert change will have the original change as a
+parent, and the second revert change will have the first revert change as a
+parent.
+
+There is one special case that involves merge commits; if a user has multiple
+changes in the same project and branch, but not in the same change series, those
+changes can still get submitted together if they have the same topic and
+link:config-gerrit.html#change.submitWholeTopic[`change.submitWholeTopic`] in
+gerrit.config is set to true. In the case, Gerrit may create merge commits on
+submit (depending on the link:config-project-config.html#submit-type[submit types]
+of the project).
+The first parent for the reverts will be the most recent merge commit that was
+created by Gerrit to merge the different change series into the target branch.
+
+.Request
+----
+  POST /changes/myProject~master~I1ffe09a505e25f15ce1521bcfb222e51e62c2a14/revert_submission HTTP/1.0
+----
+
+As response link:#revert-submission-info[RevertSubmissionInfo] entity
+is returned. That entity describes the revert changes.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  "revert_changes":
+    [
+      {
+        "id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
+        "project": "myProject",
+        "branch": "master",
+        "topic": "revert--1571043962462-3640749-ABCEEZGHIJ",
+        "change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
+        "subject": "Revert \"Implementing Feature X\"",
+        "status": "NEW",
+        "created": "2013-02-01 09:59:32.126000000",
+        "updated": "2013-02-21 11:16:36.775000000",
+        "mergeable": true,
+        "insertions": 6,
+        "deletions": 4,
+        "_number": 3965,
+        "owner": {
+          "name": "John Doe"
+        }
+      },
+      {
+        "id": "anyProject~master~1eee2c9d8f352483781e772f35dc586a69ff5646",
+        "project": "anyProject",
+        "branch": "master",
+        "topic": "revert--1571043962462-3640749-ABCEEZGHIJ",
+        "change_id": "I1eee2c9d8f352483781e772f35dc586a69ff5646",
+        "subject": "Revert \"Implementing Feature Y\"",
+        "status": "NEW",
+        "created": "2013-02-04 09:59:33.126000000",
+        "updated": "2013-02-21 11:16:37.775000000",
+        "mergeable": true,
+        "insertions": 62,
+        "deletions": 11,
+        "_number": 3966,
+        "owner": {
+          "name": "Jane Doe"
+        }
+      }
+    ]
+----
+
+If the user doesn't have revert permission on the change or upload permission on
+the destination, the response is "`403 Forbidden`", and the error message is
+contained in the response body.
+
+If the change cannot be reverted because the change state doesn't
+allow reverting the change the response is "`409 Conflict`", and the error
+message is contained in the response body.
 
 .Response
 ----
@@ -2271,7 +2375,7 @@
 A message can be specified in the request body inside a
 link:#private-input[PrivateInput] entity. Historically, this method allowed
 a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use a POST request instead:
 
 .Request
@@ -2632,6 +2736,20 @@
   PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit/foo HTTP/1.0
 ----
 
+To upload a file as binary data in the request body:
+
+.Request
+----
+  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit/foo HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "binary_content": "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ=="
+  }
+----
+
+Note that it must be base-64 encoded data uri.
+
 When change edit doesn't exist for this change yet it is created. When file
 content isn't provided, it is wiped out for that file. As response
 "`204 No Content`" is returned.
@@ -3253,7 +3371,7 @@
 Options can be provided in the request body as a
 link:#delete-reviewer-input[DeleteReviewerInput] entity.
 Historically, this method allowed a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use a POST request instead:
 
 .Request
@@ -3333,7 +3451,7 @@
 Options can be provided in the request body as a
 link:#delete-vote-input[DeleteVoteInput] entity.
 Historically, this method allowed a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use a POST request instead:
 
 .Request
@@ -3797,6 +3915,10 @@
 The review must be provided in the request body as a
 link:#review-input[ReviewInput] entity.
 
+If the labels are set, the user sending the request will automatically be
+added as a reviewer, otherwise (if they only commented) they are added to
+the CC list.
+
 A review cannot be set on a change edit. Trying to post a review for a
 change edit fails with `409 Conflict`.
 
@@ -4705,7 +4827,7 @@
 Deletion reason can be provided in the request body as a
 link:#delete-comment-input[DeleteCommentInput] entity.
 Historically, this method allowed a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use a POST request instead:
 
 .Request
@@ -5265,6 +5387,17 @@
 The `context` parameter can be specified to control the number of lines of surrounding context
 in the diff.  Valid values are `ALL` or number of lines.
 
+[[preview-fix]]
+=== Preview fix
+--
+'GET /changes/<<change-id,\{change-id\}>>/revisions/<<revision-id,\{revision-id\}>>/fixes/<<fix-id,\{fix-id\}>>/preview'
+--
+
+Gets the diffs of all files for a certain <<fix-id,\{fix-id\}>>.
+As response, a map of link:#diff-info[DiffInfo] entities is returned that describes the diffs.
+
+Each link:#diff-info[DiffInfo] is the differences between the patch set indicated by revision-id and a virtual patch set with the applied fix.
+
 [[get-blame]]
 === Get Blame
 --
@@ -5390,8 +5523,8 @@
   }
 ----
 
-As response a link:#cherry-pick-change-info[CherryPickChangeInfo]
-entity is returned that describes the resulting cherry-pick change.
+As response a link:#change-info[ChangeInfo] entity is returned that
+describes the resulting cherry-pick change.
 
 .Response
 ----
@@ -5525,7 +5658,7 @@
 Options can be provided in the request body as a
 link:#delete-vote-input[DeleteVoteInput] entity.
 Historically, this method allowed a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use a POST request instead:
 
 .Request
@@ -5827,10 +5960,9 @@
 Not set for merged changes.
 |`mergeable`          |optional|
 Whether the change is mergeable. +
-Not set for merged changes, if the change has not yet been tested, or
-if the link:#skip_mergeable[skip_mergeable] option is set or when
-link:config-gerrit.html#change.api.excludeMergeableInChangeInfo[change.api.excludeMergeableInChangeInfo]
-is set.
+Only set for open changes if
+link:config-gerrit.html#change.mergeabilityComputationBehavior[change.mergeabilityComputationBehavior]
+is `API_REF_UPDATED_AND_CHANGE_REINDEX`.
 |`submittable`        |optional|
 Whether the change has been approved by the project submit rules. +
 Only set if link:#submittable[requested].
@@ -5919,6 +6051,27 @@
 When present, change has been marked Ready at some point in time.
 |`revert_of`          |optional|
 The numeric Change-Id of the change that this change reverts.
+|`submission_id`      |optional|
+ID of the submission of this change. Only set if the status is `MERGED`.
+This ID is equal to the numeric ID of the change that triggered the submission.
+If the change that triggered the submission also has a topic, it will be
+"<id>-<topic>" of the change that triggered the submission.
+The callers must not rely on the format of the submission ID.
+|`cherry_pick_of_change`   |optional|
+The numeric Change-Id of the change that this change was cherry-picked from.
+|`cherry_pick_of_patch_set`|optional|
+The patchset number of the change that this change was cherry-picked from.
+|`contains_git_conflicts`  |optional, not set if `false`|
+Whether the change contains conflicts. +
+If `true`, some of the file contents of the change contain git conflict
+markers to indicate the conflicts. +
+Only set if this change info is returned in response to a request that
+creates a new change or patch set and conflicts are allowed. In
+particular this field is only populated if the change info is returned
+by one of the following REST endpoints: link:#create-change[Create
+Change], link:#create-merge-patch-set-for-change[Create Merge Patch Set
+For Change], link:#cherry-pick[Cherry Pick Revision],
+link:rest-api-project.html#cherry-pick-commit[Cherry Pick Commit]
 |==================================
 
 [[change-input]]
@@ -5933,9 +6086,16 @@
 The name of the target branch. +
 The `refs/heads/` prefix is omitted.
 |`subject`            ||
-The commit message of the change. Comment lines (beginning with `#`) will
-be removed.
+The commit message of the change. Comment lines (beginning with `#`)
+will be removed. If the commit message contains a Change-Id (as a
+"Change-Id: I..." footer) that Change-Id will be used for the newly
+created changed. If a change with this Change-Id already exists for
+same repository and branch, the request is rejected since Change-Ids
+must be unique per repository and branch. If the commit message doesn't
+contain a Change-Id, a newly generated Change-Id is automatically
+inserted into the commit message.
 |`topic`              |optional|The topic to which this change belongs.
+Topic can't contain quotation marks.
 |`status`             |optional, default to `NEW`|
 The status of the change (only `NEW` accepted here).
 |`is_private`         |optional, default to `false`|
@@ -5957,6 +6117,13 @@
 If set, the target branch (see  `branch` field) must exist (it is not
 possible to create it automatically by setting the `new_branch` field
 to `true`.
+|`author`             |optional|
+An link:rest-api-accounts.html#account-input[AccountInput] entity
+that will set the author of the commit to create. The author must be
+specified as name/email combination.
+The caller needs "Forge Author" permission when using this field.
+This field does not affect the owner of the change, which will
+continue to use the identity of the caller.
 |`notify`             |optional|
 Notify handling that defines to whom email notifications should be sent
 after the change is created. +
@@ -5997,23 +6164,6 @@
 Which patchset (if any) generated this message.
 |==================================
 
-[[cherry-pick-change-info]]
-=== CherryPickChangeInfo
-The `CherryPickChangeInfo` entity contains information about a
-cherry-pick change.
-
-`CherryPickChangeInfo` has the same fields as link:#change-info[
-ChangeInfo]. In addition `CherryPickChangeInfo` has the following
-fields:
-
-[options="header",cols="1,^1,5"]
-|======================================
-|Field Name               ||Description
-|`contains_git_conflicts` |optional, not set if `false`|
-Whether any file in the change contains Git conflict markers.
-|======================================
-
-
 [[cherrypick-input]]
 === CherryPickInput
 The `CherryPickInput` entity contains information for cherry-picking a change to a new branch.
@@ -6045,10 +6195,21 @@
 there are conflicts. If there are conflicts the file contents of the
 created change contain git conflict markers to indicate the conflicts.
 Callers can find out if there were conflicts by checking the
-`contains_git_conflicts` field in the link:#cherry-pick-change-info[
-CherryPickChangeInfo] that is returned by the cherry-pick REST
-endpoints. If there are conflicts the cherry-pick change is marked as
+`contains_git_conflicts` field in the link:#change-info[ChangeInfo]. If
+there are conflicts the cherry-pick change is marked as
 work-in-progress.
+|`topic`            |optional|
+The topic of the created cherry-picked change. If not set, the default depends
+on the source. If the source is a change with a topic, the resulting topic
+of the cherry-picked change will be {source_change_topic}-{destination_branch}.
+Otherwise, if the source change has no topic, or the source is a commit,
+the created change will have no topic.
+If the change already exists, the topic will not change if not set. If set, the
+topic will be overridden.
+|`allow_empty`      |optional, defaults to false|
+If `true`, the cherry-pick succeeds also if the created commit will be empty.
+If `false`, a cherry-pick that would create an empty commit fails without creating
+the commit.
 |===========================
 
 [[comment-info]]
@@ -6098,6 +6259,10 @@
 Whether or not the comment must be addressed by the user. The state of
 resolution of a comment thread is stored in the last comment in that thread
 chronologically.
+|`change_message_id` |optional|
+Available with published comments. Contains the
+link:rest-api-changes.html#change-message-info[id] of the change message
+that this comment is linked to.
 |===========================
 
 [[comment-input]]
@@ -6139,7 +6304,7 @@
 |`tag`         |optional, drafts only|
 Value of the `tag` field. Only allowed on link:#create-draft[draft comment] +
 inputs; for published comments, use the `tag` field in +
-link#review-input[ReviewInput]. Votes/comments that contain `tag` with
+link:#review-input[ReviewInput]. Votes/comments that contain `tag` with
 'autogenerated:' prefix can be filtered out in the web UI.
 |`unresolved`        |optional|
 Whether or not the comment must be addressed by the user. This value will
@@ -6657,16 +6822,16 @@
 Submit type used for this change, can be `MERGE_IF_NECESSARY`,
 `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`, `REBASE_ALWAYS`, `MERGE_ALWAYS` or
 `CHERRY_PICK`.
-|`strategy`     |optional|
+|`strategy`      |optional|
 The strategy of the merge, can be `recursive`, `resolve`,
 `simple-two-way-in-core`, `ours` or `theirs`.
 |`mergeable`     ||
 `true` if this change is cleanly mergeable, `false` otherwise
-|`commit_merged`     |optional|
+|`commit_merged` |optional|
 `true` if this change is already merged, `false` otherwise
-|`content_merged`     |optional|
+|`content_merged`|optional|
 `true` if the content of this change is already merged, `false` otherwise
-|`conflicts`|optional|
+|`conflicts`     |optional|
 A list of paths with conflicts
 |`mergeable_into`|optional|
 A list of other branch names where this change could merge cleanly
@@ -6677,16 +6842,31 @@
 The `MergeInput` entity contains information about the merge
 
 [options="header",cols="1,^1,5"]
-|============================
-|Field Name      ||Description
-|`source`   ||
+|==============================
+|Field Name       ||Description
+|`source`         ||
 The source to merge from, e.g. a complete or abbreviated commit SHA-1,
 a complete reference name, a short reference name under `refs/heads`, `refs/tags`,
 or `refs/remotes` namespace, etc.
-|`strategy`     |optional|
+|`source_branch`  |optional|
+A branch from which `source` is reachable. If specified,
+`source` is checked for visibility and reachability against only this
+branch. This speeds up the operation, especially for large repos with
+many branches.
+|`strategy`       |optional|
 The strategy of the merge, can be `recursive`, `resolve`,
 `simple-two-way-in-core`, `ours` or `theirs`, default will use project settings.
-|============================
+|`allow_conflicts`|optional, defaults to false|
+If `true`, creating the merge succeeds also if there are conflicts. +
+If there are conflicts the file contents of the created change contain
+git conflict markers to indicate the conflicts. +
+Callers can find out whether there were conflicts by checking the
+`contains_git_conflicts` field in the link:#change-info[ChangeInfo]. +
+If there are conflicts the change is marked as work-in-progress. +
+This option is not supported for all merge strategies (e.g. it's
+supported for `recursive` and `resolve`, but not for
+`simple-two-way-in-core`).
+|==============================
 
 [[merge-patch-set-input]]
 === MergePatchSetInput
@@ -6888,8 +7068,6 @@
 Alphanumerical (plus hyphens or underscores) string to identify what the requirement is and why it
 was triggered. Can be seen as a class: requirements sharing the same type were created for a similar
 reason, and the data structure will follow one set of rules.
-|`data`          |optional|
-Holds custom key-value strings, used in templates to render richer status messages
 |===========================
 
 
@@ -6924,10 +7102,25 @@
 Additional information about whom to notify about the revert as a map
 of recipient type to link:#notify-info[NotifyInfo] entity.
 |`topic`         |optional|
-Name of the topic for the revert change. If not set, the default is the topic
-of the change being reverted.
+Name of the topic for the revert change. If not set, the default for Revert
+endpoint is the topic of the change being reverted, and the default for the
+RevertSubmission endpoint is `revert-{submission_id}-{timestamp.now}`.
+Topic can't contain quotation marks.
 |=============================
 
+[[revert-submission-info]]
+=== RevertSubmissionInfo
+The `RevertSubmissionInfo` entity describes the revert changes.
+
+[options="header",cols="1,6"]
+|==============================
+|Field Name       | Description
+|`revert_changes` |
+A list of link:#change-info[ChangeInfo] that describes the revert changes. Each
+entity in that list is a revert change that was created in that revert
+submission.
+|==============================
+
 [[review-info]]
 === ReviewInfo
 The `ReviewInfo` entity contains information about a review.
@@ -7072,9 +7265,12 @@
 |`reviewer`      ||
 The link:rest-api-accounts.html#account-id[ID] of one account that
 should be added as reviewer or the link:rest-api-groups.html#group-id[
-ID] of one group for which all members should be added as reviewers. +
+ID] of one internal group for which all members should be added as reviewers. +
 If an ID identifies both an account and a group, only the account is
 added as reviewer to the change.
+External groups, such as LDAP groups, will be silently omitted from a
+link:#set-review[set-review] or
+link:rest-api-changes.html#add-reviewer[add-reviewer] call.
 |`state`         |optional|
 Add reviewer in this state. Possible reviewer states are `REVIEWER`
 and `CC`. If not given, defaults to `REVIEWER`.
@@ -7332,6 +7528,7 @@
 |Field Name    ||Description
 |`topic`       |optional|The topic. +
 The topic will be deleted if not set.
+Topic can't contain quotation marks.
 |===========================
 
 [[tracking-id-info]]
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index 063e54d..f76e0b8 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -1419,10 +1419,13 @@
 
 [options="header",cols="1,6"]
 |=============================
-|Field Name           |Description
-|`visibility`         |
+|Field Name            |Description
+|`visibility`          |
 link:config-gerrit.html#accounts.visibility[Visibility setting for
 accounts].
+|`default_display_name`|The default strategy for choosing the display
+name in the UI, see also
+link:config-gerrit.html#accounts.defaultDisplayName[gerrit.config].
 |=============================
 
 [[auth-info]]
@@ -1566,10 +1569,30 @@
 the whole topic is submitted].
 |`disable_private_changes` |not set if `false`|
 Returns true if private changes are disabled.
-|`exclude_mergeable_in_change_info` |not set if `false`|
-Value of the link:config-gerrit.html#change.api.excludeMergeableInChangeInfo[
+|`mergeability_computation_behavior` ||
+Value of the link:config-gerrit.html#change.mergeabilityComputationBehavior[
 configuration parameter] that controls whether the mergeability bit in
-link:rest-api-changes.html#change-info[ChangeInfo] will never be set.
+link:rest-api-changes.html#change-info[ChangeInfo] will never be set and if the
+bit is indexed.
+|`enable_attention_set` |defaults to `false`|
+Returns true if attention set UI features are enabled.
+|`enable_assignee` |defaults to `true`|
+Returns true if assignee related UI features are enabled.
+|=============================
+
+[[change-index-config-info]]
+=== ChangeIndexConfigInfo
+The `ChangeIndexConfigInfo` entity contains information about Gerrit
+configuration from the link:config-gerrit.html#index.change[index.change]
+section.
+
+[options="header",cols="1,^1,5"]
+|=============================
+|Field Name           ||Description
+|`index_mergeable`        |not set if `false`|
+Value of the link:config-gerrit.html#index.change.indexMergeable[
+configuration parameter] that controls whether the mergeability bit is
+indexed (hence queryable using `is:mergeable`).
 |=============================
 
 [[check-account-external-ids-input]]
@@ -1821,6 +1844,21 @@
 link:config-gerrit.html#gerrit.reportBugUrl[URL to report bugs].
 |=================================
 
+[[index-config-info]]
+=== IndexConfigInfo
+The `IndexConfigInfo` entity contains information about Gerrit
+configuration from the link:config-gerrit.html#index[index]
+section.
+
+[options="header",cols="1,^1,5"]
+|=============================
+|Field Name           ||Description
+|`change`                  ||
+Information about the configuration from the
+link:config-gerrit.html#index.change[index.change] section as
+link:#index.change[ChangeIndexConfigInfo] entity.
+|=============================
+
 [[hit-ration-info]]
 === HitRatioInfo
 The `HitRatioInfo` entity contains information about the hit ratio of a
@@ -1947,6 +1985,10 @@
 Information about the configuration from the
 link:config-gerrit.html#gerrit[gerrit] section as link:#gerrit-info[
 GerritInfo] entity.
+|`index`                  ||
+Information about the configuration from the
+link:config-gerrit.html#index[index] section as link:#index[
+IndexConfigInfo] entity.
 |`note_db_enabled`         |not set if `false`|
 Whether the NoteDb storage backend is fully enabled.
 |`plugin`                  ||
diff --git a/Documentation/rest-api-groups.txt b/Documentation/rest-api-groups.txt
index c4ba973..72974e2 100644
--- a/Documentation/rest-api-groups.txt
+++ b/Documentation/rest-api-groups.txt
@@ -341,24 +341,19 @@
 [[query-groups]]
 === Query Groups
 --
-'GET /groups/?query2=<query>'
+'GET /groups/?query=<query>'
 --
 
 Queries internal groups visible to the caller. The
 link:user-search-groups.html#_search_operators[query string] must be
-provided by the `query2` parameter. The `start` and `limit` parameters
+provided by the `query` parameter. The `start` and `limit` parameters
 can be used to skip/limit results.
 
 As result a list of link:#group-info[GroupInfo] entities is returned.
 
-[NOTE] `query2` is a temporary name and in future this option may be
-renamed to `query`. `query2` was chosen to maintain backwards
-compatibility with the deprecated `query` parameter on the
-link:#list-groups[List Groups] endpoint.
-
 .Request
 ----
-  GET /groups/?query2=inname:test HTTP/1.0
+  GET /groups/?query=inname:test HTTP/1.0
 ----
 
 .Response
@@ -398,12 +393,12 @@
 
 [[group-query-limit]]
 ==== Group Limit
-The `/groups/?query2=<query>` URL also accepts a limit integer in the
+The `/groups/?query=<query>` URL also accepts a limit integer in the
 `limit` parameter. This limits the results to `limit` groups.
 
 Query the first 25 groups in group list.
 ----
-  GET /groups/?query2=<query>&limit=25 HTTP/1.0
+  GET /groups/?query=<query>&limit=25 HTTP/1.0
 ----
 
 The `/groups/` URL also accepts a start integer in the `start`
@@ -411,7 +406,7 @@
 
 Query 25 groups starting from index 50.
 ----
-  GET /groups/?query2=<query>&limit=25&start=50 HTTP/1.0
+  GET /groups/?query=<query>&limit=25&start=50 HTTP/1.0
 ----
 
 [[group-query-options]]
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 63c3279..de2c550 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - /projects/ REST API
 
 This page describes the project related REST endpoints.
@@ -610,7 +611,7 @@
 A commit message can be provided in the request body as a
 link:#project-description-input[ProjectDescriptionInput] entity.
 Historically, this method allowed a body in the DELETE, but that behavior is
-link:https://www.gerritcodereview.com/releases/2.16.md[deprecated].
+link:https://www.gerritcodereview.com/releases/2.16.md[deprecated,role=external,window=_blank].
 In this case, use link:#set-project-description[PUT] instead.
 
 .Request
@@ -2578,9 +2579,8 @@
   }
 ----
 
-As response a link:rest-api-changes.html#cherry-pick-change-info[
-CherryPickChangeInfo] entity is returned that describes the resulting
-cherry-picked change.
+As response a link:rest-api-changes.html#change-info[ChangeInfo] entity
+is returned that describes the resulting cherry-picked change.
 
 .Response
 ----
@@ -2928,6 +2928,374 @@
   HTTP/1.1 204 No Content
 ----
 
+[[label-endpoints]]
+== Label Endpoints
+
+[[list-labels]]
+=== List Labels
+--
+'GET /projects/link:#project-name[\{project-name\}]/labels/'
+--
+
+Lists the labels that are defined in this project.
+
+The calling user must have read access to the `refs/meta/config` branch of the
+project.
+
+.Request
+----
+  GET /projects/All-Projects/labels/ HTTP/1.0
+----
+
+As result a list of link:#label-definition-info[LabelDefinitionInfo] entities
+is returned that describe the labels that are defined in this project
+(inherited labels are not returned unless the `inherited` parameter is set, see
+link:#list-with-inherited-labels[below]). The returned labels are sorted by
+label name.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  [
+    {
+      "name": "Code-Review",
+      "project": "All-Projects",
+      "function": "MaxWithBlock",
+      "values": {
+        " 0": "No score",
+        "-1": "I would prefer this is not merged as is",
+        "-2": "This shall not be merged",
+        "+1": "Looks good to me, but someone else must approve",
+        "+2": "Looks good to me, approved"
+      },
+      "default_value": 0,
+      "can_override": true,
+      "copy_min_score": true,
+      "copy_all_scores_if_no_change": true,
+      "copy_all_scores_on_trivial_rebase": true,
+      "allow_post_submit": true
+    }
+  ]
+----
+
+[[list-with-inherited-labels]]
+To include inherited labels from all parent projects the parameter `inherited`
+can be set.
+
+The calling user must have read access to the `refs/meta/config` branch of the
+project and all its parent projects.
+
+.Request
+----
+  GET /projects/My-Project/labels/?inherited HTTP/1.0
+----
+
+As result a list of link:#label-definition-info[LabelDefinitionInfo] entities
+is returned that describe the labels that are defined in this project and in
+all its parent projects. The returned labels are sorted by parent projects
+in-order from `All-Projects` through the project hierarchy to this project.
+Labels that belong to the same project are sorted by label name.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  [
+    {
+      "name": "Code-Review",
+      "project": "All-Projects",
+      "function": "MaxWithBlock",
+      "values": {
+        " 0": "No score",
+        "-1": "I would prefer this is not merged as is",
+        "-2": "This shall not be merged",
+        "+1": "Looks good to me, but someone else must approve",
+        "+2": "Looks good to me, approved"
+      },
+      "default_value": 0,
+      "can_override": true,
+      "copy_min_score": true,
+      "copy_all_scores_if_no_change": true,
+      "copy_all_scores_on_trivial_rebase": true,
+      "allow_post_submit": true
+    },
+    {
+      "name": "Foo-Review",
+      "project": "My-Project",
+      "function": "MaxWithBlock",
+      "values": {
+        " 0": "No score",
+        "-1": "I would prefer this is not merged as is",
+        "-2": "This shall not be merged",
+        "+1": "Looks good to me, but someone else must approve",
+        "+2": "Looks good to me, approved"
+      },
+      "default_value": 0,
+      "can_override": true,
+      "copy_any_score": true,
+      "allow_post_submit": true
+    }
+  ]
+----
+
+[[get-label]]
+=== Get Label
+--
+'GET /projects/link:#project-name[\{project-name\}]/labels/link:#label-name[\{label-name\}]'
+--
+
+Retrieves the definition of a label that is defined in this project.
+
+The calling user must have read access to the `refs/meta/config` branch of the
+project.
+
+.Request
+----
+  GET /projects/All-Projects/labels/Code-Review HTTP/1.0
+----
+
+As response a link:#label-definition-info[LabelDefinitionInfo] entity is
+returned that describes the label.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  {
+    "name": "Code-Review",
+    "project": "All-Projects",
+    "function": "MaxWithBlock",
+    "values": {
+      " 0": "No score",
+      "-1": "I would prefer this is not merged as is",
+      "-2": "This shall not be merged",
+      "+1": "Looks good to me, but someone else must approve",
+      "+2": "Looks good to me, approved"
+    },
+    "default_value": 0,
+    "can_override": true,
+    "copy_min_score": true,
+    "copy_all_scores_if_no_change": true,
+    "copy_all_scores_on_trivial_rebase": true,
+    "allow_post_submit": true
+  }
+----
+
+[[create-label]]
+=== Create Label
+--
+'PUT /projects/link:#project-name[\{project-name\}]/labels/link:#label-name[\{label-name\}]'
+--
+
+Creates a new label definition in this project.
+
+The calling user must have write access to the `refs/meta/config` branch of the
+project.
+
+If a label with this name is already defined in this project, this label
+definition is updated (see link:#set-label[Set Label]).
+
+.Request
+----
+  PUT /projects/My-Project/labels/Foo HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "commit_message": "Create Foo Label",
+    "values": {
+      " 0": "No score",
+      "-1": "I would prefer this is not merged as is",
+      "-2": "This shall not be merged",
+      "+1": "Looks good to me, but someone else must approve",
+      "+2": "Looks good to me, approved"
+    }
+  }
+----
+
+As response a link:#label-definition-info[LabelDefinitionInfo] entity is
+returned that describes the created label.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  {
+    "name": "Foo",
+    "project_name": "My-Project",
+    "function": "MaxWithBlock",
+    "values": {
+      " 0": "No score",
+      "-1": "I would prefer this is not merged as is",
+      "-2": "This shall not be merged",
+      "+1": "Looks good to me, but someone else must approve",
+      "+2": "Looks good to me, approved"
+    },
+    "default_value": 0,
+    "can_override": true,
+    "copy_all_scores_if_no_change": true,
+    "allow_post_submit": true
+  }
+----
+
+[[set-label]]
+=== Set Label
+--
+'PUT /projects/link:#project-name[\{project-name\}]/labels/link:#label-name[\{label-name\}]'
+--
+
+Updates the definition of a label that is defined in this project.
+
+The calling user must have write access to the `refs/meta/config` branch of the
+project.
+
+Properties which are not set in the input entity are not modified.
+
+.Request
+----
+  PUT /projects/All-Projects/labels/Code-Review HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "commit_message": "Ignore self approvals for Code-Review label",
+    "ignore_self_approval": true
+  }
+----
+
+As response a link:#label-definition-info[LabelDefinitionInfo] entity is
+returned that describes the updated label.
+
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  {
+    "name": "Code-Review",
+    "project": "All-Projects",
+    "function": "MaxWithBlock",
+    "values": {
+      " 0": "No score",
+      "-1": "I would prefer this is not merged as is",
+      "-2": "This shall not be merged",
+      "+1": "Looks good to me, but someone else must approve",
+      "+2": "Looks good to me, approved"
+    },
+    "default_value": 0,
+    "can_override": true,
+    "copy_min_score": true,
+    "copy_all_scores_if_no_change": true,
+    "copy_all_scores_on_trivial_rebase": true,
+    "allow_post_submit": true,
+    "ignore_self_approval": true
+  }
+----
+
+[[delete-label]]
+=== Delete Label
+--
+'DELETE /projects/link:#project-name[\{project-name\}]/labels/link:#label-name[\{label-name\}]'
+--
+
+Deletes the definition of a label that is defined in this project.
+
+The calling user must have write access to the `refs/meta/config` branch of the
+project.
+
+The request body does not need to include a link:#delete-label-input[
+DeleteLabelInput] entity if no commit message is specified.
+
+.Request
+----
+  DELETE /projects/My-Project/labels/Foo-Review HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "commit_message": "Delete Foo-Review label",
+  }
+----
+
+If a label was deleted the response is "`204 No Content`".
+
+.Response
+----
+  HTTP/1.1 204 No Content
+----
+
+[[batch-update-labels]]
+=== Batch Update Labels
+--
+'POST /projects/link:#project-name[\{project-name\}]/labels/'
+--
+
+Creates/updates/deletes multiple label definitions in this project at once.
+
+The calling user must have write access to the `refs/meta/config` branch of the
+project.
+
+The updates must be specified in the request body as
+link:#batch-label-input[BatchLabelInput] entity.
+
+The updates are processed in the following order:
+
+1. label deletions
+2. label creations
+3. label updates
+
+.Request
+----
+  POST /projects/My-Project/labels/ HTTP/1.0
+  Content-Type: application/json; charset=UTF-8
+
+  {
+    "commit_message": "Update Labels",
+    "delete": [
+      "Old-Review",
+      "Unused-Review"
+    ],
+    "create": [
+      {
+        "name": "Foo-Review",
+        "values": {
+          " 0": "No score",
+          "-1": "I would prefer this is not merged as is",
+          "-2": "This shall not be merged",
+          "+1": "Looks good to me, but someone else must approve",
+          "+2": "Looks good to me, approved"
+      }
+    ],
+    "update:" {
+      "Bar-Review": {
+        "function": "MaxWithBlock"
+      },
+      "Baz-Review": {
+        "copy_min_score": true
+      }
+    }
+  }
+----
+
+If the label updates were done successfully the response is "`200 OK`".
+
+.Response
+----
+  HTTP/1.1 200 OK
+----
+
 
 [[ids]]
 == IDs
@@ -2952,6 +3320,10 @@
 A special dashboard ID is `default` which represents the default
 dashboard of a project.
 
+[[label-name]]
+=== \{label-name\}
+The name of a review label.
+
 [[project-name]]
 === \{project-name\}
 The name of the project.
@@ -3125,6 +3497,25 @@
 |`enabled`  |optional|Whether the commentlink is enabled, as documented
 in link:config-gerrit.html#commentlink.name.enabled[
 commentlink.name.enabled]. If not set the commentlink is enabled.
+
+[[commentlink-input]]
+=== CommentLinkInput
+The `CommentLinkInput` entity describes the input for a
+link:config-gerrit.html#commentlink[commentlink].
+
+|==================================================
+[options="header",cols="1,^2,4"]
+|==================================================
+|Field Name |        |Description
+|`match`    |        |A JavaScript regular expression to match
+positions to be replaced with a hyperlink, as documented in
+link:config-gerrit.html#commentlink.name.match[commentlink.name.match].
+|`link`     |        |The URL to direct the user to whenever the
+regular expression is matched, as documented in
+link:config-gerrit.html#commentlink.name.link[commentlink.name.link].
+|`enabled`  |optional|Whether the commentlink is enabled, as documented
+in link:config-gerrit.html#commentlink.name.enabled[
+commentlink.name.enabled]. If not set the commentlink is enabled.
 |==================================================
 
 [[config-info]]
@@ -3275,6 +3666,11 @@
 Whether empty commits should be rejected when a change is merged.
 Can be `TRUE`, `FALSE` or `INHERIT`. +
 If not set, this setting is not updated.
+|commentlinks                              |optional|
+Map of commentlink names to link:#commentlink-input[CommentLinkInput]
+entities to add or update on the project. If the given commentlink
+already exists, it will be updated with the given values, otherwise
+it will be created. If the value is null, that entry is deleted.
 |======================================================
 
 [[config-parameter-info]]
@@ -3312,8 +3708,6 @@
 |`inherited_value` |optional|
 The inherited value of the configuration parameter, only set if
 `inheritable` is true.
-|`permitted_values` |optional|
-The list of permitted values, only set if the `type` is `LIST`.
 |===============================
 
 [[dashboard-info]]
@@ -3380,6 +3774,19 @@
 Tokens such as `${project}` are not resolved.
 |===========================
 
+[[delete-label-input]]
+=== DeleteLabelInput
+The `DeleteLabelInput` entity contains information for deleting a label
+definition in a project.
+
+[options="header",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`commit_message`|optional|
+Message that should be used to commit the deletion of the label in the
+`project.config` file to the `refs/meta/config` branch.
+|=============================
+
 [[delete-branches-input]]
 === DeleteBranchesInput
 The `DeleteBranchesInput` entity contains information about branches that should
@@ -3462,6 +3869,132 @@
 Not set if there is no parent.
 |================================
 
+[[label-definition-info]]
+=== LabelDefinitionInfo
+The `LabelDefinitionInfo` entity describes a link:config-labels.html[
+review label].
+
+[options="header",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`name`          ||
+The link:config-labels.html#label_name[name] of the label.
+|`project_name`  ||
+The name of the project in which this label is defined.
+|`function`      ||
+The link:config-labels.html#label_function[function] of the label (can be
+`MaxWithBlock`, `AnyWithBlock`, `MaxNoBlock`, `NoBlock`, `NoOp` and `PatchSetLock`.
+|`values`        ||
+The link:config-labels.html#label_value[values] of the label as a map of label
+value to value description. The label values are formatted strings, e.g. "+1"
+instead of "1", " 0" instead of "0".
+|`default_value` ||
+The link:config-labels.html#label_defaultValue[default value] of the label (as
+integer).
+|`branches`      |optional|
+A list of link:config-labels.html#label_branch[branches] for which the label
+applies. A branch can be a ref, a ref pattern or a regular expression. If not
+set, the label applies for all branches.
+|`can_override`  |`false` if not set|
+Whether this label can be link:config-labels.html#label_canOverride[overridden]
+by child projects.
+|`copy_any_score`|`false` if not set|
+Whether link:config-labels.html#label_copyAnyScore[copyAnyScore] is set on the
+label.
+|`copy_min_score`|`false` if not set|
+Whether link:config-labels.html#label_copyMinScore[copyMinScore] is set on the
+label.
+|`copy_max_score`|`false` if not set|
+Whether link:config-labels.html#label_copyMaxScore[copyMaxScore] is set on the
+label.
+|`copy_all_scores_if_no_change`|`false` if not set|
+Whether link:config-labels.html#label_copyAllScoresIfNoChange[
+copyAllScoresIfNoChange] is set on the label.
+|`copy_all_scores_if_no_code_change`|`false` if not set|
+Whether link:config-labels.html#label_copyAllScoresIfNoCodeChange[
+copyAllScoresIfNoCodeChange] is set on the label.
+|`copy_all_scores_on_trivial_rebase`|`false` if not set|
+Whether link:config-labels.html#label_copyAllScoresOnTrivialRebase[
+copyAllScoresOnTrivialRebase] is set on the label.
+|`copy_all_scores_on_merge_first_parent_update`|`false` if not set|
+Whether link:config-labels.html#label_copyAllScoresOnMergeFirstParentUpdate[
+copyAllScoresOnMergeFirstParentUpdate] is set on the label.
+|`copy_values`   |optional|
+List of values that should be copied forward when a new patch set is uploaded.
+|`allow_post_submit`|`false` if not set|
+Whether link:config-labels.html#label_allowPostSubmit[allowPostSubmit] is set
+on the label.
+|`ignore_self_approval`|`false` if not set|
+Whether link:config-labels.html#label_ignoreSelfApproval[ignoreSelfApproval] is
+set on the label.
+|=============================
+
+[[label-definition-input]]
+=== LabelDefinitionInput
+The `LabelDefinitionInput` entity describes a link:config-labels.html[
+review label].
+
+[options="header",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`commit_message`|optional|
+Message that should be used to commit the change of the label in the
+`project.config` file to the `refs/meta/config` branch.+
+Must not be set if this `LabelDefinitionInput` entity is contained in a
+link:#batch-label-input[BatchLabelInput] entity.
+|`name`          |optional|
+The new link:config-labels.html#label_name[name] of the label.+
+For label creation the name is required if this `LabelDefinitionInput` entity
+is contained in a link:#batch-label-input[BatchLabelInput]
+entity.
+|`function`      |optional|
+The new link:config-labels.html#label_function[function] of the label (can be
+`MaxWithBlock`, `AnyWithBlock`, `MaxNoBlock`, `NoBlock`, `NoOp` and `PatchSetLock`.
+|`values`        |optional|
+The new link:config-labels.html#label_value[values] of the label as a map of
+label value to value description. The label values are formatted strings, e.g.
+"+1" instead of "1", " 0" instead of "0".
+|`default_value` |optional|
+The new link:config-labels.html#label_defaultValue[default value] of the label
+(as integer).
+|`branches`      |optional|
+The new branches for which the label applies as a list of
+link:config-labels.html#label_branch[branches]. A branch can be a ref, a ref
+pattern or a regular expression. If not set, the label applies for all
+branches.
+|`can_override`  |optional|
+Whether this label can be link:config-labels.html#label_canOverride[overridden]
+by child projects.
+|`copy_any_score`|optional|
+Whether link:config-labels.html#label_copyAnyScore[copyAnyScore] is set on the
+label.
+|`copy_min_score`|optional|
+Whether link:config-labels.html#label_copyMinScore[copyMinScore] is set on the
+label.
+|`copy_max_score`|optional|
+Whether link:config-labels.html#label_copyMaxScore[copyMaxScore] is set on the
+label.
+|`copy_all_scores_if_no_change`|optional|
+Whether link:config-labels.html#label_copyAllScoresIfNoChange[
+copyAllScoresIfNoChange] is set on the label.
+|`copy_all_scores_if_no_code_change`|optional|
+Whether link:config-labels.html#label_copyAllScoresIfNoCodeChange[
+copyAllScoresIfNoCodeChange] is set on the label.
+|`copy_all_scores_on_trivial_rebase`|optional|
+Whether link:config-labels.html#label_copyAllScoresOnTrivialRebase[
+copyAllScoresOnTrivialRebase] is set on the label.
+|`copy_all_scores_on_merge_first_parent_update`|optional|
+Whether link:config-labels.html#label_copyAllScoresOnMergeFirstParentUpdate[
+copyAllScoresOnMergeFirstParentUpdate] is set on the label.
+|`copy_values`   |optional|
+List of values that should be copied forward when a new patch set is uploaded.
+|`allow_post_submit`|optional|
+Whether link:config-labels.html#label_allowPostSubmit[allowPostSubmit] is set
+on the label.
+|`ignore_self_approval`|optional|
+Whether link:config-labels.html#label_ignoreSelfApproval[ignoreSelfApproval] is
+set on the label.
+|=============================
 
 [[label-type-info]]
 === LabelTypeInfo
@@ -3498,6 +4031,27 @@
 Not set if not inherited or overridden.
 |===============================
 
+[[batch-label-input]]
+=== BatchLabelInput
+The `BatchLabelInput` entity contains information for batch updating label
+definitions in a project.
+
+[options="header",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`commit_message`|optional|
+Message that should be used to commit the label updates in the
+`project.config` file to the `refs/meta/config` branch.
+|`delete`        |optional|
+List of labels that should be deleted.
+|`create`        |optional|
+List of link:#label-definition-input[LabelDefinitionInput] entities that
+describe labels that should be created.
+|`update`        |optional|
+Map of label names to link:#label-definition-input[LabelDefinitionInput]
+entities that describe the updates that should be done for the labels.
+|=============================
+
 [[project-access-input]]
 === ProjectAccessInput
 The `ProjectAccessInput` describes changes that should be applied to a project
diff --git a/Documentation/rest-api.txt b/Documentation/rest-api.txt
index a8ab353..eabcaa9 100644
--- a/Documentation/rest-api.txt
+++ b/Documentation/rest-api.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - REST API
 
 Gerrit Code Review comes with a REST like API available over HTTP.
@@ -128,7 +129,7 @@
 === Response Codes
 The Gerrit REST endpoints use HTTP status codes as described
 in the link:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html[
-HTTP specification].
+HTTP specification,role=external,window=_blank].
 
 In most cases, the response body of an error response will be a
 plaintext, human-readable error message.
diff --git a/Documentation/user-inline-edit.txt b/Documentation/user-inline-edit.txt
index 05765ee..cd26792 100644
--- a/Documentation/user-inline-edit.txt
+++ b/Documentation/user-inline-edit.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Creating and Editing Changes in the Gerrit Web Interface
 
 == Overview
@@ -16,7 +17,7 @@
 
 To create a change in the Gerrit web interface:
 
-. From the link:http://gerrit-review.googlesource.com[Gerrit Code Review]
+. From the link:http://gerrit-review.googlesource.com[Gerrit Code Review,role=external,window=_blank]
   dashboard, select Browse > Repositories.
 
 . Under Repository Name, click the name of the repository you want to work
diff --git a/Documentation/user-notify.txt b/Documentation/user-notify.txt
index 3c922ed..5346b2e 100644
--- a/Documentation/user-notify.txt
+++ b/Documentation/user-notify.txt
@@ -125,6 +125,7 @@
 should be sent to the emails named in this section. Within a Git-style
 configuration file double quotes around complex operator values may
 need to be escaped, e.g. `filter = branch:\"^(maint|stable)-.*\"`.
+Single quotes are illegal and must be omitted.
 
 When sending email to a bare email address in a notify block, Gerrit
 Code Review ignores read access controls and assumes the administrator
diff --git a/Documentation/user-request-tracing.txt b/Documentation/user-request-tracing.txt
index b26f4c1..e684b85 100644
--- a/Documentation/user-request-tracing.txt
+++ b/Documentation/user-request-tracing.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Request Tracing
 
 [[on-demand]]
@@ -75,7 +76,7 @@
 [[auto-retry-succeeded]]
 If an auto-retry succeeds you may consider filing this as
 link:https://bugs.chromium.org/p/gerrit/issues/entry?template=GoogleSource+Issue[
-Gerrit issue] so that the Gerrit developers can fix this and treat this
+Gerrit issue,role=external,window=_blank] so that the Gerrit developers can fix this and treat this
 exception as recoverable.
 
 The trace IDs for auto-retries are generated and start with
@@ -86,8 +87,7 @@
 `AutoRetry`. For each auto-retry that happened this should match 1 or 2
 log entries:
 
-* one `ERROR` log entry with the exception that triggered the
-  auto-retry
+* one `FINE` log entry with the exception that triggered the auto-retry
 * one `FINE` log entry with the exception that happened on auto-retry
   (if this log entry is not present the operation succeeded on
   auto-retry)
diff --git a/Documentation/user-review-ui.txt b/Documentation/user-review-ui.txt
index de17c00..06c5ab7 100644
--- a/Documentation/user-review-ui.txt
+++ b/Documentation/user-review-ui.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Review UI
 
 Reviewing changes is an important task and the Gerrit Web UI provides
@@ -432,7 +433,7 @@
 The available download commands depend on the installed Gerrit plugins.
 The most popular plugin for download commands, the
 link:https://gerrit-review.googlesource.com/admin/repos/plugins/download-commands[
-download-commands] plugin, provides commands to checkout, pull and
+download-commands,role=external,window=_blank] plugin, provides commands to checkout, pull and
 cherry-pick a patch set.
 
 Each command has a copy-to-clipboard icon that allows the command to be
@@ -943,7 +944,7 @@
 contain a match and one navigates to it.
 
 For additional possibilities to search please check the
-link:http://www.vim.org/docs.php[Vim documentation]. There are other
+link:http://www.vim.org/docs.php[Vim documentation,role=external,window=_blank]. There are other
 useful ways to search, e.g. while the cursor is on a word, pressing `*`
 or `#` searches for the next or previous occurrence of the word.
 
@@ -962,7 +963,7 @@
 - `gg` / `G` moves to cursor to the start / end of the file
 - `Ctrl-D` / `Ctrl-U` scrolls downwards / upwards
 
-Please check the link:http://www.vim.org/docs.php[Vim documentation]
+Please check the link:http://www.vim.org/docs.php[Vim documentation,role=external,window=_blank]
 for further information.
 
 [[diff-preferences]]
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 0845956..0c1ec2d 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Searching Changes
 
 == Default Searches
@@ -72,6 +73,11 @@
 +
 Changes assigned to the given user.
 
+[[attention]]
+attention:'USER'::
++
+Changes whose attention set includes the given user.
+
 [[before_until]]
 before:'TIME'/until:'TIME'::
 +
@@ -140,6 +146,11 @@
 +
 Changes that revert the change specified by the numeric 'ID'.
 
+[[submissionid]]
+submissionid:'ID'::
++
+Changes that have the specified submission 'ID'.
+
 [[reviewerin]]
 reviewerin:'GROUP'::
 +
@@ -156,7 +167,7 @@
 Changes occurring in 'PROJECT'. If 'PROJECT' starts with `^` it
 matches project names by regular expression.  The
 link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[projects]]
 projects:'PREFIX'::
@@ -175,7 +186,7 @@
 Changes occurring in 'REPOSITORY'. If 'REPOSITORY' starts with `^` it
 matches repository names by regular expression.  The
 link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[repositories]]
 repositories:'PREFIX', repos:'PREFIX'::
@@ -198,7 +209,7 @@
 If 'BRANCH' starts with `^` it matches branch names by regular
 expression patterns.  The
 link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[intopic]]
 intopic:'TOPIC'::
@@ -208,7 +219,7 @@
 If 'TOPIC' starts with `^` it matches topic names by regular
 expression patterns.  The
 link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[topic]]
 topic:'TOPIC'::
@@ -223,6 +234,16 @@
 Changes whose link:intro-user.html#hashtags[hashtag] matches 'HASHTAG'.
 The match is case-insensitive.
 
+[[cherrypickof]]
+cherrypickof:'CHANGE[,PATCHSET]'::
++
+Changes which were created using the 'cherry-pick' functionality and
+whose source change number matches 'CHANGE' and source patchset number
+matches 'PATCHSET'. Note that 'PATCHSET' is optional. For example, a
+`cherrypickof:12345` matches all changes which were cherry-picked from
+change 12345 and `cherrypickof:12345,2` matches all changes which were
+cherry-picked from the 2nd patchset of change 12345.
+
 [[ref]]
 ref:'REF'::
 +
@@ -233,7 +254,7 @@
 If 'REF' starts with `^` it matches reference names by regular
 expression patterns.  The
 link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[tr,bug]]
 tr:'ID', bug:'ID'::
@@ -268,7 +289,7 @@
 Matches any change touching file at 'PATH'. By default exact path
 matching is used, but regular expressions can be enabled by starting
 with `^`.  For example, to match all XML files use `file:^.*\.xml$`.
-The link:http://www.brics.dk/automaton/[dk.brics.automaton library]
+The link:http://www.brics.dk/automaton/[dk.brics.automaton library,role=external,window=_blank]
 is used for the evaluation of such patterns.
 +
 The `^` required at the beginning of the regular expression not only
@@ -332,7 +353,7 @@
 +
 If 'DIR' starts with `^` it matches directories and directory segments by
 regular expression. The link:http://www.brics.dk/automaton/[dk.brics.automaton
-library] is used for evaluation of such patterns.
+library,role=external,window=_blank] is used for evaluation of such patterns.
 
 [[footer-operator]]
 footer:'FOOTER'::
@@ -450,6 +471,10 @@
 +
 Mergeability of abandoned changes is not computed. This operator will
 not find any abandoned but mergeable changes.
++
+This operator only works if Gerrit indexes 'mergeable'. See
+link:config-gerrit.html#index.change.indexMergeable[indexMergeable]
+for details.
 
 [[ignored]]
 is:ignored::
@@ -467,6 +492,11 @@
 +
 True if the change is Work In Progress.
 
+[[merge]]
+is:merge::
++
+True if the change is a merge commit.
+
 [[status]]
 status:open, status:pending, status:new::
 +
diff --git a/Documentation/user-signedoffby.txt b/Documentation/user-signedoffby.txt
index 507f4f2..2b000f6 100644
--- a/Documentation/user-signedoffby.txt
+++ b/Documentation/user-signedoffby.txt
@@ -1,7 +1,8 @@
+:linkattrs:
 = Gerrit Code Review - Signed-off-by Lines
 
 [NOTE]
-This document was literally taken from link:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=4e8a2372f9255a1464ef488ed925455f53fbdaa1[linux-2.6 Documentation/SubmittingPatches]
+This document was literally taken from link:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=4e8a2372f9255a1464ef488ed925455f53fbdaa1[linux-2.6 Documentation/SubmittingPatches,role=external,window=_blank]
 and is covered by the GPLv2.
 
 [[Signed-off-by]]
diff --git a/Documentation/user-upload.txt b/Documentation/user-upload.txt
index d55cb48..0670968 100644
--- a/Documentation/user-upload.txt
+++ b/Documentation/user-upload.txt
@@ -1,3 +1,4 @@
+:linkattrs:
 = Gerrit Code Review - Uploading Changes
 
 Gerrit supports three methods of uploading changes:
@@ -586,9 +587,10 @@
 === Selecting Merge Base
 
 By default new changes are opened only for new unique commits
-that have never before been seen by the Gerrit server. Clients
-may override that behavior and force new changes to be created
-by setting the merge base SHA-1 using the '%base' argument:
+that are not part of any branch in refs/heads or the target
+branch. Clients may override that behavior and force new
+changes to be created by setting the merge base SHA-1 using
+the '%base' argument:
 
 ----
   git push ssh://john.doe@git.example.com:29418/kernel/common HEAD:refs/for/master%base=$(git rev-parse origin/master)
@@ -625,7 +627,7 @@
 
 repo is a multiple repository management tool, most commonly
 used by the Android Open Source Project.  For more details, see
-link:http://source.android.com/source/using-repo.html[using repo].
+link:http://source.android.com/source/using-repo.html[using repo,role=external,window=_blank].
 
 [[repo_create]]
 === Create Changes
diff --git a/WORKSPACE b/WORKSPACE
index 54c0f8f..3906453 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,4 +1,27 @@
-workspace(name = "gerrit")
+# npm packages are split into different node_modules directories based on their usage.
+# 1. /node_modules (referenced as @npm) - contains packages to run tests, check code, etc...
+#    It is expected that @npm is used ONLY to run tools. No packages from @npm are used by
+#    other code in gerrit.
+# 2. @tools_npm (tools/node_tools/node_modules) - the tools/node_tools folder contains self-written tools
+#    which are run for building and/or testing. The @tools_npm directory contains all the packages needed to
+#    run this tools.
+# 3. @ui_npm (polygerrit-ui/app/node_modules) - packages with source code which are necessary to run polygerrit
+#    and to bundle it. Only code from these packages can be included in the final bundle for polygerrit.
+#    @ui_npm folder must not have devDependencies. All dev dependencies must be placed in @ui_dev_npm
+# 4. @ui_dev_npm (polygerrit-ui/node_modules) - devDependencies for polygerrit. The packages from these
+#    folder can be used for testing, but must not be included in the final bundle.
+# Note: separation between @ui_npm and @ui_dev_npm is necessary because with bazel we can't generate
+#    two managed directories from the same package.json. At the same time we want to avoid accidental
+#    usages of code from devDependencies in polygerrit bundle.
+workspace(
+    name = "gerrit",
+    managed_directories = {
+        "@npm": ["node_modules"],
+        "@ui_npm": ["polygerrit-ui/app/node_modules"],
+        "@ui_dev_npm": ["polygerrit-ui/node_modules"],
+        "@tools_npm": ["tools/node_tools/node_modules"],
+    },
+)
 
 load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
@@ -35,6 +58,14 @@
     ],
 )
 
+http_archive(
+    name = "build_bazel_rules_nodejs",
+    patch_args = ["-p1"],
+    patches = ["//:rules_nodejs-1.5.patch"],
+    sha256 = "d0c4bb8b902c1658f42eb5563809c70a06e46015d64057d25560b0eb4bdc9007",
+    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.5.0/rules_nodejs-1.5.0.tar.gz"],
+)
+
 # File is specific to Polymer and copied from the Closure Github -- should be
 # synced any time there are major changes to Polymer.
 # https://github.com/google/closure-compiler/blob/master/contrib/externs/polymer-1.0.js
@@ -62,10 +93,10 @@
 # Golang support for PolyGerrit local dev server.
 http_archive(
     name = "io_bazel_rules_go",
-    sha256 = "f04d2373bcaf8aa09bccb08a98a57e721306c8f6043a2a0ee610fd6853dcde3d",
+    sha256 = "b34cbe1a7514f5f5487c3bfee7340a4496713ddf4f119f7a225583d6cafd793a",
     urls = [
-        "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.18.6/rules_go-0.18.6.tar.gz",
-        "https://github.com/bazelbuild/rules_go/releases/download/0.18.6/rules_go-0.18.6.tar.gz",
+        "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.21.1/rules_go-v0.21.1.tar.gz",
+        "https://github.com/bazelbuild/rules_go/releases/download/v0.21.1/rules_go-v0.21.1.tar.gz",
     ],
 )
 
@@ -286,12 +317,6 @@
 )
 
 maven_jar(
-    name = "jsonevent-layout",
-    artifact = "net.logstash.log4j:jsonevent-layout:1.7",
-    sha1 = "507713504f0ddb75ba512f62763519c43cf46fde",
-)
-
-maven_jar(
     name = "json-smart",
     artifact = "net.minidev:json-smart:1.1.1",
     sha1 = "24a2f903d25e004de30ac602c5b47f2d4e420a59",
@@ -620,18 +645,18 @@
     sha1 = "a3ae34e57fa8a4040e28247291d0cc3d6b8c7bcf",
 )
 
-AUTO_VALUE_VERSION = "1.7"
+AUTO_VALUE_VERSION = "1.7.4"
 
 maven_jar(
     name = "auto-value",
     artifact = "com.google.auto.value:auto-value:" + AUTO_VALUE_VERSION,
-    sha1 = "fe8387764ed19460eda4f106849c664f51c07121",
+    sha1 = "6b126cb218af768339e4d6e95a9b0ae41f74e73d",
 )
 
 maven_jar(
     name = "auto-value-annotations",
     artifact = "com.google.auto.value:auto-value-annotations:" + AUTO_VALUE_VERSION,
-    sha1 = "5be124948ebdc7807df68207f35a0f23ce427f29",
+    sha1 = "eff48ed53995db2dadf0456426cc1f8700136f86",
 )
 
 declare_nongoogle_deps()
@@ -723,7 +748,7 @@
     sha1 = "f7be08ec23c21485b9b5a1cf1654c2ec8c58168d",
 )
 
-GITILES_VERS = "0.3-7"
+GITILES_VERS = "0.4"
 
 GITILES_REPO = GERRIT
 
@@ -732,14 +757,14 @@
     artifact = "com.google.gitiles:blame-cache:" + GITILES_VERS,
     attach_source = False,
     repository = GITILES_REPO,
-    sha1 = "af6212a62363906c63d367f8276ae1645f83bf93",
+    sha1 = "567198123898aa86bd854d3fcb044dc7a1845741",
 )
 
 maven_jar(
     name = "gitiles-servlet",
     artifact = "com.google.gitiles:gitiles-servlet:" + GITILES_VERS,
     repository = GITILES_REPO,
-    sha1 = "6a53f722f8572a2f1bcb7d86e5692168844bab76",
+    sha1 = "0dd832a6df108af0c75ae29b752fda64ccbd6886",
 )
 
 # prettify must match the version used in Gitiles
@@ -841,30 +866,30 @@
     sha1 = "42a25dc3219429f0e5d060061f71acb49bf010a0",
 )
 
-TRUTH_VERS = "1.0"
+TRUTH_VERS = "1.1"
 
 maven_jar(
     name = "truth",
     artifact = "com.google.truth:truth:" + TRUTH_VERS,
-    sha1 = "998e5fb3fa31df716574b4c9e8d374855e800451",
+    sha1 = "6a096a16646559c24397b03f797d0c9d75ee8720",
 )
 
 maven_jar(
     name = "truth-java8-extension",
     artifact = "com.google.truth.extensions:truth-java8-extension:" + TRUTH_VERS,
-    sha1 = "d85fbc1daf0510821f552f2aa71d9605e97aa438",
+    sha1 = "258db6eb8df61832c5c059ed2bc2e1c88683e92f",
 )
 
 maven_jar(
     name = "truth-liteproto-extension",
     artifact = "com.google.truth.extensions:truth-liteproto-extension:" + TRUTH_VERS,
-    sha1 = "7a279c50a0f93da15533cef4993b45606cf67d72",
+    sha1 = "bf65afa13aa03330e739bcaa5d795fe0f10fbf20",
 )
 
 maven_jar(
     name = "truth-proto-extension",
     artifact = "com.google.truth.extensions:truth-proto-extension:" + TRUTH_VERS,
-    sha1 = "8c0c2ea61750f02d0d5ce9c653106b6a5dc82d12",
+    sha1 = "64cba89cf87c1d84cb8c81d06f0b9c482f10b4dc",
 )
 
 maven_jar(
@@ -900,12 +925,6 @@
 )
 
 maven_jar(
-    name = "jetty-continuation",
-    artifact = "org.eclipse.jetty:jetty-continuation:" + JETTY_VERS,
-    sha1 = "09f021e5895471f622ec8f95e28f5815ea7ee192",
-)
-
-maven_jar(
     name = "jetty-http",
     artifact = "org.eclipse.jetty:jetty-http:" + JETTY_VERS,
     sha1 = "45d35131a35a1e76991682174421e8cdf765fb9f",
@@ -1144,8 +1163,8 @@
 bower_archive(
     name = "codemirror-minified",
     package = "Dominator008/codemirror-minified",
-    sha1 = "e6bda82afc7cf3493f4282c6f17265d40e1485e5",
-    version = "5.43.0",
+    sha1 = "d00f3b97345772d5a7790f206cb1e3c22e96caf6",
+    version = "5.50.2",
 )
 
 # bower test stuff
@@ -1171,9 +1190,40 @@
     version = "6.5.1",
 )
 
-# Bower component transitive dependencies.
-load("//lib/js:bower_archives.bzl", "load_bower_archives")
+load("@build_bazel_rules_nodejs//:index.bzl", "yarn_install")
 
-load_bower_archives()
+yarn_install(
+    name = "npm",
+    package_json = "//:package.json",
+    yarn_lock = "//:yarn.lock",
+)
+
+yarn_install(
+    name = "ui_npm",
+    args = ["--prod"],
+    package_json = "//:polygerrit-ui/app/package.json",
+    yarn_lock = "//:polygerrit-ui/app/yarn.lock",
+)
+
+yarn_install(
+    name = "ui_dev_npm",
+    package_json = "//:polygerrit-ui/package.json",
+    yarn_lock = "//:polygerrit-ui/yarn.lock",
+)
+
+yarn_install(
+    name = "tools_npm",
+    package_json = "//:tools/node_tools/package.json",
+    yarn_lock = "//:tools/node_tools/yarn.lock",
+)
+
+# Install all Bazel dependencies needed for npm packages that supply Bazel rules
+load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
+
+install_bazel_dependencies()
+
+load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
+
+ts_setup_workspace()
 
 external_plugin_deps()
diff --git a/contrib/mitm-ui/README.md b/contrib/mitm-ui/README.md
deleted file mode 100644
index 1ec8dd4..0000000
--- a/contrib/mitm-ui/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Scripts for PolyGerrit local development against prod using MitmProxy.
-
-## Installation (OSX)
-
-1. Install Docker from http://docker.com
-2. Start the proxy and create a new proxied browser instance
-   ```
-   cd ~/gerrit
-   ~/mitm-gerrit/mitm-serve-app-dev.sh
-   ```
-3. Make sure that the browser uses the proxy provided by the command line,
-   e.g. if you are a Googler check that the BeyondCorp extension uses the
-   "System/Alternative" proxy.
-4. Install MITM certificates
-   - Open http://mitm.it in the proxied browser window
-   - Follow the instructions to install MITM certs
-
-## Usage
-
-### Add or replace a single plugin containing static content
-
-To develop unminified plugin that loads multiple files, use this.
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-single-plugin.sh ./path/to/static/plugin.html
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. plugin.html and ./path/to/static/* will be served
-
-### Add or replace a minified plugin for *.googlesource.com
-
-This flow assumes no additional .html/.js are needed, i.e. the plugin is a single file.
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-plugins.sh ./path/to/plugin.html,./maybe/one/more.js
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. plugin.html and more.js are served
-
-### Force or replace default site theme for *.googlesource.com
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   ~/mitm-gerrit/mitm-theme.sh ./path/to/theme.html
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. Default site themes are enabled.
-4. Local `theme.html` content replaces `/static/gerrit-theme.html`
-5. `/static/*` URLs are served from local theme directory, i.e. `./path/to/`
-
-### Serve uncompiled PolyGerrit
-
-1. Create a new proxied browser window and start mitmproxy via Docker:
-   ```
-   cd ~/gerrit
-   ~/mitm-gerrit/mitm-serve-app-dev.sh
-   ```
-2. Open any *.googlesource.com domain in proxied window
-3. Instead of prod UI (gr-app.html, gr-app.js), local source files will be served
diff --git a/contrib/mitm-ui/add-header.py b/contrib/mitm-ui/add-header.py
deleted file mode 100644
index f9b2b12..0000000
--- a/contrib/mitm-ui/add-header.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# mitmdump -s add-header.py
-def response(flow):
-    if flow.request.host == 'gerrit-review.googlesource.com' and flow.request.path == "/c/92000?1":
-        #flow.response.headers['any'] = '<meta.rdf>; rel=meta'
-        flow.response.headers['Link'] = '</changes/98000/detail?O=11640c>;rel="preload";crossorigin;'
diff --git a/contrib/mitm-ui/dev-chrome.sh b/contrib/mitm-ui/dev-chrome.sh
deleted file mode 100755
index adcb296..0000000
--- a/contrib/mitm-ui/dev-chrome.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-if [[ "$OSTYPE" != "darwin"* ]]; then
-    echo Only works on OSX.
-    exit 1
-fi
-
-/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=${HOME}/devchrome --proxy-server="127.0.0.1:8888"
diff --git a/contrib/mitm-ui/force-version.py b/contrib/mitm-ui/force-version.py
deleted file mode 100644
index a69c885..0000000
--- a/contrib/mitm-ui/force-version.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# mitmdump -q -p 8888 -s "force-version.py --version $1"
-# Request URL is not changed, only the response context
-from mitmproxy import http
-import argparse
-import re
-
-class Server:
-    def __init__(self, version):
-        self.version = version
-
-    def request(self, flow: http.HTTPFlow) -> None:
-        if "gr-app." in flow.request.pretty_url:
-            flow.request.url = re.sub(
-                r"polygerrit_ui/([\d.]+)/elements",
-                "polygerrit_ui/" + self.version + "/elements",
-                flow.request.url)
-
-def start():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--version", type=str, help="Rapid release version, e.g. 432.0")
-    args = parser.parse_args()
-    return Server(args.version)
diff --git a/contrib/mitm-ui/mitm-docker.sh b/contrib/mitm-ui/mitm-docker.sh
deleted file mode 100755
index a1206f7..0000000
--- a/contrib/mitm-ui/mitm-docker.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-
-extra_volume='/tmp:/tmp'
-
-POSITIONAL=()
-while [[ $# -gt 0 ]]
-do
-key="$1"
-
-case $key in
-    -v|--volume)
-    extra_volume="$2"
-    shift # past argument
-    shift # past value
-    ;;
-    *)    # unknown option
-    POSITIONAL+=("$1") # save it in an array for later
-    shift # past argument
-    ;;
-esac
-done
-set -- "${POSITIONAL[@]}" # restore positional parameters
-
-if [[ -z "$1" ]]; then
-    echo This is a runner for higher-level scripts, e.g. mitm-serve-app-dev.sh
-    echo Alternatively, pass mitmproxy script from the same dir as a parameter, e.g. serve-app-dev.py
-    exit 1
-fi
-
-gerrit_dir=$(pwd)
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-CMD="${mitm_dir}/$1"
-
-docker run --rm -it \
-       -v ~/.mitmproxy:/home/mitmproxy/.mitmproxy \
-       -v ${mitm_dir}:${mitm_dir} \
-       -v ${gerrit_dir}:${gerrit_dir} \
-       -v ${gerrit_dir}/bazel-out:${gerrit_dir}/bazel-out \
-       -v ${extra_volume} \
-       -p 8888:8888 \
-       mitmproxy/mitmproxy:2.0.2 \
-       mitmdump -q -p 8888 -s "${CMD}"
diff --git a/contrib/mitm-ui/mitm-plugins.sh b/contrib/mitm-ui/mitm-plugins.sh
deleted file mode 100755
index fc542bb..0000000
--- a/contrib/mitm-ui/mitm-plugins.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script injects plugins for *.googlesource.com.
-    echo Provide plugin paths, comma-separated, as a parameter.
-    echo This script assumes files do not have dependencies, i.e. minified.
-    exit 1
-fi
-
-realpath() {
-    [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
-}
-
-join () {
-  local IFS="$1"
-  shift
-  echo "$*"
-}
-
-plugins=$1
-plugin_paths=()
-for plugin in $(echo ${plugins} | sed "s/,/ /g")
-do
-    plugin_paths+=($(realpath ${plugin}))
-done
-
-absolute_plugin_paths=$(join , "${plugin_paths[@]}")
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-${mitm_dir}/dev-chrome.sh &
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/mitm-docker.sh \
-           "serve-app-dev.py \
-           --plugins ${absolute_plugin_paths} \
-           --strip_assets \
-           --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-serve-app-dev.sh b/contrib/mitm-ui/mitm-serve-app-dev.sh
deleted file mode 100755
index d4c72cc..0000000
--- a/contrib/mitm-ui/mitm-serve-app-dev.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-workspace="./WORKSPACE"
-if [[ ! -f ${workspace} ]] || [[ ! $(head -n 1 ${workspace}) == *"gerrit"* ]]; then
-    echo Please change to cloned Gerrit repo from https://gerrit.googlesource.com/gerrit/
-    exit 1
-fi
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/dev-chrome.sh &
-
-${mitm_dir}/mitm-docker.sh "serve-app-dev.py --app $(pwd)/polygerrit-ui/app/ --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-single-plugin.sh b/contrib/mitm-ui/mitm-single-plugin.sh
deleted file mode 100755
index 8958229..0000000
--- a/contrib/mitm-ui/mitm-single-plugin.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script serves one plugin with the rest of static content.
-    echo Provide path to index plugin file, e.g. buildbucket.html for buildbucket plugin
-    exit 1
-fi
-
-realpath() {
-  OURPWD=$PWD
-  cd "$(dirname "$1")"
-  LINK=$(basename "$1")
-  while [ -L "$LINK" ]; do
-      LINK=$(readlink "$LINK")
-      cd "$(dirname "$LINK")"
-      LINK="$(basename "$1")"
-  done
-  REAL_DIR=`pwd -P`
-  RESULT=$REAL_DIR/$LINK
-  cd "$OURPWD"
-  echo "$RESULT"
-}
-
-plugin=$(realpath $1)
-plugin_root=$(dirname ${plugin})
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-${mitm_dir}/dev-chrome.sh &
-
-bazel build //polygerrit-ui/app:test_components &
-
-${mitm_dir}/mitm-docker.sh -v ${plugin_root}:${plugin_root} \
-           "serve-app-dev.py \
-           --plugins ${plugin} \
-           --strip_assets \
-           --plugin_root ${plugin_root}  \
-           --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/mitm-theme.sh b/contrib/mitm-ui/mitm-theme.sh
deleted file mode 100755
index 9290235..0000000
--- a/contrib/mitm-ui/mitm-theme.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-
-if [[ -z "$1" ]]; then
-    echo This script forces or replaces default site theme on *.googlesource.com
-    echo Provide path to the theme.html as a parameter.
-    exit 1
-fi
-
-realpath() {
-  OURPWD=$PWD
-  cd "$(dirname "$1")"
-  LINK=$(basename "$1")
-  while [ -L "$LINK" ]; do
-      LINK=$(readlink "$LINK")
-      cd "$(dirname "$LINK")"
-      LINK="$(basename "$1")"
-  done
-  REAL_DIR=`pwd -P`
-  RESULT=$REAL_DIR/$LINK
-  cd "$OURPWD"
-  echo "$RESULT"
-}
-
-theme=$(realpath "$1")
-theme_dir=$(dirname "${theme}")
-
-mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-
-"${mitm_dir}"/dev-chrome.sh &
-
-"${mitm_dir}"/mitm-docker.sh -v "${theme_dir}":"${theme_dir}" "serve-app-dev.py --strip_assets --theme \"${theme}\""
diff --git a/contrib/mitm-ui/serve-app-dev.py b/contrib/mitm-ui/serve-app-dev.py
deleted file mode 100644
index cdf7bfc..0000000
--- a/contrib/mitm-ui/serve-app-dev.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# 1. install and setup mitmproxy v2.0.2: https://mitmproxy.readthedocs.io/en/v2.0.2/install.html
-#   (In case of python versions trouble, use https://www.anaconda.com/)
-# 2. mitmdump -q -s -p 8888 \
-#   "serve-app-dev.py --app /path/to/polygerrit-ui/app/"
-# 3. start Chrome with --proxy-server="127.0.0.1:8888" --user-data-dir=/tmp/devchrome
-# 4. open, say, gerrit-review.googlesource.com. Or chromium-review.googlesource.com. Any.
-# 5. uncompiled source files are served and you can log in, too.
-# 6. enjoy!
-#
-# P.S. For replacing plugins, use --plugins or --plugin_root
-#
-# --plugin takes comma-separated list of plugins to add or replace.
-#
-# Example: Adding a new plugin to the server response:
-# --plugins ~/gerrit-testsite/plugins/myplugin.html
-#
-# Example: Replace all matching plugins with local versions:
-# --plugins ~/gerrit-testsite/plugins/
-# Following files will be served if they exist for /plugins/tricium/static/tricium.html:
-#  ~/gerrit-testsite/plugins/tricium.html
-#  ~/gerrit-testsite/plugins/tricium/static/tricium.html
-#
-# --assets takes assets bundle.html, expecting rest of the assets files to be in the same folder
-#
-# Example:
-#  --assets ~/gerrit-testsite/assets/a3be19f.html
-#
-
-from mitmproxy import http
-from mitmproxy.script import concurrent
-import argparse
-import json
-import mimetypes
-import os.path
-import re
-import zipfile
-
-class Server:
-    def __init__(self, devpath, components, plugins, pluginroot, assets, strip_assets, theme):
-        if devpath:
-            print("Serving app from " + devpath)
-        if components:
-            print("Serving components from " + components)
-        if pluginroot:
-            print("Serving plugins from " + pluginroot)
-        if assets:
-            self.assets_root, self.assets_file = os.path.split(assets)
-            print("Assets: using " + self.assets_file + " from " + self.assets_root)
-        else:
-            self.assets_root = None
-        if plugins:
-            self.plugins = {path.split("/")[-1:][0]: path for path in map(expandpath, plugins.split(","))}
-            for filename, path in self.plugins.items():
-                print("Serving " + filename + " from " + path)
-        else:
-            self.plugins = {}
-        self.devpath = devpath
-        self.components = components
-        self.pluginroot = pluginroot
-        self.strip_assets = strip_assets
-        self.theme = theme
-
-    def readfile(self, path):
-        with open(path, 'rb') as contentfile:
-            return contentfile.read()
-
-@concurrent
-def response(flow: http.HTTPFlow) -> None:
-    if server.strip_assets:
-        assets_bundle = 'googlesource.com/polygerrit_assets'
-        assets_pos = flow.response.text.find(assets_bundle)
-        if assets_pos != -1:
-            t = flow.response.text
-            flow.response.text = t[:t.rfind('<', 0, assets_pos)] + t[t.find('>', assets_pos) + 1:]
-            return
-
-    if server.assets_root:
-        marker = 'webcomponents-lite.js"></script>'
-        pos = flow.response.text.find(marker)
-        if pos != -1:
-            pos += len(marker)
-            flow.response.text = ''.join([
-                flow.response.text[:pos],
-                '<link rel="import" href="/gerrit_assets/123.0/' + server.assets_file + '">',
-                flow.response.text[pos:]
-            ])
-
-        assets_prefix = "/gerrit_assets/123.0/"
-        if flow.request.path.startswith(assets_prefix):
-            assets_file = flow.request.path[len(assets_prefix):]
-            flow.response.content = server.readfile(server.assets_root + '/' + assets_file)
-            flow.response.status_code = 200
-            if assets_file.endswith('.js'):
-                flow.response.headers['Content-type'] = 'text/javascript'
-            return
-    m = re.match(".+polygerrit_ui/\d+\.\d+/(.+)", flow.request.path)
-    pluginmatch = re.match("^/plugins/(.+)", flow.request.path)
-    localfile = ""
-    content = ""
-    if flow.request.path == "/config/server/info":
-        config = json.loads(flow.response.content[5:].decode('utf8'))
-        if server.theme:
-            config['default_theme'] = '/static/gerrit-theme.html'
-        for filename, path in server.plugins.items():
-            pluginname = filename.split(".")[0]
-            payload = config["plugin"]["js_resource_paths" if filename.endswith(".js") else "html_resource_paths"]
-            if list(filter(lambda url: filename in url, payload)):
-                continue
-            payload.append("plugins/" + pluginname + "/static/" + filename)
-        flow.response.content = str.encode(")]}'\n" + json.dumps(config))
-    if m is not None:
-        filepath = m.groups()[0]
-        if (filepath.startswith("bower_components/")):
-            with zipfile.ZipFile(server.components + "test_components.zip") as bower_zip:
-                content = bower_zip.read(filepath)
-        localfile = server.devpath + filepath
-    elif pluginmatch is not None:
-        pluginfile = flow.request.path_components[-1]
-        if server.plugins and pluginfile in server.plugins:
-            if os.path.isfile(server.plugins[pluginfile]):
-                localfile = server.plugins[pluginfile]
-            else:
-                print("Can't find file " + server.plugins[pluginfile] + " for " + flow.request.path)
-        elif server.pluginroot:
-            pluginurl = pluginmatch.groups()[0]
-            if os.path.isfile(server.pluginroot + pluginfile):
-                localfile = server.pluginroot + pluginfile
-            elif os.path.isfile(server.pluginroot + pluginurl):
-                localfile = server.pluginroot + pluginurl
-
-    if server.theme:
-        if flow.request.path.endswith('/gerrit-theme.html'):
-            localfile = server.theme
-        else:
-            match = re.match("^/static(/[\w\.]+)$", flow.request.path)
-            if match is not None:
-                localfile = os.path.dirname(server.theme) + match.group(1)
-
-    if localfile and os.path.isfile(localfile):
-        if pluginmatch is not None:
-            print("Serving " + flow.request.path + " from " + localfile)
-        content = server.readfile(localfile)
-
-    if content:
-        flow.response.content = content
-        flow.response.status_code = 200
-        localtype = mimetypes.guess_type(localfile)
-        if localtype and localtype[0]:
-            flow.response.headers['Content-type'] = localtype[0]
-
-def expandpath(path):
-    return os.path.realpath(os.path.expanduser(path))
-
-parser = argparse.ArgumentParser()
-parser.add_argument("--app", type=str, default="", help="Path to /polygerrit-ui/app/")
-parser.add_argument("--components", type=str, default="", help="Path to test_components.zip")
-parser.add_argument("--plugins", type=str, default="", help="Comma-separated list of plugin files to add/replace")
-parser.add_argument("--plugin_root", type=str, default="", help="Path containing individual plugin files to replace")
-parser.add_argument("--assets", type=str, default="", help="Path containing assets file to import.")
-parser.add_argument("--strip_assets", action="store_true", help="Strip plugin bundles from the response.")
-parser.add_argument("--theme", default="", type=str, help="Path to the default site theme to be used.")
-args = parser.parse_args()
-server = Server(expandpath(args.app) + '/',
-                expandpath(args.components) + '/',
-                args.plugins,
-                expandpath(args.plugin_root) + '/',
-                args.assets and expandpath(args.assets),
-                args.strip_assets,
-                expandpath(args.theme))
diff --git a/contrib/mitm-ui/serve-app-locally.py b/contrib/mitm-ui/serve-app-locally.py
deleted file mode 100644
index 636c684..0000000
--- a/contrib/mitm-ui/serve-app-locally.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# bazel build polygerrit-ui/app:gr-app
-# mitmdump -s "serve-app-locally.py ~/gerrit/bazel-bin/polygerrit-ui/app"
-from mitmproxy import http
-import argparse
-import os
-import zipfile
-
-class Server:
-    def __init__(self, bundle):
-        self.bundle = bundle
-        self.bundlemtime = 0
-        self.files = {
-            'polygerrit_ui/elements/gr-app.js': '',
-            'polygerrit_ui/elements/gr-app.html': '',
-            'polygerrit_ui/styles/main.css': '',
-        }
-        self.read_files()
-
-    def read_files(self):
-        if not os.path.isfile(self.bundle):
-            print("bundle not found!")
-            return
-        mtime = os.stat(self.bundle).st_mtime
-        if mtime <= self.bundlemtime:
-            return
-        self.bundlemtime = mtime
-        with zipfile.ZipFile(self.bundle) as z:
-            for fname in self.files:
-                print('Reading new content for ' + fname)
-                with z.open(fname, 'r') as content_file:
-                    self.files[fname] = content_file.read()
-
-    def response(self, flow: http.HTTPFlow) -> None:
-        self.read_files()
-        for name in self.files:
-            if name.rsplit('/', 1)[1] in flow.request.pretty_url:
-                flow.response.content = self.files[name]
-
-def expandpath(path):
-    return os.path.expanduser(path)
-
-def start():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("bundle", type=str)
-    args = parser.parse_args()
-    return Server(expandpath(args.bundle))
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 8b7f9a0..f29cdb2 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -27,6 +27,7 @@
 import static com.google.gerrit.extensions.api.changes.SubmittedTogetherOption.NON_VISIBLE_CHANGES;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static com.google.gerrit.server.project.ProjectCache.illegalState;
 import static com.google.gerrit.server.project.testing.TestLabels.label;
 import static com.google.gerrit.server.project.testing.TestLabels.value;
 import static java.nio.charset.StandardCharsets.UTF_8;
@@ -43,6 +44,7 @@
 import com.google.common.jimfs.Jimfs;
 import com.google.common.primitives.Chars;
 import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
+import com.google.gerrit.acceptance.PushOneCommit.Result;
 import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
 import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
 import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
@@ -65,6 +67,7 @@
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.api.changes.RevisionApi;
 import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
@@ -105,6 +108,7 @@
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.gerrit.server.config.GerritInstanceId;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.gerrit.server.config.SitePaths;
@@ -198,7 +202,13 @@
 
 @RunWith(ConfigSuite.class)
 public abstract class AbstractDaemonTest {
+
+  /**
+   * Test methods without special annotations will use a common server for efficiency reasons. The
+   * server is torn down after the test class is done.
+   */
   private static GerritServer commonServer;
+
   private static Description firstTest;
 
   @ClassRule public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -236,6 +246,7 @@
   @Inject @CanonicalWebUrl protected Provider<String> canonicalWebUrl;
   @Inject @GerritPersonIdent protected Provider<PersonIdent> serverIdent;
   @Inject @GerritServerConfig protected Config cfg;
+  @Inject @GerritInstanceId @Nullable protected String instanceId;
   @Inject protected AcceptanceTestRequestScope atrScope;
   @Inject protected AccountCache accountCache;
   @Inject protected AccountCreator accountCreator;
@@ -386,8 +397,7 @@
     initSsh();
   }
 
-  protected void evictAndReindexAccount(Account.Id accountId) {
-    accountCache.evict(accountId);
+  protected void reindexAccount(Account.Id accountId) {
     accountIndexer.index(accountId);
   }
 
@@ -448,8 +458,8 @@
     user = accountCreator.user();
 
     // Evict and reindex accounts in case tests modify them.
-    evictAndReindexAccount(admin.id());
-    evictAndReindexAccount(user.id());
+    reindexAccount(admin.id());
+    reindexAccount(user.id());
 
     adminRestSession = new RestSession(server, admin);
     userRestSession = new RestSession(server, user);
@@ -704,6 +714,14 @@
     return result;
   }
 
+  protected PushOneCommit.Result createChange(TestRepository<InMemoryRepository> repo)
+      throws Exception {
+    PushOneCommit push = pushFactory.create(admin.newIdent(), repo);
+    PushOneCommit.Result result = push.to("refs/for/master");
+    result.assertOkStatus();
+    return result;
+  }
+
   protected PushOneCommit.Result createMergeCommitChange(String ref) throws Exception {
     return createMergeCommitChange(ref, "foo");
   }
@@ -847,6 +865,10 @@
     return gApi.changes().id(id).info();
   }
 
+  protected ChangeApi change(Result r) throws RestApiException {
+    return gApi.changes().id(r.getChange().getId().get());
+  }
+
   protected Optional<EditInfo> getEdit(String id) throws RestApiException {
     return gApi.changes().id(id).edit().get();
   }
@@ -1207,9 +1229,8 @@
       GroupReference groupReference,
       String ref,
       boolean exclusive,
-      String... permissionNames)
-      throws IOException {
-    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
+      String... permissionNames) {
+    ProjectConfig cfg = projectCache.get(project).orElseThrow(illegalState(project)).getConfig();
     AccessSection accessSection = cfg.getAccessSection(ref);
     assertThat(accessSection).isNotNull();
     for (String permissionName : permissionNames) {
@@ -1294,7 +1315,7 @@
   }
 
   protected void assertNotifyTo(String expectedEmail, String expectedFullname) {
-    Address expectedAddress = new Address(expectedFullname, expectedEmail);
+    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
     assertThat(m.rcpt()).containsExactly(expectedAddress);
@@ -1304,11 +1325,11 @@
   }
 
   protected void assertNotifyCc(TestAccount expected) {
-    assertNotifyCc(expected.getEmailAddress());
+    assertNotifyCc(expected.getNameEmail());
   }
 
   protected void assertNotifyCc(String expectedEmail, String expectedFullname) {
-    Address expectedAddress = new Address(expectedFullname, expectedEmail);
+    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
     assertNotifyCc(expectedAddress);
   }
 
@@ -1324,7 +1345,7 @@
   protected void assertNotifyBcc(TestAccount expected) {
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
-    assertThat(m.rcpt()).containsExactly(expected.getEmailAddress());
+    assertThat(m.rcpt()).containsExactly(expected.getNameEmail());
     assertThat(m.headers().get("To").isEmpty()).isTrue();
     assertThat(m.headers().get("Cc").isEmpty()).isTrue();
   }
@@ -1332,7 +1353,7 @@
   protected void assertNotifyBcc(String expectedEmail, String expectedFullName) {
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
-    assertThat(m.rcpt()).containsExactly(new Address(expectedFullName, expectedEmail));
+    assertThat(m.rcpt()).containsExactly(Address.create(expectedFullName, expectedEmail));
     assertThat(m.headers().get("To").isEmpty()).isTrue();
     assertThat(m.headers().get("Cc").isEmpty()).isTrue();
   }
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index a372089..bb3901e 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -126,7 +126,7 @@
       recipients.put(
           BCC,
           message.rcpt().stream()
-              .map(Address::getEmail)
+              .map(Address::email)
               .filter(e -> !recipients.get(TO).contains(e) && !recipients.get(CC).contains(e))
               .collect(toList()));
       this.users = users;
@@ -174,7 +174,7 @@
       }
       Truth.assertThat(header).isInstanceOf(AddressList.class);
       AddressList addrList = (AddressList) header;
-      return addrList.getAddressList().stream().map(Address::getEmail).collect(toList());
+      return addrList.getAddressList().stream().map(Address::email).collect(toList());
     }
 
     public FakeEmailSenderSubject to(String... emails) {
@@ -339,8 +339,8 @@
       return description.getClassName();
     }
 
-    private TestAccount evictAndCopy(TestAccount account) {
-      evictAndReindexAccount(account.id());
+    private TestAccount reindexAndCopy(TestAccount account) {
+      reindexAccount(account.id());
       return account;
     }
 
@@ -348,14 +348,14 @@
       synchronized (stagedUsers) {
         if (stagedUsers.containsKey(usersCacheKey())) {
           StagedUsers existing = stagedUsers.get(usersCacheKey());
-          owner = evictAndCopy(existing.owner);
-          author = evictAndCopy(existing.author);
-          uploader = evictAndCopy(existing.uploader);
-          reviewer = evictAndCopy(existing.reviewer);
-          ccer = evictAndCopy(existing.ccer);
-          starrer = evictAndCopy(existing.starrer);
-          assignee = evictAndCopy(existing.assignee);
-          watchingProjectOwner = evictAndCopy(existing.watchingProjectOwner);
+          owner = reindexAndCopy(existing.owner);
+          author = reindexAndCopy(existing.author);
+          uploader = reindexAndCopy(existing.uploader);
+          reviewer = reindexAndCopy(existing.reviewer);
+          ccer = reindexAndCopy(existing.ccer);
+          starrer = reindexAndCopy(existing.starrer);
+          assignee = reindexAndCopy(existing.assignee);
+          watchingProjectOwner = reindexAndCopy(existing.watchingProjectOwner);
           watchers.putAll(existing.watchers);
           return;
         }
@@ -407,14 +407,14 @@
 
     public TestAccount testAccount(String name) throws Exception {
       String username = name(name);
-      TestAccount account = accountCreator.create(username, email(username), name);
+      TestAccount account = accountCreator.create(username, email(username), name, null);
       accountsByEmail.put(account.email(), account);
       return account;
     }
 
     public TestAccount testAccount(String name, String groupName) throws Exception {
       String username = name(name);
-      TestAccount account = accountCreator.create(username, email(username), name, groupName);
+      TestAccount account = accountCreator.create(username, email(username), name, null, groupName);
       accountsByEmail.put(account.email(), account);
       return account;
     }
diff --git a/java/com/google/gerrit/acceptance/AbstractPredicateTest.java b/java/com/google/gerrit/acceptance/AbstractPredicateTest.java
new file mode 100644
index 0000000..c9fd3fb
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/AbstractPredicateTest.java
@@ -0,0 +1,104 @@
+// Copyright (C) 2021 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.
+
+package com.google.gerrit.acceptance;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.common.PluginDefinedInfo;
+import com.google.gerrit.index.query.Predicate;
+import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.json.OutputFormat;
+import com.google.gerrit.server.DynamicOptions;
+import com.google.gerrit.server.change.ChangeAttributeFactory;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.ChangeQueryBuilder;
+import com.google.gerrit.server.restapi.change.QueryChanges;
+import com.google.gerrit.sshd.commands.Query;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import java.util.Collections;
+import java.util.List;
+import org.kohsuke.args4j.Option;
+
+public abstract class AbstractPredicateTest extends AbstractDaemonTest {
+  public static final String PLUGIN_NAME = "my-plugin";
+  public static final Gson GSON = OutputFormat.JSON.newGson();
+
+  public static class MyInfo extends PluginDefinedInfo {
+    public String message;
+  }
+
+  protected static class PluginModule extends AbstractModule {
+    @Override
+    public void configure() {
+      bind(DynamicOptions.DynamicBean.class)
+          .annotatedWith(Exports.named(Query.class))
+          .to(MyQueryOptions.class);
+      bind(DynamicOptions.DynamicBean.class)
+          .annotatedWith(Exports.named(QueryChanges.class))
+          .to(MyQueryOptions.class);
+      bind(ChangeAttributeFactory.class)
+          .annotatedWith(Exports.named("sample"))
+          .to(AttributeFactory.class);
+    }
+  }
+
+  public static class MyQueryOptions implements DynamicOptions.DynamicBean {
+    @Option(name = "--sample")
+    public boolean sample;
+  }
+
+  protected static class AttributeFactory implements ChangeAttributeFactory {
+    private final Provider<ChangeQueryBuilder> queryBuilderProvider;
+
+    @Inject
+    AttributeFactory(Provider<ChangeQueryBuilder> queryBuilderProvider) {
+      this.queryBuilderProvider = queryBuilderProvider;
+    }
+
+    @Override
+    public PluginDefinedInfo create(
+        ChangeData cd, DynamicOptions.BeanProvider beanProvider, String plugin) {
+      MyQueryOptions options = (MyQueryOptions) beanProvider.getDynamicBean(plugin);
+      MyInfo myInfo = new MyInfo();
+      if (options.sample) {
+        try {
+          Predicate<ChangeData> predicate = queryBuilderProvider.get().parse("label:Code-Review+2");
+          if (predicate.isMatchable() && predicate.asMatchable().match(cd)) {
+            myInfo.message = "matched";
+          } else {
+            myInfo.message = "not matched";
+          }
+        } catch (QueryParseException e) {
+          // ignored
+        }
+      }
+      return myInfo;
+    }
+  }
+
+  protected static List<MyInfo> decodeRawPluginsList(@Nullable Object plugins) {
+    if (plugins == null) {
+      return Collections.emptyList();
+    }
+    checkArgument(plugins instanceof List, "not a list: %s", plugins);
+    return GSON.fromJson(GSON.toJson(plugins), new TypeToken<List<MyInfo>>() {}.getType());
+  }
+}
diff --git a/java/com/google/gerrit/acceptance/AccountCreator.java b/java/com/google/gerrit/acceptance/AccountCreator.java
index 75d0d2f..44e2d2d 100644
--- a/java/com/google/gerrit/acceptance/AccountCreator.java
+++ b/java/com/google/gerrit/acceptance/AccountCreator.java
@@ -69,6 +69,7 @@
       @Nullable String username,
       @Nullable String email,
       @Nullable String fullName,
+      @Nullable String displayName,
       String... groupNames)
       throws Exception {
 
@@ -94,7 +95,11 @@
         .insert(
             "Create Test Account",
             id,
-            u -> u.setFullName(fullName).setPreferredEmail(email).addExternalIds(extIds));
+            u ->
+                u.setFullName(fullName)
+                    .setDisplayName(displayName)
+                    .setPreferredEmail(email)
+                    .addExternalIds(extIds));
 
     if (groupNames != null) {
       for (String n : groupNames) {
@@ -107,7 +112,7 @@
       }
     }
 
-    account = TestAccount.create(id, username, email, fullName, httpPass);
+    account = TestAccount.create(id, username, email, fullName, displayName, httpPass);
     if (username != null) {
       accounts.put(username, account);
     }
@@ -115,7 +120,7 @@
   }
 
   public TestAccount create(@Nullable String username, String group) throws Exception {
-    return create(username, null, username, group);
+    return create(username, null, username, null, group);
   }
 
   public TestAccount create() throws Exception {
@@ -123,23 +128,23 @@
   }
 
   public TestAccount create(@Nullable String username) throws Exception {
-    return create(username, null, username, (String[]) null);
+    return create(username, null, username, null, (String[]) null);
   }
 
   public TestAccount admin() throws Exception {
-    return create("admin", "admin@example.com", "Administrator", "Administrators");
+    return create("admin", "admin@example.com", "Administrator", "Adminny", "Administrators");
   }
 
   public TestAccount admin2() throws Exception {
-    return create("admin2", "admin2@example.com", "Administrator2", "Administrators");
+    return create("admin2", "admin2@example.com", "Administrator2", null, "Administrators");
   }
 
   public TestAccount user() throws Exception {
-    return create("user", "user@example.com", "User");
+    return create("user", "user@example.com", "User", null);
   }
 
   public TestAccount user2() throws Exception {
-    return create("user2", "user2@example.com", "User2");
+    return create("user2", "user2@example.com", "User2", null);
   }
 
   public TestAccount get(String username) {
diff --git a/java/com/google/gerrit/acceptance/BUILD b/java/com/google/gerrit/acceptance/BUILD
index 646d8f0..9d8bc57 100644
--- a/java/com/google/gerrit/acceptance/BUILD
+++ b/java/com/google/gerrit/acceptance/BUILD
@@ -1,5 +1,4 @@
 load("@rules_java//java:defs.bzl", "java_binary", "java_library")
-load("//tools/bzl:java.bzl", "java_library2")
 load("//tools/bzl:javadoc.bzl", "java_doc")
 
 FUNCTION_SRCS = [
@@ -40,6 +39,7 @@
     "//lib:gson",
     "//lib:guava-retrying",
     "//lib:jgit",
+    "//lib:jgit-ssh-jsch",
     "//lib:jsch",
     "//lib/commons:compress",
     "//lib/commons:lang",
@@ -61,7 +61,9 @@
     "//java/com/google/gerrit/pgm/http/jetty",
     "//java/com/google/gerrit/pgm/util",
     "//java/com/google/gerrit/truth",
+    "//java/com/google/gerrit/acceptance/config",
     "//java/com/google/gerrit/acceptance/testsuite/project",
+    "//java/com/google/gerrit/server/fixes/testing",
     "//java/com/google/gerrit/server/group/testing",
     "//java/com/google/gerrit/server/project/testing:project-test-util",
     "//java/com/google/gerrit/testing:gerrit-test-util",
@@ -105,28 +107,30 @@
     runtime_deps = DEPLOY_ENV + PGM_DEPLOY_ENV,
 )
 
-java_library2(
+exported_deps = [
+    ":function",
+    "//lib:jgit-junit",
+    "//lib:jimfs",
+    "//lib:servlet-api",
+    "//lib/httpcomponents:fluent-hc",
+    "//lib/httpcomponents:httpclient",
+    "//lib/httpcomponents:httpcore",
+    "//lib/mockito",
+    "//lib/truth",
+    "//lib/truth:truth-java8-extension",
+    "//lib/greenmail",
+] + TEST_DEPS
+
+java_library(
     name = "framework-lib",
     testonly = True,
     srcs = glob(
         ["**/*.java"],
         exclude = FUNCTION_SRCS,
     ),
-    exported_deps = [
-        ":function",
-        "//lib:jgit-junit",
-        "//lib:jimfs",
-        "//lib:servlet-api",
-        "//lib/httpcomponents:fluent-hc",
-        "//lib/httpcomponents:httpclient",
-        "//lib/httpcomponents:httpcore",
-        "//lib/mockito",
-        "//lib/truth",
-        "//lib/truth:truth-java8-extension",
-        "//lib/greenmail",
-    ] + TEST_DEPS,
     visibility = ["//visibility:public"],
-    deps = DEPLOY_ENV,
+    exports = exported_deps,
+    deps = DEPLOY_ENV + exported_deps,
 )
 
 java_library(
diff --git a/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java b/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
deleted file mode 100644
index 0a1d765..0000000
--- a/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) 2013 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.
-
-package com.google.gerrit.acceptance;
-
-import com.google.auto.value.AutoAnnotation;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import org.eclipse.jgit.lib.Config;
-
-class ConfigAnnotationParser {
-  private static Splitter splitter = Splitter.on(".").trimResults();
-
-  static Config parse(Config base, GerritConfigs annotation) {
-    if (annotation == null) {
-      return null;
-    }
-
-    Config cfg = new Config(base);
-    for (GerritConfig c : annotation.value()) {
-      parseAnnotation(cfg, c);
-    }
-    return cfg;
-  }
-
-  static Config parse(Config base, GerritConfig annotation) {
-    Config cfg = new Config(base);
-    parseAnnotation(cfg, annotation);
-    return cfg;
-  }
-
-  private static GerritConfig toGerritConfig(GlobalPluginConfig annotation) {
-    return newGerritConfig(annotation.name(), annotation.value(), annotation.values());
-  }
-
-  @AutoAnnotation
-  private static GerritConfig newGerritConfig(String name, String value, String[] values) {
-    return new AutoAnnotation_ConfigAnnotationParser_newGerritConfig(name, value, values);
-  }
-
-  static Map<String, Config> parse(GlobalPluginConfig annotation) {
-    if (annotation == null) {
-      return null;
-    }
-    Map<String, Config> result = new HashMap<>();
-    Config cfg = new Config();
-    parseAnnotation(cfg, toGerritConfig(annotation));
-    result.put(annotation.pluginName(), cfg);
-    return result;
-  }
-
-  static Map<String, Config> parse(GlobalPluginConfigs annotation) {
-    if (annotation == null || annotation.value().length < 1) {
-      return null;
-    }
-
-    HashMap<String, Config> result = new HashMap<>();
-
-    for (GlobalPluginConfig c : annotation.value()) {
-      String pluginName = c.pluginName();
-      Config config;
-      if (result.containsKey(pluginName)) {
-        config = result.get(pluginName);
-      } else {
-        config = new Config();
-        result.put(pluginName, config);
-      }
-      parseAnnotation(config, toGerritConfig(c));
-    }
-
-    return result;
-  }
-
-  private static void parseAnnotation(Config cfg, GerritConfig c) {
-    ArrayList<String> l = Lists.newArrayList(splitter.split(c.name()));
-    if (l.size() == 2) {
-      if (!Strings.isNullOrEmpty(c.value())) {
-        cfg.setString(l.get(0), null, l.get(1), c.value());
-      } else {
-        String[] values = c.values();
-        cfg.setStringList(l.get(0), null, l.get(1), Arrays.asList(values));
-      }
-    } else if (l.size() == 3) {
-      if (!Strings.isNullOrEmpty(c.value())) {
-        cfg.setString(l.get(0), l.get(1), l.get(2), c.value());
-      } else {
-        cfg.setStringList(l.get(0), l.get(1), l.get(2), Arrays.asList(c.values()));
-      }
-    } else {
-      throw new IllegalArgumentException(
-          "GerritConfig.name must be of the format section.subsection.name or section.name");
-    }
-  }
-}
diff --git a/java/com/google/gerrit/acceptance/EventRecorder.java b/java/com/google/gerrit/acceptance/EventRecorder.java
index cab6b58..1618573 100644
--- a/java/com/google/gerrit/acceptance/EventRecorder.java
+++ b/java/com/google/gerrit/acceptance/EventRecorder.java
@@ -40,7 +40,7 @@
 
 public class EventRecorder {
   private final RegistrationHandle eventListenerRegistration;
-  private final ListMultimap<String, RefEvent> recordedEvents;
+  private final ListMultimap<String, Event> recordedEvents;
 
   @Singleton
   public static class Factory {
@@ -70,15 +70,17 @@
               @Override
               public void onEvent(Event e) {
                 if (e instanceof ReviewerDeletedEvent) {
-                  recordedEvents.put(ReviewerDeletedEvent.TYPE, (ReviewerDeletedEvent) e);
+                  recordedEvents.put(ReviewerDeletedEvent.TYPE, e);
                 } else if (e instanceof ChangeDeletedEvent) {
-                  recordedEvents.put(ChangeDeletedEvent.TYPE, (ChangeDeletedEvent) e);
+                  recordedEvents.put(ChangeDeletedEvent.TYPE, e);
                 } else if (e instanceof RefEvent) {
                   RefEvent event = (RefEvent) e;
                   String key =
                       refEventKey(
                           event.getType(), event.getProjectNameKey().get(), event.getRefName());
                   recordedEvents.put(key, event);
+                } else {
+                  recordedEvents.put(e.type, e);
                 }
               }
 
@@ -158,6 +160,17 @@
     return events;
   }
 
+  public ImmutableList<Event> getGenericEvents(String type, int expectedSize) {
+    if (expectedSize == 0) {
+      assertThat(recordedEvents).doesNotContainKey(type);
+      return ImmutableList.of();
+    }
+    assertThat(recordedEvents).containsKey(type);
+    ImmutableList<Event> events = FluentIterable.from(recordedEvents.get(type)).toList();
+    assertThat(events).hasSize(expectedSize);
+    return events;
+  }
+
   public void assertNoRefUpdatedEvents(String project, String branch) throws Exception {
     getRefUpdatedEvents(project, branch, 0);
   }
diff --git a/java/com/google/gerrit/acceptance/ExtensionRegistry.java b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
index eaf03b3..cfe7964 100644
--- a/java/com/google/gerrit/acceptance/ExtensionRegistry.java
+++ b/java/com/google/gerrit/acceptance/ExtensionRegistry.java
@@ -15,7 +15,9 @@
 package com.google.gerrit.acceptance;
 
 import com.google.gerrit.extensions.api.changes.ActionVisitor;
+import com.google.gerrit.extensions.config.CapabilityDefinition;
 import com.google.gerrit.extensions.config.DownloadScheme;
+import com.google.gerrit.extensions.config.PluginProjectPermissionDefinition;
 import com.google.gerrit.extensions.events.AccountActivationListener;
 import com.google.gerrit.extensions.events.AccountIndexedListener;
 import com.google.gerrit.extensions.events.ChangeIndexedListener;
@@ -24,6 +26,7 @@
 import com.google.gerrit.extensions.events.GroupIndexedListener;
 import com.google.gerrit.extensions.events.ProjectIndexedListener;
 import com.google.gerrit.extensions.events.RevisionCreatedListener;
+import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
@@ -47,6 +50,8 @@
 import java.util.List;
 
 public class ExtensionRegistry {
+  public static final String PLUGIN_NAME = "myPlugin";
+
   private final DynamicSet<AccountIndexedListener> accountIndexedListeners;
   private final DynamicSet<ChangeIndexedListener> changeIndexedListeners;
   private final DynamicSet<GroupIndexedListener> groupIndexedListeners;
@@ -71,6 +76,9 @@
       accountActivationValidationListeners;
   private final DynamicSet<AccountActivationListener> accountActivationListeners;
   private final DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners;
+  private final DynamicSet<WorkInProgressStateChangedListener> workInProgressStateChangedListeners;
+  private final DynamicMap<CapabilityDefinition> capabilityDefinitions;
+  private final DynamicMap<PluginProjectPermissionDefinition> pluginProjectPermissionDefinitions;
 
   @Inject
   ExtensionRegistry(
@@ -96,7 +104,10 @@
       DynamicSet<GroupBackend> groupBackends,
       DynamicSet<AccountActivationValidationListener> accountActivationValidationListeners,
       DynamicSet<AccountActivationListener> accountActivationListeners,
-      DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners) {
+      DynamicSet<OnSubmitValidationListener> onSubmitValidationListeners,
+      DynamicSet<WorkInProgressStateChangedListener> workInProgressStateChangedListeners,
+      DynamicMap<CapabilityDefinition> capabilityDefinitions,
+      DynamicMap<PluginProjectPermissionDefinition> pluginProjectPermissionDefinitions) {
     this.accountIndexedListeners = accountIndexedListeners;
     this.changeIndexedListeners = changeIndexedListeners;
     this.groupIndexedListeners = groupIndexedListeners;
@@ -120,6 +131,9 @@
     this.accountActivationValidationListeners = accountActivationValidationListeners;
     this.accountActivationListeners = accountActivationListeners;
     this.onSubmitValidationListeners = onSubmitValidationListeners;
+    this.workInProgressStateChangedListeners = workInProgressStateChangedListeners;
+    this.capabilityDefinitions = capabilityDefinitions;
+    this.pluginProjectPermissionDefinitions = pluginProjectPermissionDefinitions;
   }
 
   public Registration newRegistration() {
@@ -227,6 +241,19 @@
       return add(onSubmitValidationListeners, onSubmitValidationListener);
     }
 
+    public Registration add(WorkInProgressStateChangedListener workInProgressStateChangedListener) {
+      return add(workInProgressStateChangedListeners, workInProgressStateChangedListener);
+    }
+
+    public Registration add(CapabilityDefinition capabilityDefinition, String exportName) {
+      return add(capabilityDefinitions, capabilityDefinition, exportName);
+    }
+
+    public Registration add(
+        PluginProjectPermissionDefinition pluginProjectPermissionDefinition, String exportName) {
+      return add(pluginProjectPermissionDefinitions, pluginProjectPermissionDefinition, exportName);
+    }
+
     private <T> Registration add(DynamicSet<T> dynamicSet, T extension) {
       return add(dynamicSet, extension, "gerrit");
     }
@@ -240,7 +267,7 @@
     private <T> Registration add(DynamicMap<T> dynamicMap, T extension, String exportName) {
       RegistrationHandle registrationHandle =
           ((PrivateInternals_DynamicMapImpl<T>) dynamicMap)
-              .put("myPlugin", exportName, Providers.of(extension));
+              .put(PLUGIN_NAME, exportName, Providers.of(extension));
       registrationHandles.add(registrationHandle);
       return this;
     }
diff --git a/java/com/google/gerrit/acceptance/GerritConfig.java b/java/com/google/gerrit/acceptance/GerritConfig.java
deleted file mode 100644
index fe0c628..0000000
--- a/java/com/google/gerrit/acceptance/GerritConfig.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2013 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.
-
-package com.google.gerrit.acceptance;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Target({METHOD})
-@Retention(RUNTIME)
-@Repeatable(GerritConfigs.class)
-public @interface GerritConfig {
-  /**
-   * Setting name in the form {@code "section.name"} or {@code "section.subsection.name"} where
-   * {@code section}, {@code subsection} and {@code name} correspond to the parameters of the same
-   * names in JGit's {@code Config#getString} method.
-   *
-   * @see org.eclipse.jgit.lib.Config#getString(String, String, String)
-   */
-  String name();
-
-  /** Single value. Takes precedence over values specified in {@code values}. */
-  String value() default "";
-
-  /** Multiple values (list). Ignored if {@code value} is specified. */
-  String[] values() default "";
-}
diff --git a/java/com/google/gerrit/acceptance/GerritConfigs.java b/java/com/google/gerrit/acceptance/GerritConfigs.java
deleted file mode 100644
index e0f9d4a..0000000
--- a/java/com/google/gerrit/acceptance/GerritConfigs.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2013 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.
-
-package com.google.gerrit.acceptance;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Target({METHOD})
-@Retention(RUNTIME)
-public @interface GerritConfigs {
-  GerritConfig[] value();
-}
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 4066a10..986f549 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -23,6 +23,11 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.config.ConfigAnnotationParser;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.acceptance.config.GerritConfigs;
+import com.google.gerrit.acceptance.config.GlobalPluginConfig;
+import com.google.gerrit.acceptance.config.GlobalPluginConfigs;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
 import com.google.gerrit.acceptance.testsuite.account.AccountOperationsImpl;
 import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
@@ -492,8 +497,8 @@
     cfg.setInt("sshd", null, "commandStartThreads", 1);
     cfg.setInt("receive", null, "threadPoolSize", 1);
     cfg.setInt("index", null, "threads", 1);
-    if (cfg.getString("index", null, "reindexAfterRefUpdate") == null) {
-      cfg.setBoolean("index", null, "reindexAfterRefUpdate", false);
+    if (cfg.getString("index", null, "mergeabilityComputationBehavior") == null) {
+      cfg.setString("index", null, "mergeabilityComputationBehavior", "NEVER");
     }
   }
 
diff --git a/java/com/google/gerrit/acceptance/GlobalPluginConfig.java b/java/com/google/gerrit/acceptance/GlobalPluginConfig.java
deleted file mode 100644
index 43477ae..0000000
--- a/java/com/google/gerrit/acceptance/GlobalPluginConfig.java
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2017 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.
-
-package com.google.gerrit.acceptance;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Repeatable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Target({METHOD})
-@Retention(RUNTIME)
-@Repeatable(GlobalPluginConfigs.class)
-public @interface GlobalPluginConfig {
-  /** Name of the plugin, corresponding to {@code $site/etc/@pluginName.config}. */
-  String pluginName();
-
-  /** @see GerritConfig#name() */
-  String name();
-
-  /** @see GerritConfig#value() */
-  String value() default "";
-
-  /** @see GerritConfig#values() */
-  String[] values() default "";
-}
diff --git a/java/com/google/gerrit/acceptance/GlobalPluginConfigs.java b/java/com/google/gerrit/acceptance/GlobalPluginConfigs.java
deleted file mode 100644
index dfcf955..0000000
--- a/java/com/google/gerrit/acceptance/GlobalPluginConfigs.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2017 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.
-
-package com.google.gerrit.acceptance;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Target({METHOD})
-@Retention(RUNTIME)
-public @interface GlobalPluginConfigs {
-  GlobalPluginConfig[] value();
-}
diff --git a/java/com/google/gerrit/acceptance/InProcessProtocol.java b/java/com/google/gerrit/acceptance/InProcessProtocol.java
index 75e5a2e..83c63f9 100644
--- a/java/com/google/gerrit/acceptance/InProcessProtocol.java
+++ b/java/com/google/gerrit/acceptance/InProcessProtocol.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.acceptance;
 
 import static com.google.gerrit.server.git.receive.LazyPostReceiveHookChain.affectsSize;
+import static com.google.gerrit.server.project.ProjectCache.illegalState;
 import static com.google.gerrit.server.quota.QuotaGroupDefinitions.REPOSITORY_SIZE_GROUP;
 
 import com.google.common.collect.ImmutableList;
@@ -241,15 +242,8 @@
         throw new RuntimeException(e);
       }
 
-      ProjectState projectState;
-      try {
-        projectState = projectCache.checkedGet(req.project);
-      } catch (IOException e) {
-        throw new RuntimeException(e);
-      }
-      if (projectState == null) {
-        throw new RuntimeException("can't load project state for " + req.project.get());
-      }
+      ProjectState projectState =
+          projectCache.get(req.project).orElseThrow(illegalState(req.project));
       Repository permissionAwareRepository = PermissionAwareRepositoryManager.wrap(repo, perm);
       UploadPack up = new UploadPack(permissionAwareRepository);
       up.setPackConfig(transferConfig.getPackConfig());
@@ -320,10 +314,11 @@
       }
       try {
         IdentifiedUser identifiedUser = userProvider.get().asIdentifiedUser();
-        ProjectState projectState = projectCache.checkedGet(req.project);
-        if (projectState == null) {
-          throw new RuntimeException(String.format("project %s not found", req.project));
-        }
+        ProjectState projectState =
+            projectCache
+                .get(req.project)
+                .orElseThrow(
+                    () -> new RuntimeException(String.format("project %s not found", req.project)));
 
         AsyncReceiveCommits arc = factory.create(projectState, identifiedUser, db, null);
         if (arc.canUpload() != Capable.OK) {
diff --git a/java/com/google/gerrit/acceptance/ProjectResetter.java b/java/com/google/gerrit/acceptance/ProjectResetter.java
index a528974..d885303 100644
--- a/java/com/google/gerrit/acceptance/ProjectResetter.java
+++ b/java/com/google/gerrit/acceptance/ProjectResetter.java
@@ -335,18 +335,18 @@
         // Make sure all accounts are evicted and reindexed.
         try (Repository repo = repoManager.openRepository(allUsersName)) {
           for (Account.Id id : accountIds(repo)) {
-            evictAndReindexAccount(id);
+            reindexAccount(id);
           }
         }
 
         // Remove deleted accounts from the cache and index.
         for (Account.Id id : deletedAccounts) {
-          evictAndReindexAccount(id);
+          reindexAccount(id);
         }
       } else {
         // Evict and reindex all modified and deleted accounts.
         for (Account.Id id : Sets.union(modifiedAccounts, deletedAccounts)) {
-          evictAndReindexAccount(id);
+          reindexAccount(id);
         }
       }
     }
@@ -367,10 +367,7 @@
     }
   }
 
-  private void evictAndReindexAccount(Account.Id accountId) {
-    if (accountCache != null) {
-      accountCache.evict(accountId);
-    }
+  private void reindexAccount(Account.Id accountId) {
     if (groupIncludeCache != null) {
       groupIncludeCache.evictGroupsWithMember(accountId);
     }
diff --git a/java/com/google/gerrit/acceptance/RestSession.java b/java/com/google/gerrit/acceptance/RestSession.java
index 0e7ad4b..7ee1b26 100644
--- a/java/com/google/gerrit/acceptance/RestSession.java
+++ b/java/com/google/gerrit/acceptance/RestSession.java
@@ -14,13 +14,14 @@
 
 package com.google.gerrit.acceptance;
 
+import static com.google.common.net.HttpHeaders.ACCEPT;
+import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
+import static com.google.gerrit.json.OutputFormat.JSON_COMPACT;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.net.HttpHeaders;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.restapi.RawInput;
-import com.google.gerrit.json.OutputFormat;
 import java.io.IOException;
 import org.apache.http.Header;
 import org.apache.http.client.fluent.Request;
@@ -40,7 +41,7 @@
   }
 
   public RestResponse getJsonAccept(String endPoint) throws IOException {
-    return getWithHeader(endPoint, new BasicHeader(HttpHeaders.ACCEPT, "application/json"));
+    return getWithHeader(endPoint, new BasicHeader(ACCEPT, "application/json"));
   }
 
   public RestResponse getWithHeader(String endPoint, Header header) throws IOException {
@@ -74,8 +75,7 @@
       put.addHeader(header);
     }
     if (content != null) {
-      put.addHeader(new BasicHeader("Content-Type", "application/json"));
-      put.body(new StringEntity(OutputFormat.JSON_COMPACT.newGson().toJson(content), UTF_8));
+      addContentToRequest(put, content);
     }
     return execute(put);
   }
@@ -83,7 +83,7 @@
   public RestResponse putRaw(String endPoint, RawInput stream) throws IOException {
     requireNonNull(stream);
     Request put = Request.Put(getUrl(endPoint));
-    put.addHeader(new BasicHeader("Content-Type", stream.getContentType()));
+    put.addHeader(new BasicHeader(CONTENT_TYPE, stream.getContentType()));
     put.body(
         new BufferedHttpEntity(
             new InputStreamEntity(stream.getInputStream(), stream.getContentLength())));
@@ -105,12 +105,16 @@
       post.addHeader(header);
     }
     if (content != null) {
-      post.addHeader(new BasicHeader("Content-Type", "application/json"));
-      post.body(new StringEntity(OutputFormat.JSON_COMPACT.newGson().toJson(content), UTF_8));
+      addContentToRequest(post, content);
     }
     return execute(post);
   }
 
+  private static void addContentToRequest(Request request, Object content) {
+    request.addHeader(new BasicHeader(CONTENT_TYPE, "application/json"));
+    request.body(new StringEntity(JSON_COMPACT.newGson().toJson(content), UTF_8));
+  }
+
   public RestResponse delete(String endPoint) throws IOException {
     return execute(Request.Delete(getUrl(endPoint)));
   }
diff --git a/java/com/google/gerrit/acceptance/SshSession.java b/java/com/google/gerrit/acceptance/SshSession.java
index fd60d16..6698657 100644
--- a/java/com/google/gerrit/acceptance/SshSession.java
+++ b/java/com/google/gerrit/acceptance/SshSession.java
@@ -47,11 +47,10 @@
   }
 
   @SuppressWarnings("resource")
-  public String exec(String command, InputStream opt) throws Exception {
+  public String exec(String command) throws Exception {
     ChannelExec channel = (ChannelExec) getSession().openChannel("exec");
     try {
       channel.setCommand(command);
-      channel.setInputStream(opt);
       InputStream in = channel.getInputStream();
       InputStream err = channel.getErrStream();
       channel.connect();
@@ -82,19 +81,6 @@
     }
   }
 
-  public InputStream exec2(String command, InputStream opt) throws Exception {
-    ChannelExec channel = (ChannelExec) getSession().openChannel("exec");
-    channel.setCommand(command);
-    channel.setInputStream(opt);
-    InputStream in = channel.getInputStream();
-    channel.connect();
-    return in;
-  }
-
-  public String exec(String command) throws Exception {
-    return exec(command, null);
-  }
-
   private boolean hasError() {
     return error != null;
   }
diff --git a/java/com/google/gerrit/acceptance/TestAccount.java b/java/com/google/gerrit/acceptance/TestAccount.java
index 07bb739..a7a4a89 100644
--- a/java/com/google/gerrit/acceptance/TestAccount.java
+++ b/java/com/google/gerrit/acceptance/TestAccount.java
@@ -47,8 +47,9 @@
       @Nullable String username,
       @Nullable String email,
       @Nullable String fullName,
+      @Nullable String displayName,
       @Nullable String httpPassword) {
-    return new AutoValue_TestAccount(id, username, email, fullName, httpPassword);
+    return new AutoValue_TestAccount(id, username, email, fullName, displayName, httpPassword);
   }
 
   public abstract Account.Id id();
@@ -63,6 +64,9 @@
   public abstract String fullName();
 
   @Nullable
+  public abstract String displayName();
+
+  @Nullable
   public abstract String httpPassword();
 
   public PersonIdent newIdent() {
@@ -79,7 +83,7 @@
         .toString();
   }
 
-  public Address getEmailAddress() {
+  public Address getNameEmail() {
     // Address is weird enough that it's safer and clearer to create a new instance in a
     // non-abstract method rather than, say, having an abstract emailAddress() as part of this
     // AutoValue class. Specifically:
@@ -88,6 +92,6 @@
     //    emailAddress().
     //  * Address#equals only considers email, not name, whereas TestAccount#equals should include
     //    name.
-    return new Address(fullName(), email());
+    return Address.create(fullName(), email());
   }
 }
diff --git a/java/com/google/gerrit/acceptance/UseLocalDisk.java b/java/com/google/gerrit/acceptance/UseLocalDisk.java
index e177bb4..192caa0 100644
--- a/java/com/google/gerrit/acceptance/UseLocalDisk.java
+++ b/java/com/google/gerrit/acceptance/UseLocalDisk.java
@@ -21,6 +21,15 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
+/**
+ * Annotation to mark tests that require a local disk for the execution.
+ *
+ * <p>Tests that do not have this annotation are executed in memory.
+ *
+ * <p>Using this annotation makes the execution of the test more expensive/slower. This is why it
+ * should only be used if the test requires a local disk (e.g. if the test triggers the Git garbage
+ * collection functionality which only works with a local disk).
+ */
 @Target({TYPE, METHOD})
 @Retention(RUNTIME)
 public @interface UseLocalDisk {}
diff --git a/java/com/google/gerrit/acceptance/UseSsh.java b/java/com/google/gerrit/acceptance/UseSsh.java
index 5509140..12a9977 100644
--- a/java/com/google/gerrit/acceptance/UseSsh.java
+++ b/java/com/google/gerrit/acceptance/UseSsh.java
@@ -21,6 +21,14 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
+/**
+ * Annotation to mark SSH tests.
+ *
+ * <p>When running tests the SSH functionality is disabled unless the {@link UseSsh} annotation is
+ * used.
+ *
+ * <p>SSH tests can be skipped when executing tests (see {@link com.google.gerrit.testing.SshMode}).
+ */
 @Target({TYPE, METHOD})
 @Retention(RUNTIME)
 public @interface UseSsh {}
diff --git a/java/com/google/gerrit/acceptance/config/BUILD b/java/com/google/gerrit/acceptance/config/BUILD
new file mode 100644
index 0000000..a8ccc1f
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/BUILD
@@ -0,0 +1,15 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+package(default_testonly = 1)
+
+java_library(
+    name = "config",
+    srcs = glob(["*.java"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        "//lib:guava",
+        "//lib:jgit",
+        "//lib/auto:auto-value",
+        "//lib/auto:auto-value-annotations",
+    ],
+)
diff --git a/java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java b/java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java
new file mode 100644
index 0000000..24a2117
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/ConfigAnnotationParser.java
@@ -0,0 +1,110 @@
+// Copyright (C) 2013 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.
+
+package com.google.gerrit.acceptance.config;
+
+import com.google.auto.value.AutoAnnotation;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.jgit.lib.Config;
+
+public class ConfigAnnotationParser {
+  private static Splitter splitter = Splitter.on(".").trimResults();
+
+  public static Config parse(Config base, GerritConfigs annotation) {
+    if (annotation == null) {
+      return null;
+    }
+
+    Config cfg = new Config(base);
+    for (GerritConfig c : annotation.value()) {
+      parseAnnotation(cfg, c);
+    }
+    return cfg;
+  }
+
+  public static Config parse(Config base, GerritConfig annotation) {
+    Config cfg = new Config(base);
+    parseAnnotation(cfg, annotation);
+    return cfg;
+  }
+
+  public static Map<String, Config> parse(GlobalPluginConfigs annotation) {
+    if (annotation == null || annotation.value().length < 1) {
+      return null;
+    }
+
+    HashMap<String, Config> result = new HashMap<>();
+
+    for (GlobalPluginConfig c : annotation.value()) {
+      String pluginName = c.pluginName();
+      Config config;
+      if (result.containsKey(pluginName)) {
+        config = result.get(pluginName);
+      } else {
+        config = new Config();
+        result.put(pluginName, config);
+      }
+      parseAnnotation(config, toGerritConfig(c));
+    }
+
+    return result;
+  }
+
+  public static Map<String, Config> parse(GlobalPluginConfig annotation) {
+    if (annotation == null) {
+      return null;
+    }
+    Map<String, Config> result = new HashMap<>();
+    Config cfg = new Config();
+    parseAnnotation(cfg, toGerritConfig(annotation));
+    result.put(annotation.pluginName(), cfg);
+    return result;
+  }
+
+  private static GerritConfig toGerritConfig(GlobalPluginConfig annotation) {
+    return newGerritConfig(annotation.name(), annotation.value(), annotation.values());
+  }
+
+  @AutoAnnotation
+  private static GerritConfig newGerritConfig(String name, String value, String[] values) {
+    return new AutoAnnotation_ConfigAnnotationParser_newGerritConfig(name, value, values);
+  }
+
+  private static void parseAnnotation(Config cfg, GerritConfig c) {
+    ArrayList<String> l = Lists.newArrayList(splitter.split(c.name()));
+    if (l.size() == 2) {
+      if (!Strings.isNullOrEmpty(c.value())) {
+        cfg.setString(l.get(0), null, l.get(1), c.value());
+      } else {
+        String[] values = c.values();
+        cfg.setStringList(l.get(0), null, l.get(1), Arrays.asList(values));
+      }
+    } else if (l.size() == 3) {
+      if (!Strings.isNullOrEmpty(c.value())) {
+        cfg.setString(l.get(0), l.get(1), l.get(2), c.value());
+      } else {
+        cfg.setStringList(l.get(0), l.get(1), l.get(2), Arrays.asList(c.values()));
+      }
+    } else {
+      throw new IllegalArgumentException(
+          "GerritConfig.name must be of the format section.subsection.name or section.name");
+    }
+  }
+}
diff --git a/java/com/google/gerrit/acceptance/config/GerritConfig.java b/java/com/google/gerrit/acceptance/config/GerritConfig.java
new file mode 100644
index 0000000..26be2d4
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/GerritConfig.java
@@ -0,0 +1,42 @@
+// Copyright (C) 2013 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.
+
+package com.google.gerrit.acceptance.config;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+@Repeatable(GerritConfigs.class)
+public @interface GerritConfig {
+  /**
+   * Setting name in the form {@code "section.name"} or {@code "section.subsection.name"} where
+   * {@code section}, {@code subsection} and {@code name} correspond to the parameters of the same
+   * names in JGit's {@code Config#getString} method.
+   *
+   * @see org.eclipse.jgit.lib.Config#getString(String, String, String)
+   */
+  String name();
+
+  /** Single value. Takes precedence over values specified in {@code values}. */
+  String value() default "";
+
+  /** Multiple values (list). Ignored if {@code value} is specified. */
+  String[] values() default "";
+}
diff --git a/java/com/google/gerrit/acceptance/config/GerritConfigs.java b/java/com/google/gerrit/acceptance/config/GerritConfigs.java
new file mode 100644
index 0000000..0127ace
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/GerritConfigs.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2013 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.
+
+package com.google.gerrit.acceptance.config;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+public @interface GerritConfigs {
+  GerritConfig[] value();
+}
diff --git a/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
new file mode 100644
index 0000000..ae88e37
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 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.
+
+package com.google.gerrit.acceptance.config;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+@Repeatable(GlobalPluginConfigs.class)
+public @interface GlobalPluginConfig {
+  /** Name of the plugin, corresponding to {@code $site/etc/@pluginName.config}. */
+  String pluginName();
+
+  /** @see GerritConfig#name() */
+  String name();
+
+  /** @see GerritConfig#value() */
+  String value() default "";
+
+  /** @see GerritConfig#values() */
+  String[] values() default "";
+}
diff --git a/java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java b/java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java
new file mode 100644
index 0000000..e53e5ba
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/config/GlobalPluginConfigs.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2017 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.
+
+package com.google.gerrit.acceptance.config;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target({METHOD})
+@Retention(RUNTIME)
+public @interface GlobalPluginConfigs {
+  GlobalPluginConfig[] value();
+}
diff --git a/java/com/google/gerrit/acceptance/rest/PluginCollection.java b/java/com/google/gerrit/acceptance/rest/PluginCollection.java
index c0daf93..dc40cde 100644
--- a/java/com/google/gerrit/acceptance/rest/PluginCollection.java
+++ b/java/com/google/gerrit/acceptance/rest/PluginCollection.java
@@ -45,7 +45,7 @@
   @Override
   public PluginResource parse(ConfigResource parent, IdString id)
       throws ResourceNotFoundException, Exception {
-    throw new ResourceNotFoundException();
+    throw new ResourceNotFoundException(id);
   }
 
   @Override
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperations.java b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperations.java
index efae223..cca0a45 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperations.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperations.java
@@ -95,5 +95,25 @@
      * @return a builder to update the account
      */
     TestAccountUpdate.Builder forUpdate();
+
+    /**
+     * Starts the fluent chain to invalidate an account. The returned builder can be used to specify
+     * how the account should be made invalid. To invalidate the account for real, {@link
+     * TestAccountInvalidation.Builder#invalidate()} must be called.
+     *
+     * <p>Example:
+     *
+     * <pre>
+     * accountOperations.forInvalidation()
+     *     .preferredEmailWithoutExternalId("foo.bar@example.com")
+     *     .invalidate();
+     * </pre>
+     *
+     * <p><strong>Note:</strong> The invalidation will fail with an exception if the account to
+     * invalidate doesn't exist.
+     *
+     * @return a builder to invalidate the account
+     */
+    TestAccountInvalidation.Builder forInvalidation();
   }
 }
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
index f1b840a..f64d7a2 100644
--- a/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/account/AccountOperationsImpl.java
@@ -168,5 +168,23 @@
       accountUpdate.status().ifPresent(builder::setStatus);
       accountUpdate.active().ifPresent(builder::setActive);
     }
+
+    @Override
+    public TestAccountInvalidation.Builder forInvalidation() {
+      return TestAccountInvalidation.builder(this::invalidateAccount);
+    }
+
+    private void invalidateAccount(TestAccountInvalidation testAccountInvalidation)
+        throws Exception {
+      Optional<AccountState> accountState = getAccountState(accountId);
+      checkState(accountState.isPresent(), "Tried to invalidate a non-existing test account");
+
+      if (testAccountInvalidation.preferredEmailWithoutExternalId().isPresent()) {
+        updateAccount(
+            (account, updateBuilder) ->
+                updateBuilder.setPreferredEmail(
+                    testAccountInvalidation.preferredEmailWithoutExternalId().get()));
+      }
+    }
   }
 }
diff --git a/java/com/google/gerrit/acceptance/testsuite/account/TestAccountInvalidation.java b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountInvalidation.java
new file mode 100644
index 0000000..6816f3b
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/account/TestAccountInvalidation.java
@@ -0,0 +1,58 @@
+// 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.
+
+package com.google.gerrit.acceptance.testsuite.account;
+
+import com.google.auto.value.AutoValue;
+import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
+import java.util.Optional;
+
+/**
+ * API to invalidate accounts in tests.
+ *
+ * <p>This allows to test Gerrit behavior when there is invalid account data in NoteDb (e.g.
+ * accounts with duplicate emails).
+ */
+@AutoValue
+public abstract class TestAccountInvalidation {
+  /**
+   * Sets a preferred email for the account for which the account doesn't have an external ID.
+   *
+   * <p>This allows to set the same preferred email for multiple accounts so that the email becomes
+   * ambiguous.
+   */
+  public abstract Optional<String> preferredEmailWithoutExternalId();
+
+  abstract ThrowingConsumer<TestAccountInvalidation> accountInvalidator();
+
+  public static Builder builder(ThrowingConsumer<TestAccountInvalidation> accountInvalidator) {
+    return new AutoValue_TestAccountInvalidation.Builder().accountInvalidator(accountInvalidator);
+  }
+
+  @AutoValue.Builder
+  public abstract static class Builder {
+    public abstract Builder preferredEmailWithoutExternalId(String preferredEmail);
+
+    abstract Builder accountInvalidator(
+        ThrowingConsumer<TestAccountInvalidation> accountInvalidator);
+
+    abstract TestAccountInvalidation autoBuild();
+
+    /** Executes the account invalidation as specified. */
+    public void invalidate() {
+      TestAccountInvalidation accountInvalidation = autoBuild();
+      accountInvalidation.accountInvalidator().acceptAndThrowSilently(accountInvalidation);
+    }
+  }
+}
diff --git a/java/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImpl.java
index fd5c003..21d1232 100644
--- a/java/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/group/GroupOperationsImpl.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.exceptions.NoSuchGroupException;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.ServerInitiated;
-import com.google.gerrit.server.account.GroupUUID;
+import com.google.gerrit.server.account.GroupUuid;
 import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.group.db.Groups;
 import com.google.gerrit.server.group.db.GroupsUpdate;
@@ -80,7 +80,7 @@
   private InternalGroupCreation toInternalGroupCreation(TestGroupCreation groupCreation) {
     AccountGroup.Id groupId = AccountGroup.id(seq.nextGroupId());
     String groupName = groupCreation.name().orElse("group-with-id-" + groupId.get());
-    AccountGroup.UUID groupUuid = GroupUUID.make(groupName, serverIdent);
+    AccountGroup.UUID groupUuid = GroupUuid.make(groupName, serverIdent);
     AccountGroup.NameKey nameKey = AccountGroup.nameKey(groupName);
     return InternalGroupCreation.builder()
         .setId(groupId)
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/BUILD b/java/com/google/gerrit/acceptance/testsuite/project/BUILD
index 8a3a23a..f9e2fb5 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/BUILD
+++ b/java/com/google/gerrit/acceptance/testsuite/project/BUILD
@@ -14,6 +14,7 @@
         "//java/com/google/gerrit/server",
         "//lib:guava",
         "//lib:jgit",
+        "//lib:jgit-junit",
         "//lib/auto:auto-value",
         "//lib/auto:auto-value-annotations",
         "//lib/commons:lang",
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
index 2db611b..738be4d 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperations.java
@@ -73,5 +73,25 @@
      * @return a builder to update the check.
      */
     TestProjectUpdate.Builder forUpdate();
+
+    /**
+     * Starts the fluent chain to invalidate a project. The returned builder can be used to specify
+     * how the project should be made invalid. To invalidate the project for real, {@link
+     * TestProjectInvalidation.Builder#invalidate()} must be called.
+     *
+     * <p>Example:
+     *
+     * <pre>
+     * projectOperations.forInvalidation()
+     *     .addProjectConfigUpdater(cfg -> cfg.setString("invalidSection", null, "foo", "bar"))
+     *     .invalidate();
+     * </pre>
+     *
+     * <p><strong>Note:</strong> The invalidation will fail with an exception if the project to
+     * invalidate doesn't exist.
+     *
+     * @return a builder to invalidate the project
+     */
+    TestProjectInvalidation.Builder forInvalidation();
   }
 }
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
index 62a560b..b0f46e9 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/ProjectOperationsImpl.java
@@ -19,6 +19,7 @@
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.acceptance.testsuite.project.TestProjectCreation.Builder;
@@ -45,6 +46,7 @@
 import java.util.Collections;
 import org.apache.commons.lang.RandomStringUtils;
 import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectLoader;
@@ -89,11 +91,12 @@
 
     CreateProjectArgs args = new CreateProjectArgs();
     args.setProjectName(name);
+    args.permissionsOnly = projectCreation.permissionOnly().orElse(false);
     args.branch = Collections.singletonList(Constants.R_HEADS + Constants.MASTER);
     args.createEmptyCommit = projectCreation.createEmptyCommit().orElse(true);
     projectCreation.parent().ifPresent(p -> args.newParent = p);
     // ProjectCreator wants non-null owner IDs.
-    args.ownerIds = new ArrayList<>();
+    args.ownerIds = new ArrayList<>(projectCreation.owners());
     projectCreation.submitType().ifPresent(st -> args.submitType = st);
     projectCreator.createProject(args);
     return Project.nameKey(name);
@@ -258,6 +261,71 @@
         throw new IllegalStateException(e);
       }
     }
+
+    private void setConfig(Config projectConfig) {
+      try (TestRepository<Repository> repo =
+          new TestRepository<>(repoManager.openRepository(nameKey))) {
+        repo.update(
+            RefNames.REFS_CONFIG,
+            repo.commit()
+                .message("Update project.config from test")
+                .parent(getHead(RefNames.REFS_CONFIG))
+                .add(ProjectConfig.PROJECT_CONFIG, projectConfig.toText()));
+      } catch (Exception e) {
+        throw new IllegalStateException(
+            "updating project.config of project " + nameKey + " failed", e);
+      }
+    }
+
+    @Override
+    public TestProjectInvalidation.Builder forInvalidation() {
+      return TestProjectInvalidation.builder(this::invalidateProject);
+    }
+
+    private void invalidateProject(TestProjectInvalidation testProjectInvalidation)
+        throws Exception {
+      if (testProjectInvalidation.makeProjectConfigInvalid()) {
+        Config projectConfig = new Config();
+        projectConfig.fromText(getConfig().toText());
+
+        // Make the project config invalid by adding a permission entry with an invalid permission
+        // name.
+        projectConfig.setString(
+            "access", "refs/*", "Invalid Permission Name", "group Administrators");
+
+        setConfig(projectConfig);
+        try {
+          projectCache.evict(nameKey);
+        } catch (Exception e) {
+          // Evicting the project from the cache, also triggers a reindex of the project.
+          // The reindex step fails if the project config is invalid. That's fine, since it was our
+          // intention to make the project config invalid. Hence we ignore exceptions that are cause
+          // by an invalid project config here.
+          if (!Throwables.getCausalChain(e).stream()
+              .anyMatch(ConfigInvalidException.class::isInstance)) {
+            throw e;
+          }
+        }
+      }
+      if (!testProjectInvalidation.projectConfigUpdater().isEmpty()) {
+        Config projectConfig = new Config();
+        projectConfig.fromText(getConfig().toText());
+        testProjectInvalidation.projectConfigUpdater().forEach(c -> c.accept(projectConfig));
+        setConfig(projectConfig);
+        try {
+          projectCache.evict(nameKey);
+        } catch (Exception e) {
+          // Evicting the project from the cache, also triggers a reindex of the project.
+          // The reindex step fails if the project config is invalid. That's fine, since it was our
+          // intention to make the project config invalid. Hence we ignore exceptions that are cause
+          // by an invalid project config here.
+          if (!Throwables.getCausalChain(e).stream()
+              .anyMatch(ConfigInvalidException.class::isInstance)) {
+            throw e;
+          }
+        }
+      }
+    }
   }
 
   private static PermissionRule newRule(ProjectConfig project, AccountGroup.UUID groupUUID) {
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
index 99e045c..3bbb8db 100644
--- a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
+++ b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectCreation.java
@@ -14,8 +14,12 @@
 
 package com.google.gerrit.acceptance.testsuite.project;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
+import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.extensions.client.SubmitType;
 import java.util.Optional;
@@ -29,8 +33,12 @@
 
   public abstract Optional<Boolean> createEmptyCommit();
 
+  public abstract Optional<Boolean> permissionOnly();
+
   public abstract Optional<SubmitType> submitType();
 
+  public abstract ImmutableSet<AccountGroup.UUID> owners();
+
   abstract ThrowingFunction<TestProjectCreation, Project.NameKey> projectCreator();
 
   public static Builder builder(
@@ -48,11 +56,20 @@
 
     public abstract TestProjectCreation.Builder createEmptyCommit(boolean value);
 
+    public abstract TestProjectCreation.Builder permissionOnly(boolean value);
+
     /** Skips the empty commit on creation. This means that project's branches will not exist. */
     public TestProjectCreation.Builder noEmptyCommit() {
       return createEmptyCommit(false);
     }
 
+    public TestProjectCreation.Builder addOwner(AccountGroup.UUID owner) {
+      ownersBuilder().add(requireNonNull(owner, "owner"));
+      return this;
+    }
+
+    abstract ImmutableSet.Builder<AccountGroup.UUID> ownersBuilder();
+
     abstract TestProjectCreation.Builder projectCreator(
         ThrowingFunction<TestProjectCreation, Project.NameKey> projectCreator);
 
diff --git a/java/com/google/gerrit/acceptance/testsuite/project/TestProjectInvalidation.java b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectInvalidation.java
new file mode 100644
index 0000000..d4bd912
--- /dev/null
+++ b/java/com/google/gerrit/acceptance/testsuite/project/TestProjectInvalidation.java
@@ -0,0 +1,79 @@
+// 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.
+
+package com.google.gerrit.acceptance.testsuite.project;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.acceptance.testsuite.ThrowingConsumer;
+import java.util.function.Consumer;
+import org.eclipse.jgit.lib.Config;
+
+/**
+ * API to invalidate projects in tests.
+ *
+ * <p>This allows to test Gerrit behavior when there is invalid project data in NoteDb (e.g. an
+ * invalid {@code project.config} file).
+ */
+@AutoValue
+public abstract class TestProjectInvalidation {
+  public abstract boolean makeProjectConfigInvalid();
+
+  public abstract ImmutableList<Consumer<Config>> projectConfigUpdater();
+
+  abstract ThrowingConsumer<TestProjectInvalidation> projectInvalidator();
+
+  public static Builder builder(ThrowingConsumer<TestProjectInvalidation> projectInvalidator) {
+    return new AutoValue_TestProjectInvalidation.Builder()
+        .projectInvalidator(projectInvalidator)
+        .makeProjectConfigInvalid(false);
+  }
+
+  @AutoValue.Builder
+  public abstract static class Builder {
+    /**
+     * Updates the project.config file so that it becomes invalid and loading it within Gerrit fails
+     * with {@link org.eclipse.jgit.errors.ConfigInvalidException}.
+     */
+    public Builder makeProjectConfigInvalid() {
+      makeProjectConfigInvalid(true);
+      return this;
+    }
+
+    protected abstract Builder makeProjectConfigInvalid(boolean makeProjectConfigInvalid);
+
+    /**
+     * Adds a consumer that can update the project config.
+     *
+     * <p>This allows tests to set arbitrary values in the project config.
+     */
+    public Builder addProjectConfigUpdater(Consumer<Config> projectConfigUpdater) {
+      projectConfigUpdaterBuilder().add(projectConfigUpdater);
+      return this;
+    }
+
+    protected abstract ImmutableList.Builder<Consumer<Config>> projectConfigUpdaterBuilder();
+
+    abstract Builder projectInvalidator(
+        ThrowingConsumer<TestProjectInvalidation> projectInvalidator);
+
+    abstract TestProjectInvalidation autoBuild();
+
+    /** Executes the project invalidation as specified. */
+    public void invalidate() {
+      TestProjectInvalidation projectInvalidation = autoBuild();
+      projectInvalidation.projectInvalidator().acceptAndThrowSilently(projectInvalidation);
+    }
+  }
+}
diff --git a/java/com/google/gerrit/common/data/CommentDetail.java b/java/com/google/gerrit/common/data/CommentDetail.java
index d69f0bb..55e0143 100644
--- a/java/com/google/gerrit/common/data/CommentDetail.java
+++ b/java/com/google/gerrit/common/data/CommentDetail.java
@@ -18,10 +18,7 @@
 import com.google.gerrit.entities.Comment;
 import com.google.gerrit.entities.PatchSet;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 public class CommentDetail {
   protected List<Comment> a;
@@ -29,8 +26,6 @@
 
   private transient PatchSet.Id idA;
   private transient PatchSet.Id idB;
-  private transient Map<Integer, List<Comment>> forA;
-  private transient Map<Integer, List<Comment>> forB;
 
   public CommentDetail(PatchSet.Id idA, PatchSet.Id idB) {
     this.a = new ArrayList<>();
@@ -67,88 +62,4 @@
   public boolean isEmpty() {
     return a.isEmpty() && b.isEmpty();
   }
-
-  public List<Comment> getForA(int lineNbr) {
-    if (forA == null) {
-      forA = index(a);
-    }
-    return get(forA, lineNbr);
-  }
-
-  public List<Comment> getForB(int lineNbr) {
-    if (forB == null) {
-      forB = index(b);
-    }
-    return get(forB, lineNbr);
-  }
-
-  private static List<Comment> get(Map<Integer, List<Comment>> m, int i) {
-    List<Comment> r = m.get(i);
-    return r != null ? orderComments(r) : Collections.emptyList();
-  }
-
-  /**
-   * Order the comments based on their parent_uuid parent. It is possible to do this by iterating
-   * over the list only once but it's probably overkill since the number of comments on a given line
-   * will be small most of the time.
-   *
-   * @param comments The list of comments for a given line.
-   * @return The comments sorted as they should appear in the UI
-   */
-  private static List<Comment> orderComments(List<Comment> comments) {
-    // Map of comments keyed by their parent. The values are lists of comments since it is
-    // possible for several comments to have the same parent (this can happen if two reviewers
-    // click Reply on the same comment at the same time). Such comments will be displayed under
-    // their correct parent in chronological order.
-    Map<String, List<Comment>> parentMap = new HashMap<>();
-
-    // It's possible to have more than one root comment if two reviewers create a comment on the
-    // same line at the same time
-    List<Comment> rootComments = new ArrayList<>();
-
-    // Store all the comments in parentMap, keyed by their parent
-    for (Comment c : comments) {
-      String parentUuid = c.parentUuid;
-      List<Comment> l = parentMap.get(parentUuid);
-      if (l == null) {
-        l = new ArrayList<>();
-        parentMap.put(parentUuid, l);
-      }
-      l.add(c);
-      if (parentUuid == null) {
-        rootComments.add(c);
-      }
-    }
-
-    // Add the comments in the list, starting with the head and then going through all the
-    // comments that have it as a parent, and so on
-    List<Comment> result = new ArrayList<>();
-    addChildren(parentMap, rootComments, result);
-
-    return result;
-  }
-
-  /** Add the comments to {@code outResult}, depth first */
-  private static void addChildren(
-      Map<String, List<Comment>> parentMap, List<Comment> children, List<Comment> outResult) {
-    if (children != null) {
-      for (Comment c : children) {
-        outResult.add(c);
-        addChildren(parentMap, parentMap.get(c.key.uuid), outResult);
-      }
-    }
-  }
-
-  private Map<Integer, List<Comment>> index(List<Comment> in) {
-    HashMap<Integer, List<Comment>> r = new HashMap<>();
-    for (Comment p : in) {
-      List<Comment> l = r.get(p.lineNbr);
-      if (l == null) {
-        l = new ArrayList<>();
-        r.put(p.lineNbr, l);
-      }
-      l.add(p);
-    }
-    return r;
-  }
 }
diff --git a/java/com/google/gerrit/common/data/GarbageCollectionResult.java b/java/com/google/gerrit/common/data/GarbageCollectionResult.java
index 5ed0158..5e3601e 100644
--- a/java/com/google/gerrit/common/data/GarbageCollectionResult.java
+++ b/java/com/google/gerrit/common/data/GarbageCollectionResult.java
@@ -18,6 +18,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+/** A list of errors occurred during GC. */
 public class GarbageCollectionResult {
   protected List<Error> errors;
 
diff --git a/java/com/google/gerrit/common/data/GlobalCapability.java b/java/com/google/gerrit/common/data/GlobalCapability.java
index fbe1deb..10a66cc 100644
--- a/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -20,7 +20,12 @@
 import java.util.Collections;
 import java.util.List;
 
-/** Server wide capabilities. Represented as {@link Permission} objects. */
+/**
+ * Server wide capabilities. Represented as {@link Permission} objects.
+ *
+ * <p>Contrary to {@link Permission}, global capabilities do not need a resource to check
+ * permissions on.
+ */
 public class GlobalCapability {
   /** Ability to view code review metadata refs in repositories. */
   public static final String ACCESS_DATABASE = "accessDatabase";
diff --git a/java/com/google/gerrit/common/data/LabelType.java b/java/com/google/gerrit/common/data/LabelType.java
index 90b0930..3a68414 100644
--- a/java/com/google/gerrit/common/data/LabelType.java
+++ b/java/com/google/gerrit/common/data/LabelType.java
@@ -14,14 +14,17 @@
 
 package com.google.gerrit.common.data;
 
+import static com.google.common.collect.ImmutableList.toImmutableList;
 import static java.util.Comparator.comparing;
 import static java.util.stream.Collectors.collectingAndThen;
 import static java.util.stream.Collectors.toList;
 
+import com.google.common.collect.ImmutableList;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.LabelId;
 import com.google.gerrit.entities.PatchSetApproval;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -37,6 +40,7 @@
   public static final boolean DEF_COPY_ANY_SCORE = false;
   public static final boolean DEF_COPY_MAX_SCORE = false;
   public static final boolean DEF_COPY_MIN_SCORE = false;
+  public static final ImmutableList<Short> DEF_COPY_VALUES = ImmutableList.of();
   public static final boolean DEF_IGNORE_SELF_APPROVAL = false;
 
   public static LabelType withDefaultValues(String name) {
@@ -104,6 +108,7 @@
   protected boolean copyAllScoresOnTrivialRebase;
   protected boolean copyAllScoresIfNoCodeChange;
   protected boolean copyAllScoresIfNoChange;
+  protected ImmutableList<Short> copyValues;
   protected boolean allowPostSubmit;
   protected boolean ignoreSelfApproval;
   protected short defaultValue;
@@ -144,6 +149,7 @@
     setCopyAnyScore(DEF_COPY_ANY_SCORE);
     setCopyMaxScore(DEF_COPY_MAX_SCORE);
     setCopyMinScore(DEF_COPY_MIN_SCORE);
+    setCopyValues(DEF_COPY_VALUES);
     setAllowPostSubmit(DEF_ALLOW_POST_SUBMIT);
     setIgnoreSelfApproval(DEF_IGNORE_SELF_APPROVAL);
 
@@ -157,6 +163,10 @@
     return name;
   }
 
+  public void setName(String name) {
+    this.name = checkName(name);
+  }
+
   public boolean matches(PatchSetApproval psa) {
     return psa.labelId().get().equalsIgnoreCase(name);
   }
@@ -173,6 +183,7 @@
     return canOverride;
   }
 
+  @Nullable
   public List<String> getRefPatterns() {
     return refPatterns;
   }
@@ -198,7 +209,7 @@
   }
 
   public void setRefPatterns(List<String> refPatterns) {
-    if (refPatterns != null) {
+    if (refPatterns != null && !refPatterns.isEmpty()) {
       this.refPatterns =
           refPatterns.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
     } else {
@@ -210,6 +221,10 @@
     return values;
   }
 
+  public void setValues(List<LabelValue> values) {
+    this.values = sortValues(values);
+  }
+
   public LabelValue getMin() {
     if (values.isEmpty()) {
       return null;
@@ -289,6 +304,14 @@
     this.copyAllScoresIfNoChange = copyAllScoresIfNoChange;
   }
 
+  public ImmutableList<Short> getCopyValues() {
+    return copyValues;
+  }
+
+  public void setCopyValues(Collection<Short> copyValues) {
+    this.copyValues = copyValues.stream().sorted().collect(toImmutableList());
+  }
+
   public boolean isMaxNegative(PatchSetApproval ca) {
     return maxNegative == ca.value();
   }
diff --git a/java/com/google/gerrit/common/data/PatchScript.java b/java/com/google/gerrit/common/data/PatchScript.java
index c177e35..e3c0ba6 100644
--- a/java/com/google/gerrit/common/data/PatchScript.java
+++ b/java/com/google/gerrit/common/data/PatchScript.java
@@ -14,8 +14,8 @@
 
 package com.google.gerrit.common.data;
 
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Patch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.entities.Patch.ChangeType;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
@@ -37,102 +37,73 @@
     GITLINK
   }
 
-  private Change.Key changeId;
-  private ChangeType changeType;
-  private String oldName;
-  private String newName;
-  private FileMode oldMode;
-  private FileMode newMode;
-  private List<String> header;
-  private DiffPreferencesInfo diffPrefs;
-  private SparseFileContent a;
-  private SparseFileContent b;
-  private List<Edit> edits;
-  private Set<Edit> editsDueToRebase;
-  private DisplayMethod displayMethodA;
-  private DisplayMethod displayMethodB;
-  private transient String mimeTypeA;
-  private transient String mimeTypeB;
-  private CommentDetail comments;
-  private List<Patch> history;
-  private boolean hugeFile;
-  private boolean intralineFailure;
-  private boolean intralineTimeout;
-  private boolean binary;
-  private transient String commitIdA;
-  private transient String commitIdB;
+  public static class PatchScriptFileInfo {
+    public final String name;
+    public final FileMode mode;
+    public final SparseFileContent content;
+    public final DisplayMethod displayMethod;
+    public final String mimeType;
+    public final String commitId;
+
+    PatchScriptFileInfo(
+        String name,
+        FileMode mode,
+        SparseFileContent content,
+        DisplayMethod displayMethod,
+        String mimeType,
+        String commitId) {
+      this.name = name;
+      this.mode = mode;
+      this.content = content;
+      this.displayMethod = displayMethod;
+      this.mimeType = mimeType;
+      this.commitId = commitId;
+    }
+  }
+
+  private final ChangeType changeType;
+  private final ImmutableList<String> header;
+  private final DiffPreferencesInfo diffPrefs;
+  private final ImmutableList<Edit> edits;
+  private final ImmutableSet<Edit> editsDueToRebase;
+  private final boolean intralineFailure;
+  private final boolean intralineTimeout;
+  private final boolean binary;
+  private final PatchScriptFileInfo fileInfoA;
+  private final PatchScriptFileInfo fileInfoB;
 
   public PatchScript(
-      Change.Key ck,
       ChangeType ct,
       String on,
       String nn,
       FileMode om,
       FileMode nm,
-      List<String> h,
+      ImmutableList<String> h,
       DiffPreferencesInfo dp,
       SparseFileContent ca,
       SparseFileContent cb,
-      List<Edit> e,
-      Set<Edit> editsDueToRebase,
+      ImmutableList<Edit> e,
+      ImmutableSet<Edit> editsDueToRebase,
       DisplayMethod ma,
       DisplayMethod mb,
       String mta,
       String mtb,
-      CommentDetail cd,
-      List<Patch> hist,
-      boolean hf,
       boolean idf,
       boolean idt,
       boolean bin,
       String cma,
       String cmb) {
-    changeId = ck;
     changeType = ct;
-    oldName = on;
-    newName = nn;
-    oldMode = om;
-    newMode = nm;
     header = h;
     diffPrefs = dp;
-    a = ca;
-    b = cb;
     edits = e;
     this.editsDueToRebase = editsDueToRebase;
-    displayMethodA = ma;
-    displayMethodB = mb;
-    mimeTypeA = mta;
-    mimeTypeB = mtb;
-    comments = cd;
-    history = hist;
-    hugeFile = hf;
     intralineFailure = idf;
     intralineTimeout = idt;
     binary = bin;
-    commitIdA = cma;
-    commitIdB = cmb;
-  }
 
-  protected PatchScript() {}
-
-  public Change.Key getChangeId() {
-    return changeId;
-  }
-
-  public DisplayMethod getDisplayMethodA() {
-    return displayMethodA;
-  }
-
-  public DisplayMethod getDisplayMethodB() {
-    return displayMethodB;
-  }
-
-  public FileMode getFileModeA() {
-    return oldMode;
-  }
-
-  public FileMode getFileModeB() {
-    return newMode;
+    fileInfoA = new PatchScriptFileInfo(on, om, ca, ma, mta, cma);
+    fileInfoB = new PatchScriptFileInfo(nn, nm, cb, mb, mtb, cmb);
   }
 
   public List<String> getPatchHeader() {
@@ -144,33 +115,17 @@
   }
 
   public String getOldName() {
-    return oldName;
+    return fileInfoA.name;
   }
 
   public String getNewName() {
-    return newName;
-  }
-
-  public CommentDetail getCommentDetail() {
-    return comments;
-  }
-
-  public List<Patch> getHistory() {
-    return history;
+    return fileInfoB.name;
   }
 
   public DiffPreferencesInfo getDiffPrefs() {
     return diffPrefs;
   }
 
-  public void setDiffPrefs(DiffPreferencesInfo dp) {
-    diffPrefs = dp;
-  }
-
-  public boolean isHugeFile() {
-    return hugeFile;
-  }
-
   public boolean isIgnoreWhitespace() {
     return diffPrefs.ignoreWhitespace != Whitespace.IGNORE_NONE;
   }
@@ -183,24 +138,12 @@
     return intralineTimeout;
   }
 
-  public boolean isExpandAllComments() {
-    return diffPrefs.expandAllComments;
-  }
-
   public SparseFileContent getA() {
-    return a;
+    return fileInfoA.content;
   }
 
   public SparseFileContent getB() {
-    return b;
-  }
-
-  public String getMimeTypeA() {
-    return mimeTypeA;
-  }
-
-  public String getMimeTypeB() {
-    return mimeTypeB;
+    return fileInfoB.content;
   }
 
   public List<Edit> getEdits() {
@@ -215,11 +158,11 @@
     return binary;
   }
 
-  public String getCommitIdA() {
-    return commitIdA;
+  public PatchScriptFileInfo getFileInfoA() {
+    return fileInfoA;
   }
 
-  public String getCommitIdB() {
-    return commitIdB;
+  public PatchScriptFileInfo getFileInfoB() {
+    return fileInfoB;
   }
 }
diff --git a/java/com/google/gerrit/common/data/Permission.java b/java/com/google/gerrit/common/data/Permission.java
index 3ba0ba7..9b86b7e 100644
--- a/java/com/google/gerrit/common/data/Permission.java
+++ b/java/com/google/gerrit/common/data/Permission.java
@@ -44,6 +44,7 @@
   public static final String READ = "read";
   public static final String REBASE = "rebase";
   public static final String REMOVE_REVIEWER = "removeReviewer";
+  public static final String REVERT = "revert";
   public static final String SUBMIT = "submit";
   public static final String SUBMIT_AS = "submitAs";
   public static final String TOGGLE_WORK_IN_PROGRESS_STATE = "toggleWipState";
@@ -77,6 +78,7 @@
     NAMES_LC.add(READ.toLowerCase());
     NAMES_LC.add(REBASE.toLowerCase());
     NAMES_LC.add(REMOVE_REVIEWER.toLowerCase());
+    NAMES_LC.add(REVERT.toLowerCase());
     NAMES_LC.add(SUBMIT.toLowerCase());
     NAMES_LC.add(SUBMIT_AS.toLowerCase());
     NAMES_LC.add(TOGGLE_WORK_IN_PROGRESS_STATE.toLowerCase());
diff --git a/java/com/google/gerrit/common/data/SubmitRequirement.java b/java/com/google/gerrit/common/data/SubmitRequirement.java
index 66e647d..2c341bf 100644
--- a/java/com/google/gerrit/common/data/SubmitRequirement.java
+++ b/java/com/google/gerrit/common/data/SubmitRequirement.java
@@ -18,8 +18,6 @@
 
 import com.google.auto.value.AutoValue;
 import com.google.common.base.CharMatcher;
-import com.google.common.collect.ImmutableMap;
-import java.util.Map;
 
 /** Describes a requirement to submit a change. */
 @AutoValue
@@ -37,15 +35,6 @@
 
     public abstract Builder setFallbackText(String value);
 
-    public Builder setData(Map<String, String> value) {
-      return setData(ImmutableMap.copyOf(value));
-    }
-
-    public Builder addCustomValue(String key, String value) {
-      dataBuilder().put(key, value);
-      return this;
-    }
-
     public SubmitRequirement build() {
       SubmitRequirement requirement = autoBuild();
       checkState(
@@ -54,10 +43,6 @@
       return requirement;
     }
 
-    abstract Builder setData(ImmutableMap<String, String> value);
-
-    abstract ImmutableMap.Builder<String, String> dataBuilder();
-
     abstract SubmitRequirement autoBuild();
   }
 
@@ -65,8 +50,6 @@
 
   public abstract String type();
 
-  public abstract ImmutableMap<String, String> data();
-
   public static Builder builder() {
     return new AutoValue_SubmitRequirement.Builder();
   }
diff --git a/java/com/google/gerrit/common/data/SubmitTypeRecord.java b/java/com/google/gerrit/common/data/SubmitTypeRecord.java
index d16da96..afb3bac 100644
--- a/java/com/google/gerrit/common/data/SubmitTypeRecord.java
+++ b/java/com/google/gerrit/common/data/SubmitTypeRecord.java
@@ -65,7 +65,7 @@
     StringBuilder sb = new StringBuilder();
     sb.append(status);
     if (status == Status.RULE_ERROR && errorMessage != null) {
-      sb.append('(').append(errorMessage).append(")");
+      sb.append(" (").append(errorMessage).append(")");
     }
     if (type != null) {
       sb.append('[');
diff --git a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index ed32ce5..e56f470 100644
--- a/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -26,6 +26,7 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Streams;
 import com.google.common.flogger.FluentLogger;
+import com.google.common.io.BaseEncoding;
 import com.google.common.io.CharStreams;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
@@ -68,7 +69,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
-import org.apache.commons.codec.binary.Base64;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpStatus;
 import org.apache.http.StatusLine;
@@ -88,7 +88,7 @@
   protected static final String SETTINGS = "settings";
 
   protected static byte[] decodeBase64(String base64String) {
-    return Base64.decodeBase64(base64String);
+    return BaseEncoding.base64().decode(base64String);
   }
 
   protected static <T> List<T> decodeProtos(
@@ -248,7 +248,7 @@
         } else if (type == FieldType.TIMESTAMP) {
           rawFields.put(element.getKey(), new Timestamp(inner.getAsLong()));
         } else if (type == FieldType.STORED_ONLY) {
-          rawFields.put(element.getKey(), Base64.decodeBase64(inner.getAsString()));
+          rawFields.put(element.getKey(), decodeBase64(inner.getAsString()));
         } else {
           throw FieldType.badFieldType(type);
         }
diff --git a/java/com/google/gerrit/elasticsearch/BUILD b/java/com/google/gerrit/elasticsearch/BUILD
index edbd82c..8bab80b 100644
--- a/java/com/google/gerrit/elasticsearch/BUILD
+++ b/java/com/google/gerrit/elasticsearch/BUILD
@@ -19,7 +19,6 @@
         "//lib:guava",
         "//lib:jgit",
         "//lib:protobuf",
-        "//lib/commons:codec",
         "//lib/commons:lang",
         "//lib/elasticsearch-rest-client",
         "//lib/flogger:api",
diff --git a/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
index bde3ad5..8967789 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -72,7 +73,9 @@
 
   @Override
   public void replace(AccountState as) {
-    BulkRequest bulk = new IndexRequest(getId(as), indexName).add(new UpdateRequest<>(schema, as));
+    BulkRequest bulk =
+        new IndexRequest(getId(as), indexName)
+            .add(new UpdateRequest<>(schema, as, ImmutableSet.of()));
 
     String uri = getURI(BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
diff --git a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index 2be1585..625a598 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -19,6 +19,7 @@
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.MultimapBuilder;
@@ -43,6 +44,8 @@
 import com.google.gerrit.server.ReviewerByEmailSet;
 import com.google.gerrit.server.ReviewerSet;
 import com.google.gerrit.server.StarredChangesUtil;
+import com.google.gerrit.server.change.MergeabilityComputationBehavior;
+import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.index.IndexUtils;
 import com.google.gerrit.server.index.change.ChangeField;
@@ -58,6 +61,7 @@
 import java.util.Optional;
 import java.util.Set;
 import org.apache.http.HttpStatus;
+import org.eclipse.jgit.lib.Config;
 import org.elasticsearch.client.Response;
 
 /** Secondary index implementation using Elasticsearch. */
@@ -82,6 +86,7 @@
   private final ChangeData.Factory changeDataFactory;
   private final Schema<ChangeData> schema;
   private final FieldDef<ChangeData, ?> idField;
+  private final ImmutableSet<String> skipFields;
 
   @Inject
   ElasticChangeIndex(
@@ -89,6 +94,7 @@
       ChangeData.Factory changeDataFactory,
       SitePaths sitePaths,
       ElasticRestClientProvider clientBuilder,
+      @GerritServerConfig Config gerritConfig,
       @Assisted Schema<ChangeData> schema) {
     super(cfg, sitePaths, schema, clientBuilder, CHANGES);
     this.changeDataFactory = changeDataFactory;
@@ -96,11 +102,16 @@
     this.mapping = new ChangeMapping(schema, client.adapter());
     this.idField =
         this.schema.useLegacyNumericFields() ? ChangeField.LEGACY_ID : ChangeField.LEGACY_ID_STR;
+    this.skipFields =
+        MergeabilityComputationBehavior.fromConfig(gerritConfig).includeInIndex()
+            ? ImmutableSet.of()
+            : ImmutableSet.of(ChangeField.MERGEABLE.getName());
   }
 
   @Override
   public void replace(ChangeData cd) {
-    BulkRequest bulk = new IndexRequest(getId(cd), indexName).add(new UpdateRequest<>(schema, cd));
+    BulkRequest bulk =
+        new IndexRequest(getId(cd), indexName).add(new UpdateRequest<>(schema, cd, skipFields));
 
     String uri = getURI(BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
@@ -209,7 +220,7 @@
 
     // Mergeable.
     JsonElement mergeableElement = source.get(ChangeField.MERGEABLE.getName());
-    if (mergeableElement != null) {
+    if (mergeableElement != null && !skipFields.contains(ChangeField.MERGEABLE.getName())) {
       String mergeable = mergeableElement.getAsString();
       if ("1".equals(mergeable)) {
         cd.setMergeable(true);
@@ -341,6 +352,15 @@
     // Unresolved-comment-count.
     decodeUnresolvedCommentCount(source, ChangeField.UNRESOLVED_COMMENT_COUNT.getName(), cd);
 
+    // Attention set.
+    if (fields.contains(ChangeField.ATTENTION_SET_FULL.getName())) {
+      ChangeField.parseAttentionSet(
+          FluentIterable.from(source.getAsJsonArray(ChangeField.ATTENTION_SET_FULL.getName()))
+              .transform(ElasticChangeIndex::decodeBase64JsonElement)
+              .toSet(),
+          cd);
+    }
+
     return cd;
   }
 
@@ -359,12 +379,16 @@
     }
     ChangeField.parseSubmitRecords(
         FluentIterable.from(records)
-            .transform(i -> new String(decodeBase64(i.getAsString()), UTF_8))
+            .transform(ElasticChangeIndex::decodeBase64JsonElement)
             .toList(),
         opts,
         out);
   }
 
+  private static String decodeBase64JsonElement(JsonElement input) {
+    return new String(decodeBase64(input.getAsString()), UTF_8);
+  }
+
   private void decodeUnresolvedCommentCount(JsonObject doc, String fieldName, ChangeData out) {
     JsonElement count = doc.get(fieldName);
     if (count == null) {
diff --git a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
index 241e7fd..f8c2ec5 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -73,7 +74,8 @@
   @Override
   public void replace(InternalGroup group) {
     BulkRequest bulk =
-        new IndexRequest(getId(group), indexName).add(new UpdateRequest<>(schema, group));
+        new IndexRequest(getId(group), indexName)
+            .add(new UpdateRequest<>(schema, group, ImmutableSet.of()));
 
     String uri = getURI(BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
diff --git a/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
index 36eeca1..b8bfc38 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticProjectIndex.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.elasticsearch;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.bulk.BulkRequest;
 import com.google.gerrit.elasticsearch.bulk.IndexRequest;
@@ -31,12 +32,14 @@
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.index.IndexUtils;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectState;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
+import java.util.Optional;
 import java.util.Set;
 import org.apache.http.HttpStatus;
 import org.elasticsearch.client.Response;
@@ -74,7 +77,7 @@
   public void replace(ProjectData projectState) {
     BulkRequest bulk =
         new IndexRequest(projectState.getProject().getName(), indexName)
-            .add(new UpdateRequest<>(schema, projectState));
+            .add(new UpdateRequest<>(schema, projectState, ImmutableSet.of()));
 
     String uri = getURI(BULK);
     Response response = postRequest(uri, bulk, getRefreshParam());
@@ -118,6 +121,10 @@
 
     Project.NameKey nameKey =
         Project.nameKey(source.getAsJsonObject().get(ProjectField.NAME.getName()).getAsString());
-    return projectCache.get().get(nameKey).toProjectData();
+    Optional<ProjectState> state = projectCache.get().get(nameKey);
+    if (!state.isPresent()) {
+      return null;
+    }
+    return state.get().toProjectData();
   }
 }
diff --git a/java/com/google/gerrit/elasticsearch/ElasticVersion.java b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
index 5e72780..c6400df 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticVersion.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
@@ -18,8 +18,6 @@
 import java.util.regex.Pattern;
 
 public enum ElasticVersion {
-  V7_4("7.4.*"),
-  V7_5("7.5.*"),
   V7_6("7.6.*"),
   V7_7("7.7.*"),
   V7_8("7.8.*");
diff --git a/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java b/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
index 2f0bd01..196b8d6 100644
--- a/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
+++ b/java/com/google/gerrit/elasticsearch/bulk/UpdateRequest.java
@@ -16,6 +16,7 @@
 
 import static java.util.stream.Collectors.toList;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Streams;
 import com.google.gerrit.elasticsearch.builders.XContentBuilder;
@@ -27,17 +28,19 @@
 
   private final Schema<V> schema;
   private final V v;
+  private final ImmutableSet<String> skipFields;
 
-  public UpdateRequest(Schema<V> schema, V v) {
+  public UpdateRequest(Schema<V> schema, V v, ImmutableSet<String> skipFields) {
     this.schema = schema;
     this.v = v;
+    this.skipFields = skipFields;
   }
 
   @Override
   protected String getRequest() {
     try (XContentBuilder closeable = new XContentBuilder()) {
       XContentBuilder builder = closeable.startObject();
-      for (Values<V> values : schema.buildFields(v)) {
+      for (Values<V> values : schema.buildFields(v, skipFields)) {
         String name = values.getField().getName();
         if (values.getField().isRepeatable()) {
           builder.field(name, Streams.stream(values.getValues()).collect(toList()));
diff --git a/java/com/google/gerrit/entities/Account.java b/java/com/google/gerrit/entities/Account.java
index 809db1e..cd3b27a 100644
--- a/java/com/google/gerrit/entities/Account.java
+++ b/java/com/google/gerrit/entities/Account.java
@@ -129,6 +129,10 @@
   @Nullable
   public abstract String fullName();
 
+  /** Optional display name of the user to be shown in the UI. */
+  @Nullable
+  public abstract String displayName();
+
   /** Email address the user prefers to be contacted through. */
   @Nullable
   public abstract String preferredEmail();
@@ -236,6 +240,11 @@
     public abstract Builder setFullName(String fullName);
 
     @Nullable
+    public abstract String displayName();
+
+    public abstract Builder setDisplayName(String displayName);
+
+    @Nullable
     public abstract String preferredEmail();
 
     public abstract Builder setPreferredEmail(String preferredEmail);
diff --git a/java/com/google/gerrit/entities/AccountGroup.java b/java/com/google/gerrit/entities/AccountGroup.java
index c10edc2..0b2a346 100644
--- a/java/com/google/gerrit/entities/AccountGroup.java
+++ b/java/com/google/gerrit/entities/AccountGroup.java
@@ -15,23 +15,8 @@
 package com.google.gerrit.entities;
 
 import com.google.auto.value.AutoValue;
-import com.google.gerrit.common.Nullable;
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.util.Objects;
 
-/** Named group of one or more accounts, typically used for access controls. */
 public final class AccountGroup {
-  /**
-   * Time when the audit subsystem was implemented, used as the default value for {@link #createdOn}
-   * when one couldn't be determined from the audit log.
-   */
-  private static final Instant AUDIT_CREATION_INSTANT_MS = Instant.ofEpochMilli(1244489460000L);
-
-  public static Timestamp auditCreationInstantTs() {
-    return Timestamp.from(AUDIT_CREATION_INSTANT_MS);
-  }
-
   public static NameKey nameKey(String n) {
     return new AutoValue_AccountGroup_NameKey(n);
   }
@@ -69,6 +54,11 @@
       return uuid();
     }
 
+    /** @return true if the UUID is for a group managed within Gerrit. */
+    public boolean isInternalGroup() {
+      return get().matches("^[0-9a-f]{40}$");
+    }
+
     /** Parse an {@link AccountGroup.UUID} out of a string representation. */
     public static UUID parse(String str) {
       return AccountGroup.uuid(KeyUtil.decode(str));
@@ -107,11 +97,6 @@
     }
   }
 
-  /** @return true if the UUID is for a group managed within Gerrit. */
-  public static boolean isInternalGroup(AccountGroup.UUID uuid) {
-    return uuid.get().matches("^[0-9a-f]{40}$");
-  }
-
   public static Id id(int id) {
     return new AutoValue_AccountGroup_Id(id);
   }
@@ -135,158 +120,4 @@
       return Integer.toString(get());
     }
   }
-
-  /** Unique name of this group within the system. */
-  protected NameKey name;
-
-  /** Unique identity, to link entities as {@link #name} can change. */
-  protected Id groupId;
-
-  // DELETED: id = 3 (ownerGroupId)
-
-  /** A textual description of the group's purpose. */
-  @Nullable protected String description;
-
-  // DELETED: id = 5 (groupType)
-  // DELETED: id = 6 (externalName)
-
-  protected boolean visibleToAll;
-
-  // DELETED: id = 8 (emailOnlyAuthors)
-
-  /** Globally unique identifier name for this group. */
-  protected UUID groupUUID;
-
-  /**
-   * Identity of the group whose members can manage this group.
-   *
-   * <p>This can be a self-reference to indicate the group's members manage itself.
-   */
-  protected UUID ownerGroupUUID;
-
-  @Nullable protected Timestamp createdOn;
-
-  protected AccountGroup() {}
-
-  public AccountGroup(
-      AccountGroup.NameKey newName,
-      AccountGroup.Id newId,
-      AccountGroup.UUID uuid,
-      Timestamp createdOn) {
-    name = newName;
-    groupId = newId;
-    visibleToAll = false;
-    groupUUID = uuid;
-    ownerGroupUUID = groupUUID;
-    this.createdOn = createdOn;
-  }
-
-  public AccountGroup(AccountGroup other) {
-    name = other.name;
-    groupId = other.groupId;
-    description = other.description;
-    visibleToAll = other.visibleToAll;
-    groupUUID = other.groupUUID;
-    ownerGroupUUID = other.ownerGroupUUID;
-    createdOn = other.createdOn;
-  }
-
-  public AccountGroup.Id getId() {
-    return groupId;
-  }
-
-  public String getName() {
-    return name.get();
-  }
-
-  public AccountGroup.NameKey getNameKey() {
-    return name;
-  }
-
-  public void setNameKey(AccountGroup.NameKey nameKey) {
-    name = nameKey;
-  }
-
-  public String getDescription() {
-    return description;
-  }
-
-  public void setDescription(String d) {
-    description = d;
-  }
-
-  public AccountGroup.UUID getOwnerGroupUUID() {
-    return ownerGroupUUID;
-  }
-
-  public void setOwnerGroupUUID(AccountGroup.UUID uuid) {
-    ownerGroupUUID = uuid;
-  }
-
-  public void setVisibleToAll(boolean visibleToAll) {
-    this.visibleToAll = visibleToAll;
-  }
-
-  public boolean isVisibleToAll() {
-    return visibleToAll;
-  }
-
-  public AccountGroup.UUID getGroupUUID() {
-    return groupUUID;
-  }
-
-  public void setGroupUUID(AccountGroup.UUID uuid) {
-    groupUUID = uuid;
-  }
-
-  public Timestamp getCreatedOn() {
-    return createdOn != null ? creat