Merge "Recognize all parts marked with 'multipart/'" into stable-2.14
diff --git a/.gitignore b/.gitignore
index 1b93f20..5e9b659 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,11 +19,7 @@
 /.settings/org.eclipse.ltk.core.refactoring.prefs
 /.settings/org.eclipse.m2e.core.prefs
 /.settings/org.maven.ide.eclipse.prefs
-/bazel-bin
-/bazel-genfiles
-/bazel-gerrit
-/bazel-out
-/bazel-testlogs
+/bazel-*
 /bin/
 /buck-out
 /eclipse-out
diff --git a/.mailmap b/.mailmap
index ebf2781..c35b2ec 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1,28 +1,40 @@
 Adrian Görler <adrian.goerler@sap.com>                                                      Adrian Goerler <adrian.goerler@sap.com>
 Ahaan Ugale <ahaanugale@gmail.com>                                                          <augale@codeaurora.org>
 Alex Blewitt <alex.blewitt@gmail.com>                                                       <alex.blewitt@gs.com>
+Alex Blewitt <alex.blewitt@gmail.com>                                                       <alex.blewitt@credit-suisse.com>
 Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex <alex.ryazantsev@gmail.com>
 Alex Ryazantsev <alex.ryazantsev@gmail.com>                                                 alex.ryazantsev <alex.ryazantsev@gmail.com>
+Andrew Bonventre <andybons@chromium.org>                                                    <andybons@google.com>
 Becky Siegel <beckysiegel@google.com>                                                       beckysiegel <beckysiegel@google.com>
 Brad Larson <bklarson@gmail.com>                                                            <brad.larson@garmin.com>
-Bruce Zu <bruce.zu@sonymobile.com>                                                          <bruce.zu@sonyericsson.com>
+Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonyericsson.com>
+Bruce Zu <bruce.zu.run10@gmail.com>                                                         <bruce.zu@sonymobile.com>
 Carlos Eduardo Baldacin <carloseduardo.baldacin@sonyericsson.com>                           carloseduardo.baldacin <carloseduardo.baldacin@sonyericsson.com>
+Dariusz Luksza <dluksza@collab.net>                                                         <dariusz@luksza.org>
 David Ostrovsky <david@ostrovsky.org>                                                       <d.ostrovsky@gmx.de>
+David Ostrovsky <david@ostrovsky.org>                                                       <david.ostrovsky@gmail.com>
+David Pursehouse <dpursehouse@collab.net>                                                   <david.pursehouse@sonymobile.com>
 Deniz Türkoglu <deniz@spotify.com>                                                          Deniz Türkoglu <deniz@spotify.com>
 Deniz Türkoglu <deniz@spotify.com>                                                          Deniz Turkoglu <deniz@spotify.com>
+Doug Kelly <dougk.ff7@gmail.com>                                                            <doug.kelly@garmin.com>
 Edwin Kempin <ekempin@google.com>                                                           Edwin Kempin <edwin.kempin@gmail.com>
 Edwin Kempin <ekempin@google.com>                                                           Edwin Kempin <edwin.kempin@sap.com>
 Edwin Kempin <ekempin@google.com>                                                           ekempin <ekempin@google.com>
 Eryk Szymanski <eryksz@gmail.com>                                                           <eryksz@google.com>
 Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik@gandaraj.com>
 Fredrik Luthander <fredrik.luthander@sonymobile.com>                                        <fredrik.luthander@sonyericsson.com>
-Gustaf Lundh <gustaf.lundh@sonymobile.com>                                                  <gustaf.lundh@sonyericsson.com>
+Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@axis.com>
+Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonyericsson.com>
+Gustaf Lundh <gustaflh@axis.com>                                                            <gustaf.lundh@sonymobile.com>
 Hugo Arès <hugo.ares@ericsson.com>                                                          Hugo Ares <hugo.ares@ericsson.com>
+Jacek Centkowski <jcentkowski@collab.net>                                                   <gemincia.programs@gmail.com>
+Jacek Centkowski <jcentkowski@collab.net>                                                   <geminica.programs@gmail.com>
 Jason Huntley <jhuntley@houghtonassociates.com>                                             jhuntley <jhuntley@houghtonassociates.com>
 Jiří Engelthaler <EngyCZ@gmail.com>                                                         <engycz@gmail.com>
 Joe Onorato <onoratoj@gmail.com>                                                            <joeo@android.com>
 Joel Dodge <dodgejoel@gmail.com>                                                            dodgejoel <dodgejoel@gmail.com>
 Johan Björk <jbjoerk@gmail.com>                                                             Johan Bjork <phb@spotify.com>
+JT Olds <hello@jtolds.com>                                                                  <jtolds@gmail.com>
 Lincoln Oliveira Campos Do Nascimento <lincoln.oliveiracamposdonascimento@sonyericsson.com> lincoln <lincoln.oliveiracamposdonascimento@sonyericsson.com>
 Luca Milanesio <luca.milanesio@gmail.com>                                                   <luca@gitent-scm.com>
 Magnus Bäck <baeck@google.com>                                                              <magnus.back@sonyericsson.com>
@@ -36,10 +48,15 @@
 Peter Jönsson <peter.joensson@gmail.com>                                                    Peter Jönsson <peter.joensson@gmail.com>
 Rafael Rabelo Silva <rafael.rabelosilva@sonyericsson.com>                                   rafael.rabelosilva <rafael.rabelosilva@sonyericsson.com>
 Richard Möhn <richard.moehn@posteo.de>                                                      <richard.moehn@fu-berlin.de>
+Sam Saccone <samccone@google.com>                                                           <samccone@gmail.com>
 Saša Živkov <sasa.zivkov@sap.com>                                                           Sasa Zivkov <sasa.zivkov@sap.com>
 Saša Živkov <sasa.zivkov@sap.com>                                                           Saša Živkov <zivkov@gmail.com>
+Saša Živkov <sasa.zivkov@sap.com>                                                           Sasa Zivkov <zivkov@gmail.com>
+Scott Dial <scott@scottdial.com>                                                            <geekmug@gmail.com>
 Shawn Pearce <sop@google.com>                                                               Shawn O. Pearce <sop@google.com>
 Sixin Li <sixin210@gmail.com>                                                               sixin li <sixin210@gmail.com>
+Sven Selberg <svense@axis.com>                                                              <sven.selberg@axis.com>
+Sven Selberg <svense@axis.com>                                                              <sven.selberg@sonymobile.com>
 Tom Wang <twang10@gmail.com>                                                                Tom <twang10@gmail.com>
 Tomas Westling <thomas.westling@sonyericsson.com>                                           thomas.westling <thomas.westling@sonyericsson.com>
 Ulrik Sjölin <ulrik.sjolin@sonyericsson.com>                                                <ulrik.sjolin@gmail.com>
diff --git a/Documentation/cmd-review.txt b/Documentation/cmd-review.txt
index 53e2385..4e24701 100644
--- a/Documentation/cmd-review.txt
+++ b/Documentation/cmd-review.txt
@@ -63,7 +63,7 @@
 
 --json::
 -j::
-	Read review input from JSON file. See
+	Read review input json from stdin. See
 	link:rest-api-changes.html#review-input[ReviewInput] entity for the
 	format.
 	(option is mutually exclusive with --submit, --restore, --publish, --delete,
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 09a579d..c67b628 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -604,7 +604,7 @@
 See <<database.h2.cachesize,database.h2.cachesize>> for a detailed discussion.
 +
 Default is unset, using up to half of the available memory.
-
++
 H2 will persist this value in the database, so to unset explicitly specify 0.
 +
 Common unit suffixes of 'k', 'm', or 'g' are supported.
@@ -1707,7 +1707,7 @@
 link:http://www.h2database.com/html/features.html#cache_settings[here]
 +
 Default is unset, using up to half of the available memory.
-
++
 H2 will persist this value in the database, so to unset explicitly specify 0.
 +
 Common unit suffixes of 'k', 'm', or 'g' are supported.
@@ -2541,14 +2541,16 @@
 Maximum idle time for a connection, which roughly translates to the
 TCP socket `SO_TIMEOUT`.
 +
-The max idle time is applied:
-* When waiting for a new message to be received on a connection
-* When waiting for a new message to be sent on a connection
-+
 This value is interpreted as the maximum time between some progress
 being made on the connection. So if a single byte is read or written,
 then the timeout is reset.
 +
+The max idle time is applied:
++
+* When waiting for a new message to be received on a connection
+* When waiting for a new message to be sent on a connection
+
++
 By default, 30 seconds.
 
 [[httpd.robotsFile]]httpd.robotsFile::
@@ -2653,6 +2655,15 @@
 +
 Defaults to 1024.
 
+[[index.autoReindexIfStale]]index.autoReindexIfStale::
++
+Whether to automatically check if a document became stale in the index
+immediately after indexing it. If false, there is a race condition during two
+simultaneous writes that may cause one of the writes to not be reflected in the
+index. The check to avoid this does consume some resources.
++
+Defaults to true.
+
 ==== Lucene configuration
 
 Open and closed changes are indexed in separate indexes named
diff --git a/Documentation/config-mail.txt b/Documentation/config-mail.txt
index 1adc8d9..af2bd98 100644
--- a/Documentation/config-mail.txt
+++ b/Documentation/config-mail.txt
@@ -201,7 +201,7 @@
 
 $change.shortSubject::
 +
-The subject limited to 63 characters, with an ellipsis if it exceeds that.
+The subject limited to 72 characters, with an ellipsis if it exceeds that.
 
 $change.ownerEmail::
 +
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 3692dfb7..2976e96 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -2193,6 +2193,8 @@
 
 FileHistoryWebLinks will appear on the access rights screen.
 
+TagWebLinks will appear in the tag list in the last column.
+
 [[lfs-extension]]
 == LFS Storage Plugins
 
diff --git a/Documentation/index.txt b/Documentation/index.txt
index 09ea1a2..511f19a 100644
--- a/Documentation/index.txt
+++ b/Documentation/index.txt
@@ -5,7 +5,7 @@
 .. link:intro-quick.html[A Quick Introduction to Gerrit]
 .. link:intro-user.html[User Guide]
 .. link:intro-project-owner.html[Project Owner Guide]
-.. link:http://source.android.com/submit-patches/workflow[Default Android Workflow] (external)
+.. link:http://source.android.com/source/life-of-a-patch[Default Android Workflow] (external)
 . Web
 .. link:user-review-ui.html[Reviewing Changes]
 .. link:user-search.html[Searching Changes]
diff --git a/Documentation/install-quick.txt b/Documentation/install-quick.txt
index d665226..3ab2d4b 100644
--- a/Documentation/install-quick.txt
+++ b/Documentation/install-quick.txt
@@ -211,7 +211,7 @@
 
 This covers the scope of getting Gerrit started and your first change uploaded.
 It doesn't give any clue as to how the review workflow works, please read
-link:http://source.android.com/submit-patches/workflow[Default Workflow] to
+link:http://source.android.com/source/life-of-a-patch[Default Workflow] to
 learn more about the workflow of Gerrit.
 
 To read more on the installation of Gerrit please see link:install.html[the detailed
diff --git a/Documentation/pgm-LocalUsernamesToLowerCase.txt b/Documentation/pgm-LocalUsernamesToLowerCase.txt
index f295225..e0fe1b3 100644
--- a/Documentation/pgm-LocalUsernamesToLowerCase.txt
+++ b/Documentation/pgm-LocalUsernamesToLowerCase.txt
@@ -28,9 +28,11 @@
 same local username, but with different case. In this case the local
 username for these accounts is not converted to lower case.
 
-This task can run in the background concurrently to the server if the
-database is MySQL or PostgreSQL. If the database is H2, this task
-must be run by itself.
+After all usernames have been migrated, the link:pgm-reindex.html[
+reindex] program is automatically invoked to reindex all accounts.
+
+This task cannot run in the background concurrently to the server;
+it must be run by itself.
 
 == OPTIONS
 
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 13fca66..880a1a2 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1525,6 +1525,7 @@
     "hide_line_numbers": true,
     "match_brackets": true,
     "line_wrapping": false,
+    "indent_with_tabs": false,
     "auto_close_brackets": true
   }
 ----
@@ -2428,6 +2429,8 @@
 Default font size in pixels for change to be displayed in the diff view.
 |`line_wrapping`               |optional|
 Whether to enable line wrapping or not.
+|`indent_with_tabs`            |optional|
+Whether to enable indent with tabs or not.
 |===========================================
 
 [[edit-preferences-info]]
diff --git a/Documentation/rest-api-groups.txt b/Documentation/rest-api-groups.txt
index bef2153..378c7f5 100644
--- a/Documentation/rest-api-groups.txt
+++ b/Documentation/rest-api-groups.txt
@@ -216,6 +216,38 @@
   }
 ----
 
+Substring(m)::
+Limit the results to those groups that match the specified substring.
++
+The match is case insensitive.
++
+List all groups that match substring `test/`:
++
+.Request
+----
+  GET /groups/?m=test%2F HTTP/1.0
+----
++
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  {
+    "test/test": {
+      "url": "#/admin/groups/uuid-786a95e85f9a2223a96545f10003f396aba871f2",
+      "options": {},
+      "group_id": 15,
+      "owner": "test/test",
+      "owner_id": "786a95e85f9a2223a96545f10003f396aba871f2",
+      "created_on": "2017-07-11 13:56:24.000000000",
+      "id": "786a95e85f9a2223a96545f10003f396aba871f2"
+    }
+  }
+----
+
 [[query-groups]]
 === Query Groups
 --
@@ -687,7 +719,7 @@
 
 .Request
 ----
-  PUT /groups/9999c971bb4ab872aab759d8c49833ee6b9ff320/description HTTP/1.0
+  PUT /groups/9999c971bb4ab872aab759d8c49833ee6b9ff320/owner HTTP/1.0
   Content-Type: application/json; charset=UTF-8
 
   {
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 72c6a39..816a40c 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -149,6 +149,8 @@
 Limit the results to those projects that start with the specified
 prefix.
 +
+The match is case sensitive. May not be used together with `m` or `r`.
++
 List all projects that start with `platform/`:
 +
 .Request
@@ -182,6 +184,8 @@
 match any projects that start with 'test' and regex '.*test' will match any
 project that end with 'test'.
 +
+The match is case sensitive. May not be used together with `m` or `p`.
++
 List all projects that match regex `test.*project`:
 +
 .Request
@@ -234,6 +238,8 @@
 Substring(m)::
 Limit the results to those projects that match the specified substring.
 +
+The match is case insensitive. May not be used together with `r` or `p`.
++
 List all projects that match substring `test/`:
 +
 .Request
@@ -1183,9 +1189,11 @@
 ----
 
 Substring(m)::
-Limit the results to those projects that match the specified substring.
+Limit the results to those branches that match the specified substring.
 +
-List all projects that match substring `test`:
+The match is case insensitive. May not be used together with `r`.
++
+List all branches that match substring `test`:
 +
 .Request
 ----
@@ -1211,8 +1219,10 @@
 Regex(r)::
 Limit the results to those branches that match the specified regex.
 Boundary matchers '^' and '$' are implicit. For example: the regex 't*' will
-match any branches that start with 'test' and regex '*t' will match any
-branches that end with 'test'.
+match any branches that start with 't' and regex '*t' will match any
+branches that end with 't'.
++
+The match is case sensitive. May not be used together with `m`.
 +
 List all branches that match regex `t.*1`:
 +
@@ -1867,6 +1877,87 @@
   ]
 ----
 
+Substring(m)::
+Limit the results to those tags that match the specified substring.
++
+The match is case insensitive.  May not be used together with `r`.
++
+List all tags that match substring `v2`:
+
++
+.Request
+----
+  GET /projects/testproject/tags?m=v2 HTTP/1.0
+----
++
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  [
+    {
+      "ref": "refs/tags/v2.0",
+      "revision": "1624f5af8ae89148d1a3730df8c290413e3dcf30"
+    },
+  ]
+----
+
+Regex(r)::
+Limit the results to those tags that match the specified regex.
+Boundary matchers '^' and '$' are implicit. For example: the regex 't*' will
+match any tags that start with 't' and regex '*t' will match any
+tags that end with 't'.
++
+The match is case sensitive.  May not be used together with `m`.
++
+List all tags that match regex `v.*0`:
++
+.Request
+----
+  GET /projects/testproject/tags?r=v.*0 HTTP/1.0
+----
++
+.Response
+----
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json; charset=UTF-8
+
+  )]}'
+  [
+    {
+      "ref": "refs/tags/v1.0",
+      "revision": "49ce77fdcfd3398dc0dedbe016d1a425fd52d666",
+      "object": "1624f5af8ae89148d1a3730df8c290413e3dcf30",
+      "message": "Annotated tag",
+      "tagger": {
+        "name": "David Pursehouse",
+        "email": "david.pursehouse@sonymobile.com",
+        "date": "2014-10-06 07:35:03.000000000",
+        "tz": 540
+      }
+    },
+    {
+      "ref": "refs/tags/v2.0",
+      "revision": "1624f5af8ae89148d1a3730df8c290413e3dcf30"
+    },
+    {
+      "ref": "refs/tags/v3.0",
+      "revision": "c628685b3c5a3614571ecb5c8fceb85db9112313",
+      "object": "1624f5af8ae89148d1a3730df8c290413e3dcf30",
+      "message": "Signed tag\n-----BEGIN PGP SIGNATURE-----\nVersion: GnuPG v1.4.11 (GNU/Linux)\n\niQEcBAABAgAGBQJUMlqYAAoJEPI2qVPgglptp7MH/j+KFcittFbxfSnZjUl8n5IZ\nveZo7wE+syjD9sUbMH4EGv0WYeVjphNTyViBof+stGTNkB0VQzLWI8+uWmOeiJ4a\nzj0LsbDOxodOEMI5tifo02L7r4Lzj++EbqtKv8IUq2kzYoQ2xjhKfFiGjeYOn008\n9PGnhNblEHZgCHguGR6GsfN8bfA2XNl9B5Ysl5ybX1kAVs/TuLZR4oDMZ/pW2S75\nhuyNnSgcgq7vl2gLGefuPs9lxkg5Fj3GZr7XPZk4pt/x1oiH7yXxV4UzrUwg2CC1\nfHrBlNbQ4uJNY8TFcwof52Z0cagM5Qb/ZSLglHbqEDGA68HPqbwf5z2hQyU2/U4\u003d\n\u003dZtUX\n-----END PGP SIGNATURE-----",
+      "tagger": {
+        "name": "David Pursehouse",
+        "email": "david.pursehouse@sonymobile.com",
+        "date": "2014-10-06 09:02:16.000000000",
+        "tz": 540
+      }
+    }
+  ]
+----
 
 [[get-tag]]
 === Get Tag
@@ -2882,6 +2973,9 @@
 link:rest-api-changes.html#git-person-info[GitPersonInfo] entity.
 |`can_delete`|`false` if not set|
 Whether the calling user can delete this tag.
+|`web_links` |optional|
+Links to the tag in external sites as a list of
+link:rest-api-changes.html#web-link-info[WebLinkInfo] entries.
 |=========================
 
 [[tag-input]]
diff --git a/Documentation/user-review-ui.txt b/Documentation/user-review-ui.txt
index cb72519b..434a7a4 100644
--- a/Documentation/user-review-ui.txt
+++ b/Documentation/user-review-ui.txt
@@ -1130,7 +1130,7 @@
 
 - [[line-wrapping]]`Line Wrapping`:
 +
-Controls weather to enable line wrapping or not.
+Controls whether to enable line wrapping or not.
 +
 If `false` is selected then line wrapping is disabled.
 This is the default option.
diff --git a/gerrit-acceptance-framework/pom.xml b/gerrit-acceptance-framework/pom.xml
index efb68ecb..cd21587 100644
--- a/gerrit-acceptance-framework/pom.xml
+++ b/gerrit-acceptance-framework/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-acceptance-framework</artifactId>
-  <version>2.14.1-SNAPSHOT</version>
+  <version>2.14.1</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Acceptance Test Framework</name>
   <description>Framework for Gerrit's acceptance tests</description>
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 5d25809..4fa4518 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -848,6 +848,14 @@
     return rule;
   }
 
+  protected void blockLabel(
+      String label, int min, int max, AccountGroup.UUID id, String ref, Project.NameKey project)
+      throws Exception {
+    ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
+    Util.block(cfg, Permission.LABEL + label, min, max, id, ref);
+    saveProjectConfig(project, cfg);
+  }
+
   protected void saveProjectConfig(Project.NameKey p, ProjectConfig cfg) throws Exception {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(p)) {
       md.setAuthor(identifiedUserFactory.create(admin.getId()));
@@ -891,6 +899,33 @@
     }
   }
 
+  protected void grantLabel(
+      String label,
+      int min,
+      int max,
+      Project.NameKey project,
+      String ref,
+      boolean force,
+      AccountGroup.UUID groupUUID,
+      boolean exclusive)
+      throws RepositoryNotFoundException, IOException, ConfigInvalidException {
+    String permission = Permission.LABEL + label;
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
+      md.setMessage(String.format("Grant %s on %s", permission, ref));
+      ProjectConfig config = ProjectConfig.read(md);
+      AccessSection s = config.getAccessSection(ref, true);
+      Permission p = s.getPermission(permission, true);
+      p.setExclusiveGroup(exclusive);
+      PermissionRule rule = Util.newRule(config, groupUUID);
+      rule.setForce(force);
+      rule.setMin(min);
+      rule.setMax(max);
+      p.add(rule);
+      config.commit(md);
+      projectCache.evict(config.getProject());
+    }
+  }
+
   protected void removePermission(String permission, Project.NameKey project, String ref)
       throws IOException, ConfigInvalidException {
     try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
index e136bb3..20ae2d1 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AccountCreator.java
@@ -29,7 +29,6 @@
 import com.google.gerrit.server.account.ExternalIdsUpdate;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.account.VersionedAuthorizedKeys;
-import com.google.gerrit.server.index.account.AccountIndexer;
 import com.google.gerrit.server.ssh.SshKeyCache;
 import com.google.gerrit.testutil.SshMode;
 import com.google.gwtorm.server.SchemaFactory;
@@ -56,7 +55,6 @@
   private final SshKeyCache sshKeyCache;
   private final AccountCache accountCache;
   private final AccountByEmailCache byEmailCache;
-  private final AccountIndexer indexer;
   private final ExternalIdsUpdate.Server externalIdsUpdate;
 
   @Inject
@@ -67,7 +65,6 @@
       SshKeyCache sshKeyCache,
       AccountCache accountCache,
       AccountByEmailCache byEmailCache,
-      AccountIndexer indexer,
       ExternalIdsUpdate.Server externalIdsUpdate) {
     accounts = new HashMap<>();
     reviewDbProvider = schema;
@@ -76,7 +73,6 @@
     this.sshKeyCache = sshKeyCache;
     this.accountCache = accountCache;
     this.byEmailCache = byEmailCache;
-    this.indexer = indexer;
     this.externalIdsUpdate = externalIdsUpdate;
   }
 
@@ -120,11 +116,10 @@
         sshKeyCache.evict(username);
       }
 
+      accountCache.evict(id);
       accountCache.evictByUsername(username);
       byEmailCache.evict(email);
 
-      indexer.index(id);
-
       account = new TestAccount(id, username, email, fullName, sshKey, httpPass);
       accounts.put(username, account);
       return account;
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 2afc8c4..75fd448 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -140,8 +140,6 @@
       externalIdsUpdate.delete(db, getExternalIds(user));
       externalIdsUpdate.insert(db, savedExternalIds);
     }
-    accountCache.evict(admin.getId());
-    accountCache.evict(user.getId());
   }
 
   @After
@@ -455,7 +453,6 @@
             ExternalId.createWithEmail(ExternalId.Key.parse(extId1), admin.id, email),
             ExternalId.createWithEmail(ExternalId.Key.parse(extId2), admin.id, email));
     externalIdsUpdateFactory.create().insert(db, extIds);
-    accountCache.evict(admin.id);
     assertThat(
             gApi.accounts().self().getExternalIds().stream().map(e -> e.identity).collect(toSet()))
         .containsAllOf(extId1, extId2);
@@ -506,7 +503,6 @@
     externalIdsUpdateFactory
         .create()
         .insert(db, ExternalId.createWithEmail(ExternalId.Key.parse("foo:bar"), admin.id, email));
-    accountCache.evict(admin.id);
     assertEmail(byEmailCache.get(email), admin);
 
     // wrong case doesn't match
@@ -714,7 +710,6 @@
     // Both users have a matching external ID for this key.
     addExternalIdEmail(admin, "test5@example.com");
     externalIdsUpdate.insert(db, ExternalId.create("foo", "myId", user.getId()));
-    accountCache.evict(user.getId());
 
     TestKey key = validKeyWithSecondUserId();
     addGpgKey(key.getPublicKeyArmored());
@@ -940,8 +935,6 @@
     checkNotNull(email);
     externalIdsUpdate.insert(
         db, ExternalId.createWithEmail(name("test"), email, account.getId(), email));
-    // Clear saved AccountState and ExternalIds.
-    accountCache.evict(account.getId());
     setApiUser(account);
   }
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/EditPreferencesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/EditPreferencesIT.java
index 8baaa54..c1d9bcb 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/EditPreferencesIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/EditPreferencesIT.java
@@ -40,6 +40,7 @@
     assertThat(out.hideLineNumbers).isNull();
     assertThat(out.matchBrackets).isTrue();
     assertThat(out.lineWrapping).isNull();
+    assertThat(out.indentWithTabs).isNull();
     assertThat(out.autoCloseBrackets).isNull();
     assertThat(out.showBase).isNull();
     assertThat(out.theme).isEqualTo(Theme.DEFAULT);
@@ -57,6 +58,7 @@
     out.hideLineNumbers = true;
     out.matchBrackets = false;
     out.lineWrapping = true;
+    out.indentWithTabs = true;
     out.autoCloseBrackets = true;
     out.showBase = true;
     out.theme = Theme.TWILIGHT;
@@ -89,6 +91,7 @@
     assertThat(out.hideLineNumbers).isEqualTo(in.hideLineNumbers);
     assertThat(out.matchBrackets).isNull();
     assertThat(out.lineWrapping).isEqualTo(in.lineWrapping);
+    assertThat(out.indentWithTabs).isEqualTo(in.indentWithTabs);
     assertThat(out.autoCloseBrackets).isEqualTo(in.autoCloseBrackets);
     assertThat(out.showBase).isEqualTo(in.showBase);
     assertThat(out.theme).isEqualTo(in.theme);
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
index c92006b..5c5d15d 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -27,7 +27,6 @@
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.CHANGE_OWNER;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.project.Util.blockLabel;
 import static com.google.gerrit.server.project.Util.category;
 import static com.google.gerrit.server.project.Util.value;
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -1812,7 +1811,7 @@
     assertThat(approval.value).isEqualTo(0);
 
     ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
-    blockLabel(cfg, "Code-Review", REGISTERED_USERS, "refs/heads/*");
+    Util.blockLabel(cfg, "Code-Review", REGISTERED_USERS, "refs/heads/*");
     saveProjectConfig(project, cfg);
     c = gApi.changes().id(triplet).get(EnumSet.of(ListChangesOption.DETAILED_LABELS));
     codeReview = c.labels.get("Code-Review");
@@ -2435,7 +2434,7 @@
   @Test
   public void maxPermittedValueBlocked() throws Exception {
     ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
-    blockLabel(cfg, "Code-Review", REGISTERED_USERS, "refs/heads/*");
+    Util.blockLabel(cfg, "Code-Review", REGISTERED_USERS, "refs/heads/*");
     saveProjectConfig(project, cfg);
 
     PushOneCommit.Result r = createChange();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 7752f3e..76e1160 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -19,6 +19,7 @@
 import static com.google.gerrit.acceptance.rest.account.AccountAssert.assertAccountInfos;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static java.util.stream.Collectors.toList;
+import static org.junit.Assert.fail;
 
 import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -28,6 +29,7 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.extensions.api.groups.GroupApi;
 import com.google.gerrit.extensions.api.groups.GroupInput;
+import com.google.gerrit.extensions.api.groups.Groups;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.GroupAuditEventInfo;
 import com.google.gerrit.extensions.common.GroupAuditEventInfo.GroupMemberAuditEventInfo;
@@ -36,6 +38,7 @@
 import com.google.gerrit.extensions.common.GroupInfo;
 import com.google.gerrit.extensions.common.GroupOptionsInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
@@ -477,6 +480,32 @@
     Map<String, GroupInfo> groups = gApi.groups().list().withSuggest("adm").getAsMap();
     assertThat(groups).containsKey("Administrators");
     assertThat(groups).hasSize(1);
+    assertBadRequest(gApi.groups().list().withSuggest("adm").withSubstring("foo"));
+    assertBadRequest(gApi.groups().list().withSuggest("adm").withUser("user"));
+    assertBadRequest(gApi.groups().list().withSuggest("adm").withOwned(true));
+    assertBadRequest(gApi.groups().list().withSuggest("adm").withVisibleToAll(true));
+    assertBadRequest(gApi.groups().list().withSuggest("adm").withStart(1));
+  }
+
+  @Test
+  public void withSubstring() throws Exception {
+    Map<String, GroupInfo> groups = gApi.groups().list().withSubstring("dmin").getAsMap();
+    assertThat(groups).containsKey("Administrators");
+    assertThat(groups).hasSize(1);
+
+    groups = gApi.groups().list().withSubstring("admin").getAsMap();
+    assertThat(groups).containsKey("Administrators");
+    assertThat(groups).hasSize(1);
+
+    String other = name("Administrators");
+    gApi.groups().create(other);
+    groups = gApi.groups().list().withSubstring("dmin").getAsMap();
+    assertThat(groups).hasSize(2);
+    assertThat(groups).containsKey("Administrators");
+    assertThat(groups).containsKey(other);
+
+    groups = gApi.groups().list().withSubstring("foo").getAsMap();
+    assertThat(groups).isEmpty();
   }
 
   @Test
@@ -614,4 +643,13 @@
     accounts.create(name, group);
     return name;
   }
+
+  private void assertBadRequest(Groups.ListRequest req) throws Exception {
+    try {
+      req.get();
+      fail("Expected BadRequestException");
+    } catch (BadRequestException e) {
+      // Expected
+    }
+  }
 }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
index 06b8f68..df44366 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
@@ -191,6 +191,7 @@
     ExternalIdsUpdate update =
         new ExternalIdsUpdate(
             repoManager,
+            accountCache,
             allUsers,
             serverIdent.get(),
             serverIdent.get(),
@@ -223,6 +224,7 @@
     ExternalIdsUpdate update =
         new ExternalIdsUpdate(
             repoManager,
+            accountCache,
             allUsers,
             serverIdent.get(),
             serverIdent.get(),
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
index 49f5c5a..6a00d59 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeOwnerIT.java
@@ -14,21 +14,18 @@
 
 package com.google.gerrit.acceptance.rest.change;
 
-import static com.google.gerrit.common.data.Permission.LABEL;
-
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.AcceptanceTestRequestScope.Context;
 import com.google.gerrit.acceptance.PushOneCommit;
 import com.google.gerrit.acceptance.TestAccount;
 import com.google.gerrit.acceptance.TestProjectInput;
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRule;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.git.ProjectConfig;
+import com.google.gerrit.reviewdb.client.AccountGroup;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.group.SystemGroupBackend;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -45,21 +42,68 @@
   @Test
   @TestProjectInput(cloneAs = "user")
   public void testChangeOwner_OwnerACLNotGranted() throws Exception {
-    assertApproveFails(user, createMyChange());
+    assertApproveFails(user, createMyChange(testRepo));
   }
 
   @Test
   @TestProjectInput(cloneAs = "user")
   public void testChangeOwner_OwnerACLGranted() throws Exception {
-    grantApproveToChangeOwner();
-    approve(user, createMyChange());
+    grantApproveToChangeOwner(project);
+    approve(user, createMyChange(testRepo));
   }
 
   @Test
   @TestProjectInput(cloneAs = "user")
   public void testChangeOwner_NotOwnerACLGranted() throws Exception {
-    grantApproveToChangeOwner();
-    assertApproveFails(user2, createMyChange());
+    grantApproveToChangeOwner(project);
+    assertApproveFails(user2, createMyChange(testRepo));
+  }
+
+  @Test
+  public void testChangeOwner_OwnerACLGrantedOnParentProject() throws Exception {
+    setApiUser(admin);
+    grantApproveToChangeOwner(project);
+    Project.NameKey child = createProject("child", project);
+
+    setApiUser(user);
+    TestRepository<InMemoryRepository> childRepo = cloneProject(child, user);
+    approve(user, createMyChange(childRepo));
+  }
+
+  @Test
+  public void testChangeOwner_BlockedOnParentProject() throws Exception {
+    setApiUser(admin);
+    blockApproveForChangeOwner(project);
+    Project.NameKey child = createProject("child", project);
+
+    setApiUser(user);
+    grantApproveToAll(child);
+    TestRepository<InMemoryRepository> childRepo = cloneProject(child, user);
+    String changeId = createMyChange(childRepo);
+
+    // change owner cannot approve because Change-Owner group is blocked on parent
+    assertApproveFails(user, changeId);
+
+    // other user can approve
+    approve(user2, changeId);
+  }
+
+  @Test
+  public void testChangeOwner_BlockedOnParentProjectAndExclusiveAllowOnChild() throws Exception {
+    setApiUser(admin);
+    blockApproveForChangeOwner(project);
+    Project.NameKey child = createProject("child", project);
+
+    setApiUser(user);
+    grantExclusiveApproveToAll(child);
+    TestRepository<InMemoryRepository> childRepo = cloneProject(child, user);
+    String changeId = createMyChange(childRepo);
+
+    // change owner cannot approve because Change-Owner group is blocked on parent
+    assertApproveFails(user, changeId);
+
+    // other user can approve
+    approve(user2, changeId);
   }
 
   private void approve(TestAccount a, String changeId) throws Exception {
@@ -76,24 +120,28 @@
     approve(a, changeId);
   }
 
-  private void grantApproveToChangeOwner() throws Exception {
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
-      md.setMessage(String.format("Grant approve to change owner"));
-      ProjectConfig config = ProjectConfig.read(md);
-      AccessSection s = config.getAccessSection("refs/heads/*", true);
-      Permission p = s.getPermission(LABEL + "Code-Review", true);
-      PermissionRule rule =
-          new PermissionRule(
-              config.resolve(systemGroupBackend.getGroup(SystemGroupBackend.CHANGE_OWNER)));
-      rule.setMin(-2);
-      rule.setMax(+2);
-      p.add(rule);
-      config.commit(md);
-      projectCache.evict(config.getProject());
-    }
+  private void grantApproveToChangeOwner(Project.NameKey project) throws Exception {
+    grantApprove(project, SystemGroupBackend.CHANGE_OWNER, false);
   }
 
-  private String createMyChange() throws Exception {
+  private void grantApproveToAll(Project.NameKey project) throws Exception {
+    grantApprove(project, SystemGroupBackend.REGISTERED_USERS, false);
+  }
+
+  private void grantExclusiveApproveToAll(Project.NameKey project) throws Exception {
+    grantApprove(project, SystemGroupBackend.REGISTERED_USERS, true);
+  }
+
+  private void grantApprove(Project.NameKey project, AccountGroup.UUID groupUUID, boolean exclusive)
+      throws Exception {
+    grantLabel("Code-Review", -2, 2, project, "refs/heads/*", false, groupUUID, exclusive);
+  }
+
+  private void blockApproveForChangeOwner(Project.NameKey project) throws Exception {
+    blockLabel("Code-Review", -2, 2, SystemGroupBackend.CHANGE_OWNER, "refs/heads/*", project);
+  }
+
+  private String createMyChange(TestRepository<InMemoryRepository> testRepo) throws Exception {
     PushOneCommit push = pushFactory.create(db, user.getIdent(), testRepo);
     return push.to("refs/for/master").getChangeId();
   }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
index bf08ac9..66c61f7 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchIT.java
@@ -14,21 +14,23 @@
 
 package com.google.gerrit.acceptance.rest.project;
 
+import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.projects.BranchApi;
 import com.google.gerrit.extensions.api.projects.BranchInput;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.Url;
 import com.google.gerrit.reviewdb.client.Branch;
 import org.junit.Before;
 import org.junit.Test;
 
-@NoHttpd
 public class DeleteBranchIT extends AbstractDaemonTest {
 
   private Branch.NameKey branch;
@@ -86,6 +88,29 @@
     assertDeleteSucceeds();
   }
 
+  @Test
+  public void deleteBranchByRestWithoutRefsHeadsPrefix() throws Exception {
+    grantDelete();
+    String ref = branch.getShortName();
+    assertThat(ref).doesNotMatch(R_HEADS);
+    assertDeleteByRestSucceeds(ref);
+  }
+
+  @Test
+  public void deleteBranchByRestWithEncodedFullName() throws Exception {
+    grantDelete();
+    assertDeleteByRestSucceeds(Url.encode(branch.get()));
+  }
+
+  @Test
+  public void deleteBranchByRestFailsWithUnencodedFullName() throws Exception {
+    grantDelete();
+    RestResponse r =
+        userRestSession.delete("/projects/" + project.get() + "/branches/" + branch.get());
+    r.assertNotFound();
+    branch().get();
+  }
+
   private void blockForcePush() throws Exception {
     block(Permission.PUSH, ANONYMOUS_USERS, "refs/heads/*").setForce(true);
   }
@@ -106,6 +131,13 @@
     return gApi.projects().name(branch.getParentKey().get()).branch(branch.get());
   }
 
+  private void assertDeleteByRestSucceeds(String ref) throws Exception {
+    RestResponse r = userRestSession.delete("/projects/" + project.get() + "/branches/" + ref);
+    r.assertNoContent();
+    exception.expect(ResourceNotFoundException.class);
+    branch().get();
+  }
+
   private void assertDeleteSucceeds() throws Exception {
     String branchRev = branch().get().revision;
     branch().delete();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
index 1ca6c15..dc18a58 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteBranchesIT.java
@@ -16,6 +16,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.acceptance.rest.project.RefAssert.assertRefNames;
+import static java.util.stream.Collectors.toList;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
 import static org.junit.Assert.fail;
 
 import com.google.common.collect.ImmutableList;
@@ -37,7 +39,7 @@
 @NoHttpd
 public class DeleteBranchesIT extends AbstractDaemonTest {
   private static final ImmutableList<String> BRANCHES =
-      ImmutableList.of("refs/heads/test-1", "refs/heads/test-2", "refs/heads/test-3");
+      ImmutableList.of("refs/heads/test-1", "refs/heads/test-2", "test-3");
 
   @Before
   public void setUp() throws Exception {
@@ -138,7 +140,7 @@
     for (String branch : branches) {
       message
           .append("Cannot delete ")
-          .append(branch)
+          .append(prefixRef(branch))
           .append(": it doesn't exist or you do not have permission ")
           .append("to delete it\n");
     }
@@ -156,17 +158,22 @@
   private void assertRefUpdatedEvents(HashMap<String, RevCommit> revisions) throws Exception {
     for (String branch : revisions.keySet()) {
       RevCommit revision = revisions.get(branch);
-      eventRecorder.assertRefUpdatedEvents(project.get(), branch, null, revision, revision, null);
+      eventRecorder.assertRefUpdatedEvents(
+          project.get(), prefixRef(branch), null, revision, revision, null);
     }
   }
 
+  private String prefixRef(String ref) {
+    return ref.startsWith(R_HEADS) ? ref : R_HEADS + ref;
+  }
+
   private ProjectApi project() throws Exception {
     return gApi.projects().name(project.get());
   }
 
   private void assertBranches(List<String> branches) throws Exception {
     List<String> expected = Lists.newArrayList("HEAD", RefNames.REFS_CONFIG, "refs/heads/master");
-    expected.addAll(branches);
+    expected.addAll(branches.stream().map(b -> prefixRef(b)).collect(toList()));
     assertRefNames(expected, project().branches().get());
   }
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
index c9d7446..5608fb6 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagIT.java
@@ -16,9 +16,10 @@
 
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static org.eclipse.jgit.lib.Constants.R_TAGS;
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.RestResponse;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.projects.TagApi;
 import com.google.gerrit.extensions.api.projects.TagInput;
@@ -27,9 +28,8 @@
 import org.junit.Before;
 import org.junit.Test;
 
-@NoHttpd
 public class DeleteTagIT extends AbstractDaemonTest {
-  private final String TAG = "refs/tags/test";
+  private static final String TAG = "refs/tags/test";
 
   @Before
   public void setUp() throws Exception {
@@ -82,6 +82,14 @@
     assertDeleteSucceeds();
   }
 
+  @Test
+  public void deleteTagByRestWithoutRefsTagsPrefix() throws Exception {
+    grantDelete();
+    String ref = TAG.substring(R_TAGS.length());
+    RestResponse r = userRestSession.delete("/projects/" + project.get() + "/tags/" + ref);
+    r.assertNoContent();
+  }
+
   private void blockForcePush() throws Exception {
     block(Permission.PUSH, ANONYMOUS_USERS, "refs/tags/*").setForce(true);
   }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
index 69cd29a..8f24609 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/DeleteTagsIT.java
@@ -15,6 +15,8 @@
 package com.google.gerrit.acceptance.rest.project;
 
 import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.toList;
+import static org.eclipse.jgit.lib.Constants.R_TAGS;
 import static org.junit.Assert.fail;
 
 import com.google.common.collect.ImmutableList;
@@ -36,7 +38,7 @@
 @NoHttpd
 public class DeleteTagsIT extends AbstractDaemonTest {
   private static final ImmutableList<String> TAGS =
-      ImmutableList.of("refs/tags/test-1", "refs/tags/test-2", "refs/tags/test-3");
+      ImmutableList.of("refs/tags/test-1", "refs/tags/test-2", "refs/tags/test-3", "test-4");
 
   @Before
   public void setUp() throws Exception {
@@ -112,7 +114,7 @@
     for (String tag : tags) {
       message
           .append("Cannot delete ")
-          .append(tag)
+          .append(prefixRef(tag))
           .append(": it doesn't exist or you do not have permission ")
           .append("to delete it\n");
     }
@@ -122,18 +124,24 @@
   private HashMap<String, RevCommit> initialRevisions(List<String> tags) throws Exception {
     HashMap<String, RevCommit> result = new HashMap<>();
     for (String tag : tags) {
-      result.put(tag, getRemoteHead(project, tag));
+      String ref = prefixRef(tag);
+      result.put(ref, getRemoteHead(project, ref));
     }
     return result;
   }
 
   private void assertRefUpdatedEvents(HashMap<String, RevCommit> revisions) throws Exception {
     for (String tag : revisions.keySet()) {
-      RevCommit revision = revisions.get(tag);
-      eventRecorder.assertRefUpdatedEvents(project.get(), tag, null, revision, revision, null);
+      RevCommit revision = revisions.get(prefixRef(tag));
+      eventRecorder.assertRefUpdatedEvents(
+          project.get(), prefixRef(tag), null, revision, revision, null);
     }
   }
 
+  private String prefixRef(String ref) {
+    return ref.startsWith(R_TAGS) ? ref : R_TAGS + ref;
+  }
+
   private ProjectApi project() throws Exception {
     return gApi.projects().name(project.get());
   }
@@ -141,7 +149,9 @@
   private void assertTags(List<String> expected) throws Exception {
     List<TagInfo> actualTags = project().tags().get();
     Iterable<String> actualNames = Iterables.transform(actualTags, b -> b.ref);
-    assertThat(actualNames).containsExactlyElementsIn(expected).inOrder();
+    assertThat(actualNames)
+        .containsExactlyElementsIn(expected.stream().map(t -> prefixRef(t)).collect(toList()))
+        .inOrder();
   }
 
   private void assertTagsDeleted() throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
index a642d17..b62fd68 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListBranchesIT.java
@@ -16,6 +16,7 @@
 
 import static com.google.gerrit.acceptance.rest.project.RefAssert.assertRefNames;
 import static com.google.gerrit.acceptance.rest.project.RefAssert.assertRefs;
+import static org.junit.Assert.fail;
 
 import com.google.common.collect.ImmutableList;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -23,6 +24,7 @@
 import com.google.gerrit.acceptance.TestProjectInput;
 import com.google.gerrit.extensions.api.projects.BranchInfo;
 import com.google.gerrit.extensions.api.projects.ProjectApi.ListRefsRequest;
+import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.reviewdb.client.RefNames;
 import org.junit.Test;
@@ -147,8 +149,17 @@
             "refs/heads/someBranch1", "refs/heads/someBranch2", "refs/heads/someBranch3"),
         list().withSubstring("Branch").get());
 
+    assertRefNames(
+        ImmutableList.of(
+            "refs/heads/someBranch1", "refs/heads/someBranch2", "refs/heads/someBranch3"),
+        list().withSubstring("somebranch").get());
+
     // Using regex.
     assertRefNames(ImmutableList.of("refs/heads/master"), list().withRegex(".*ast.*r").get());
+    assertRefNames(ImmutableList.of(), list().withRegex(".*AST.*R").get());
+
+    // Conflicting options
+    assertBadRequest(list().withSubstring("somebranch").withRegex(".*ast.*r"));
   }
 
   private ListRefsRequest<BranchInfo> list() throws Exception {
@@ -162,4 +173,13 @@
     info.canDelete = canDelete ? true : null;
     return info;
   }
+
+  private void assertBadRequest(ListRefsRequest<BranchInfo> req) throws Exception {
+    try {
+      req.get();
+      fail("Expected BadRequestException");
+    } catch (BadRequestException e) {
+      // Expected
+    }
+  }
 }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
index e41d579..a31a34c 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/ListProjectsIT.java
@@ -112,6 +112,8 @@
     assertThatNameList(filter(gApi.projects().list().withPrefix(p).get()))
         .containsExactly(someOtherProject, someProject)
         .inOrder();
+    p = name("SOME");
+    assertThatNameList(filter(gApi.projects().list().withPrefix(p).get())).isEmpty();
   }
 
   @Test
@@ -161,6 +163,9 @@
     assertThatNameList(filter(gApi.projects().list().withSubstring("some").get()))
         .containsExactly(projectAwesome, someOtherProject, someProject)
         .inOrder();
+    assertThatNameList(filter(gApi.projects().list().withSubstring("SOME").get()))
+        .containsExactly(projectAwesome, someOtherProject, someProject)
+        .inOrder();
   }
 
   @Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
index f191681..ce43b08 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
@@ -17,6 +17,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static org.eclipse.jgit.lib.Constants.R_TAGS;
+import static org.junit.Assert.fail;
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
@@ -108,11 +109,17 @@
     result = getTags().withRegex("^tag-[C|D]$").get();
     assertTagList(FluentIterable.from(ImmutableList.of("tag-C", "tag-D")), result);
 
+    result = getTags().withRegex("^tag-[c|d]$").get();
+    assertTagList(FluentIterable.from(ImmutableList.of()), result);
+
     // With substring filter
     result = getTags().withSubstring("tag-").get();
     assertTagList(FluentIterable.from(testTags), result);
     result = getTags().withSubstring("ag-B").get();
     assertTagList(FluentIterable.from(ImmutableList.of("tag-B")), result);
+
+    // With conflicting options
+    assertBadRequest(getTags().withSubstring("ag-B").withRegex("^tag-[c|d]$"));
   }
 
   @Test
@@ -344,4 +351,13 @@
   private TagApi tag(String tagname) throws Exception {
     return gApi.projects().name(project.get()).tag(tagname);
   }
+
+  private void assertBadRequest(ListRefsRequest<TagInfo> req) throws Exception {
+    try {
+      req.get();
+      fail("Expected BadRequestException");
+    } catch (BadRequestException e) {
+      // Expected
+    }
+  }
 }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
index 8d9885c..6c06753 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/change/GetRelatedIT.java
@@ -517,7 +517,7 @@
   }
 
   @Test
-  @GerritConfig(name = "index.testReindexAfterUpdate", value = "false")
+  @GerritConfig(name = "index.autoReindexIfStale", value = "false")
   public void getRelatedForStaleChange() throws Exception {
     RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
index 9d15daf..87ca2a0 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
@@ -120,7 +120,7 @@
     // unintentional auto-rebuilding of the change in NoteDb during the read
     // path of the reindex-if-stale check. For the purposes of this test, we
     // want precise control over when auto-rebuilding happens.
-    cfg.setBoolean("index", null, "testReindexAfterUpdate", false);
+    cfg.setBoolean("index", null, "autoReindexIfStale", false);
 
     return cfg;
   }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
index 6e315de..bcdc866 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
@@ -18,7 +18,6 @@
 import static com.google.common.truth.TruthJUnit.assume;
 
 import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.acceptance.GerritConfig;
 import com.google.gerrit.acceptance.NoHttpd;
@@ -93,9 +92,11 @@
       }
     }
 
-    assertThat(entryNames.size()).isEqualTo(1);
-    assertThat(Iterables.getOnlyElement(entryNames))
-        .isEqualTo(String.format("%s/%s", abbreviated, PushOneCommit.FILE_NAME));
+    assertThat(entryNames)
+        .containsExactly(
+            String.format("%s/", abbreviated),
+            String.format("%s/%s", abbreviated, PushOneCommit.FILE_NAME))
+        .inOrder();
   }
 
   private String command(PushOneCommit.Result r, String abbreviated) {
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebType.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebType.java
index 248de49..9cc408b 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebType.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebType.java
@@ -24,6 +24,7 @@
   private String project;
   private String revision;
   private String rootTree;
+  private String tag;
 
   private char pathSeparator = '/';
   private boolean urlEncode = true;
@@ -56,6 +57,20 @@
     branch = str;
   }
 
+  /** @return parameterized string for the tag URL. */
+  public String getTag() {
+    return tag;
+  }
+
+  /**
+   * Set the parameterized string for the tag URL.
+   *
+   * @param str new string.
+   */
+  public void setTag(String str) {
+    tag = str;
+  }
+
   /** @return parameterized string for the file URL. */
   public String getFile() {
     return file;
diff --git a/gerrit-extension-api/pom.xml b/gerrit-extension-api/pom.xml
index 61d0bec..bc028a6 100644
--- a/gerrit-extension-api/pom.xml
+++ b/gerrit-extension-api/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-extension-api</artifactId>
-  <version>2.14.1-SNAPSHOT</version>
+  <version>2.14.1</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Extension API</name>
   <description>API for Gerrit Extensions</description>
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
index 876f85a..b88097c 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/AccountApi.java
@@ -105,167 +105,170 @@
    */
   class NotImplemented implements AccountApi {
     @Override
-    public AccountInfo get() {
+    public AccountInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public boolean getActive() {
+    public boolean getActive() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void setActive(boolean active) {
+    public void setActive(boolean active) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String getAvatarUrl(int size) {
+    public String getAvatarUrl(int size) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GeneralPreferencesInfo getPreferences() {
+    public GeneralPreferencesInfo getPreferences() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GeneralPreferencesInfo setPreferences(GeneralPreferencesInfo in) {
+    public GeneralPreferencesInfo setPreferences(GeneralPreferencesInfo in)
+        throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffPreferencesInfo getDiffPreferences() {
+    public DiffPreferencesInfo getDiffPreferences() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffPreferencesInfo setDiffPreferences(DiffPreferencesInfo in) {
+    public DiffPreferencesInfo setDiffPreferences(DiffPreferencesInfo in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public EditPreferencesInfo getEditPreferences() {
+    public EditPreferencesInfo getEditPreferences() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public EditPreferencesInfo setEditPreferences(EditPreferencesInfo in) {
+    public EditPreferencesInfo setEditPreferences(EditPreferencesInfo in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<ProjectWatchInfo> getWatchedProjects() {
+    public List<ProjectWatchInfo> getWatchedProjects() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<ProjectWatchInfo> setWatchedProjects(List<ProjectWatchInfo> in) {
+    public List<ProjectWatchInfo> setWatchedProjects(List<ProjectWatchInfo> in)
+        throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteWatchedProjects(List<ProjectWatchInfo> in) {
+    public void deleteWatchedProjects(List<ProjectWatchInfo> in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void starChange(String changeId) {
+    public void starChange(String changeId) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void unstarChange(String changeId) {
+    public void unstarChange(String changeId) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void setStars(String changeId, StarsInput input) {
+    public void setStars(String changeId, StarsInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SortedSet<String> getStars(String changeId) {
+    public SortedSet<String> getStars(String changeId) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<ChangeInfo> getStarredChanges() {
+    public List<ChangeInfo> getStarredChanges() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<EmailInfo> getEmails() {
+    public List<EmailInfo> getEmails() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void addEmail(EmailInput input) {
+    public void addEmail(EmailInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteEmail(String email) {
+    public void deleteEmail(String email) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void setStatus(String status) {
+    public void setStatus(String status) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<SshKeyInfo> listSshKeys() {
+    public List<SshKeyInfo> listSshKeys() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SshKeyInfo addSshKey(String key) {
+    public SshKeyInfo addSshKey(String key) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteSshKey(int seq) {
+    public void deleteSshKey(int seq) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, GpgKeyInfo> putGpgKeys(List<String> add, List<String> remove) {
+    public Map<String, GpgKeyInfo> putGpgKeys(List<String> add, List<String> remove)
+        throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GpgKeyApi gpgKey(String id) {
+    public GpgKeyApi gpgKey(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, GpgKeyInfo> listGpgKeys() {
+    public Map<String, GpgKeyInfo> listGpgKeys() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<AgreementInfo> listAgreements() {
+    public List<AgreementInfo> listAgreements() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void signAgreement(String agreementName) {
+    public void signAgreement(String agreementName) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void index() {
+    public void index() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<AccountExternalIdInfo> getExternalIds() {
+    public List<AccountExternalIdInfo> getExternalIds() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteExternalIds(List<String> externalIds) {
+    public void deleteExternalIds(List<String> externalIds) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
index eab3233..e92d229 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/Accounts.java
@@ -204,47 +204,47 @@
    */
   class NotImplemented implements Accounts {
     @Override
-    public AccountApi id(String id) {
+    public AccountApi id(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountApi id(int id) {
+    public AccountApi id(int id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountApi self() {
+    public AccountApi self() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountApi create(String username) {
+    public AccountApi create(String username) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountApi create(AccountInput input) {
+    public AccountApi create(AccountInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SuggestAccountsRequest suggestAccounts() {
+    public SuggestAccountsRequest suggestAccounts() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SuggestAccountsRequest suggestAccounts(String query) {
+    public SuggestAccountsRequest suggestAccounts(String query) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public QueryRequest query() {
+    public QueryRequest query() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public QueryRequest query(String query) {
+    public QueryRequest query(String query) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/GpgKeyApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/GpgKeyApi.java
index a8a761d..6757a05 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/GpgKeyApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/accounts/GpgKeyApi.java
@@ -29,12 +29,12 @@
    */
   class NotImplemented implements GpgKeyApi {
     @Override
-    public GpgKeyInfo get() {
+    public GpgKeyInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index 27fdc18..8c1ebf3 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -257,223 +257,224 @@
     }
 
     @Override
-    public RevisionApi current() {
+    public RevisionApi current() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public RevisionApi revision(int id) {
+    public RevisionApi revision(int id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ReviewerApi reviewer(String id) {
+    public ReviewerApi reviewer(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public RevisionApi revision(String id) {
+    public RevisionApi revision(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void abandon() {
+    public void abandon() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void abandon(AbandonInput in) {
+    public void abandon(AbandonInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void restore() {
+    public void restore() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void restore(RestoreInput in) {
+    public void restore(RestoreInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void move(String destination) {
+    public void move(String destination) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void move(MoveInput in) {
+    public void move(MoveInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi revert() {
+    public ChangeApi revert() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi revert(RevertInput in) {
+    public ChangeApi revert(RevertInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void publish() {
+    public void publish() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void rebase() {
+    public void rebase() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void rebase(RebaseInput in) {
+    public void rebase(RebaseInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String topic() {
+    public String topic() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void topic(String topic) {
+    public void topic(String topic) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public IncludedInInfo includedIn() {
+    public IncludedInInfo includedIn() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void addReviewer(AddReviewerInput in) {
+    public void addReviewer(AddReviewerInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void addReviewer(String in) {
+    public void addReviewer(String in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SuggestedReviewersRequest suggestReviewers() {
+    public SuggestedReviewersRequest suggestReviewers() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SuggestedReviewersRequest suggestReviewers(String query) {
+    public SuggestedReviewersRequest suggestReviewers(String query) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo get(EnumSet<ListChangesOption> options) {
+    public ChangeInfo get(EnumSet<ListChangesOption> options) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo get() {
+    public ChangeInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo info() {
+    public ChangeInfo info() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public EditInfo getEdit() {
+    public EditInfo getEdit() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeEditApi edit() {
+    public ChangeEditApi edit() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void setHashtags(HashtagsInput input) {
+    public void setHashtags(HashtagsInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Set<String> getHashtags() {
+    public Set<String> getHashtags() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountInfo setAssignee(AssigneeInput input) {
+    public AccountInfo setAssignee(AssigneeInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountInfo getAssignee() {
+    public AccountInfo getAssignee() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<AccountInfo> getPastAssignees() {
+    public List<AccountInfo> getPastAssignees() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public AccountInfo deleteAssignee() {
+    public AccountInfo deleteAssignee() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, List<CommentInfo>> comments() {
+    public Map<String, List<CommentInfo>> comments() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, List<RobotCommentInfo>> robotComments() {
+    public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, List<CommentInfo>> drafts() {
+    public Map<String, List<CommentInfo>> drafts() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo check() {
+    public ChangeInfo check() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo check(FixInput fix) {
+    public ChangeInfo check(FixInput fix) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void index() {
+    public void index() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<ChangeInfo> submittedTogether() {
+    public List<ChangeInfo> submittedTogether() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SubmittedTogetherInfo submittedTogether(EnumSet<SubmittedTogetherOption> options) {
+    public SubmittedTogetherInfo submittedTogether(EnumSet<SubmittedTogetherOption> options)
+        throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
     public SubmittedTogetherInfo submittedTogether(
-        EnumSet<ListChangesOption> a, EnumSet<SubmittedTogetherOption> b) {
+        EnumSet<ListChangesOption> a, EnumSet<SubmittedTogetherOption> b) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeInfo createMergePatchSet(MergePatchSetInput in) {
+    public ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeEditApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeEditApi.java
index 33f17e9..9d0275a 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeEditApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ChangeEditApi.java
@@ -156,67 +156,67 @@
    */
   class NotImplemented implements ChangeEditApi {
     @Override
-    public Optional<EditInfo> get() {
+    public Optional<EditInfo> get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void create() {
+    public void create() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void rebase() {
+    public void rebase() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void publish() {
+    public void publish() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void publish(PublishChangeEditInput publishChangeEditInput) {
+    public void publish(PublishChangeEditInput publishChangeEditInput) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Optional<BinaryResult> getFile(String filePath) {
+    public Optional<BinaryResult> getFile(String filePath) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void renameFile(String oldFilePath, String newFilePath) {
+    public void renameFile(String oldFilePath, String newFilePath) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void restoreFile(String filePath) {
+    public void restoreFile(String filePath) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void modifyFile(String filePath, RawInput newContent) {
+    public void modifyFile(String filePath, RawInput newContent) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteFile(String filePath) {
+    public void deleteFile(String filePath) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String getCommitMessage() {
+    public String getCommitMessage() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void modifyCommitMessage(String newCommitMessage) {
+    public void modifyCommitMessage(String newCommitMessage) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
index 8cac103..d14ddfe 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/Changes.java
@@ -138,22 +138,22 @@
    */
   class NotImplemented implements Changes {
     @Override
-    public ChangeApi id(int id) {
+    public ChangeApi id(int id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi id(String triplet) {
+    public ChangeApi id(String triplet) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi id(String project, String branch, String id) {
+    public ChangeApi id(String project, String branch, String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi create(ChangeInput in) {
+    public ChangeApi create(ChangeInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/CommentApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/CommentApi.java
index 78f2b89..a6d64a6 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/CommentApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/CommentApi.java
@@ -27,7 +27,7 @@
    */
   class NotImplemented implements CommentApi {
     @Override
-    public CommentInfo get() {
+    public CommentInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/DraftApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/DraftApi.java
index d31e4ae..fa663a5 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/DraftApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/DraftApi.java
@@ -29,12 +29,12 @@
    */
   class NotImplemented extends CommentApi.NotImplemented implements DraftApi {
     @Override
-    public CommentInfo update(DraftInput in) {
+    public CommentInfo update(DraftInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/FileApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/FileApi.java
index a319cbe..e2bd074 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/FileApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/FileApi.java
@@ -89,27 +89,27 @@
    */
   class NotImplemented implements FileApi {
     @Override
-    public BinaryResult content() {
+    public BinaryResult content() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffInfo diff() {
+    public DiffInfo diff() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffInfo diff(String base) {
+    public DiffInfo diff(String base) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffInfo diff(int parent) {
+    public DiffInfo diff(int parent) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffRequest diffRequest() {
+    public DiffRequest diffRequest() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewerApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewerApi.java
index 078f828..70e456d 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewerApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewerApi.java
@@ -36,27 +36,27 @@
    */
   class NotImplemented implements ReviewerApi {
     @Override
-    public Map<String, Short> votes() {
+    public Map<String, Short> votes() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteVote(String label) {
+    public void deleteVote(String label) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteVote(DeleteVoteInput input) {
+    public void deleteVote(DeleteVoteInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void remove() {
+    public void remove() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void remove(DeleteReviewerInput input) {
+    public void remove(DeleteReviewerInput input) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
index 5dd4ba4..f5f6fbf 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
@@ -140,87 +140,87 @@
    */
   class NotImplemented implements RevisionApi {
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void review(ReviewInput in) {
+    public void review(ReviewInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void submit() {
+    public void submit() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void submit(SubmitInput in) {
+    public void submit(SubmitInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void publish() {
+    public void publish() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi cherryPick(CherryPickInput in) {
+    public ChangeApi cherryPick(CherryPickInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi rebase() {
+    public ChangeApi rebase() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChangeApi rebase(RebaseInput in) {
+    public ChangeApi rebase(RebaseInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public boolean canRebase() {
+    public boolean canRebase() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public RevisionReviewerApi reviewer(String id) {
+    public RevisionReviewerApi reviewer(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void setReviewed(String path, boolean reviewed) {
+    public void setReviewed(String path, boolean reviewed) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Set<String> reviewed() {
+    public Set<String> reviewed() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public MergeableInfo mergeable() {
+    public MergeableInfo mergeable() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public MergeableInfo mergeableOtherBranches() {
+    public MergeableInfo mergeableOtherBranches() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, FileInfo> files(String base) {
+    public Map<String, FileInfo> files(String base) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, FileInfo> files(int parentNum) {
+    public Map<String, FileInfo> files(int parentNum) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, FileInfo> files() {
+    public Map<String, FileInfo> files() throws RestApiException {
       throw new NotImplementedException();
     }
 
@@ -230,107 +230,107 @@
     }
 
     @Override
-    public Map<String, List<CommentInfo>> comments() {
+    public Map<String, List<CommentInfo>> comments() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, List<RobotCommentInfo>> robotComments() {
+    public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<CommentInfo> commentsAsList() {
+    public List<CommentInfo> commentsAsList() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<CommentInfo> draftsAsList() {
+    public List<CommentInfo> draftsAsList() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<RobotCommentInfo> robotCommentsAsList() {
+    public List<RobotCommentInfo> robotCommentsAsList() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, List<CommentInfo>> drafts() {
+    public Map<String, List<CommentInfo>> drafts() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DraftApi createDraft(DraftInput in) {
+    public DraftApi createDraft(DraftInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DraftApi draft(String id) {
+    public DraftApi draft(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public CommentApi comment(String id) {
+    public CommentApi comment(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public RobotCommentApi robotComment(String id) {
+    public RobotCommentApi robotComment(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BinaryResult patch() {
+    public BinaryResult patch() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BinaryResult patch(String path) {
+    public BinaryResult patch(String path) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public Map<String, ActionInfo> actions() {
+    public Map<String, ActionInfo> actions() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SubmitType submitType() {
+    public SubmitType submitType() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BinaryResult submitPreview() {
+    public BinaryResult submitPreview() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BinaryResult submitPreview(String format) {
+    public BinaryResult submitPreview(String format) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public SubmitType testSubmitType(TestSubmitRuleInput in) {
+    public SubmitType testSubmitType(TestSubmitRuleInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public MergeListRequest getMergeList() {
+    public MergeListRequest getMergeList() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void description(String description) {
+    public void description(String description) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String description() {
+    public String description() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String etag() {
+    public String etag() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionReviewerApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionReviewerApi.java
index 681ef4f..ec2d5d6 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionReviewerApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RevisionReviewerApi.java
@@ -31,17 +31,17 @@
    */
   class NotImplemented implements RevisionReviewerApi {
     @Override
-    public Map<String, Short> votes() {
+    public Map<String, Short> votes() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteVote(String label) {
+    public void deleteVote(String label) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteVote(DeleteVoteInput input) {
+    public void deleteVote(DeleteVoteInput input) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RobotCommentApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RobotCommentApi.java
index 23e65ae..e44f21f 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RobotCommentApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/RobotCommentApi.java
@@ -27,7 +27,7 @@
    */
   class NotImplemented implements RobotCommentApi {
     @Override
-    public RobotCommentInfo get() {
+    public RobotCommentInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
index 97f4af0..07b3ab2 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/config/Server.java
@@ -40,32 +40,34 @@
    */
   class NotImplemented implements Server {
     @Override
-    public String getVersion() {
+    public String getVersion() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ServerInfo getInfo() {
+    public ServerInfo getInfo() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GeneralPreferencesInfo getDefaultPreferences() {
+    public GeneralPreferencesInfo getDefaultPreferences() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GeneralPreferencesInfo setDefaultPreferences(GeneralPreferencesInfo in) {
+    public GeneralPreferencesInfo setDefaultPreferences(GeneralPreferencesInfo in)
+        throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffPreferencesInfo getDefaultDiffPreferences() {
+    public DiffPreferencesInfo getDefaultDiffPreferences() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public DiffPreferencesInfo setDefaultDiffPreferences(DiffPreferencesInfo in) {
+    public DiffPreferencesInfo setDefaultDiffPreferences(DiffPreferencesInfo in)
+        throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/GroupApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/GroupApi.java
index 93effe2..0d4742b 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/GroupApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/GroupApi.java
@@ -155,57 +155,57 @@
    */
   class NotImplemented implements GroupApi {
     @Override
-    public GroupInfo get() {
+    public GroupInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GroupInfo detail() {
+    public GroupInfo detail() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String name() {
+    public String name() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void name(String name) {
+    public void name(String name) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GroupInfo owner() {
+    public GroupInfo owner() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void owner(String owner) {
+    public void owner(String owner) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String description() {
+    public String description() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void description(String description) {
+    public void description(String description) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GroupOptionsInfo options() {
+    public GroupOptionsInfo options() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void options(GroupOptionsInfo options) {
+    public void options(GroupOptionsInfo options) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<AccountInfo> members() {
+    public List<AccountInfo> members() throws RestApiException {
       throw new NotImplementedException();
     }
 
@@ -215,27 +215,27 @@
     }
 
     @Override
-    public void addMembers(String... members) {
+    public void addMembers(String... members) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void removeMembers(String... members) {
+    public void removeMembers(String... members) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<GroupInfo> includedGroups() {
+    public List<GroupInfo> includedGroups() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void addGroups(String... groups) {
+    public void addGroups(String... groups) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void removeGroups(String... groups) {
+    public void removeGroups(String... groups) throws RestApiException {
       throw new NotImplementedException();
     }
 
@@ -245,7 +245,7 @@
     }
 
     @Override
-    public void index() {
+    public void index() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/Groups.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/Groups.java
index c874061..a560fdf 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/Groups.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/groups/Groups.java
@@ -271,17 +271,17 @@
    */
   class NotImplemented implements Groups {
     @Override
-    public GroupApi id(String id) {
+    public GroupApi id(String id) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GroupApi create(String name) {
+    public GroupApi create(String name) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public GroupApi create(GroupInput input) {
+    public GroupApi create(GroupInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
index bf939f1..995f41a 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/BranchApi.java
@@ -34,22 +34,22 @@
    */
   class NotImplemented implements BranchApi {
     @Override
-    public BranchApi create(BranchInput in) {
+    public BranchApi create(BranchInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BranchInfo get() {
+    public BranchInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BinaryResult file(String path) {
+    public BinaryResult file(String path) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ChildProjectApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ChildProjectApi.java
index 88cca66..146ef27 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ChildProjectApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ChildProjectApi.java
@@ -29,12 +29,12 @@
    */
   class NotImplemented implements ChildProjectApi {
     @Override
-    public ProjectInfo get() {
+    public ProjectInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectInfo get(boolean recursive) {
+    public ProjectInfo get(boolean recursive) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
index dc2f899..a5221b9 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectApi.java
@@ -130,47 +130,47 @@
    */
   class NotImplemented implements ProjectApi {
     @Override
-    public ProjectApi create() {
+    public ProjectApi create() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectApi create(ProjectInput in) {
+    public ProjectApi create(ProjectInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectInfo get() {
+    public ProjectInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public String description() {
+    public String description() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectAccessInfo access() {
+    public ProjectAccessInfo access() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ConfigInfo config() {
+    public ConfigInfo config() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ConfigInfo config(ConfigInput in) {
+    public ConfigInfo config(ConfigInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectAccessInfo access(ProjectAccessInput p) {
+    public ProjectAccessInfo access(ProjectAccessInput p) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void description(DescriptionInput in) {
+    public void description(DescriptionInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
@@ -185,37 +185,37 @@
     }
 
     @Override
-    public List<ProjectInfo> children() {
+    public List<ProjectInfo> children() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public List<ProjectInfo> children(boolean recursive) {
+    public List<ProjectInfo> children(boolean recursive) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ChildProjectApi child(String name) {
+    public ChildProjectApi child(String name) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public BranchApi branch(String ref) {
+    public BranchApi branch(String ref) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public TagApi tag(String ref) {
+    public TagApi tag(String ref) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteBranches(DeleteBranchesInput in) {
+    public void deleteBranches(DeleteBranchesInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void deleteTags(DeleteTagsInput in) {
+    public void deleteTags(DeleteTagsInput in) throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
index bb9ebc9..e4a659c 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/Projects.java
@@ -177,17 +177,17 @@
    */
   class NotImplemented implements Projects {
     @Override
-    public ProjectApi name(String name) {
+    public ProjectApi name(String name) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectApi create(ProjectInput in) {
+    public ProjectApi create(ProjectInput in) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public ProjectApi create(String name) {
+    public ProjectApi create(String name) throws RestApiException {
       throw new NotImplementedException();
     }
 
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagApi.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagApi.java
index ad30e03..39efeac 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagApi.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagApi.java
@@ -30,17 +30,17 @@
    */
   class NotImplemented implements TagApi {
     @Override
-    public TagApi create(TagInput input) {
+    public TagApi create(TagInput input) throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public TagInfo get() {
+    public TagInfo get() throws RestApiException {
       throw new NotImplementedException();
     }
 
     @Override
-    public void delete() {
+    public void delete() throws RestApiException {
       throw new NotImplementedException();
     }
   }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagInfo.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagInfo.java
index ccfea46..c7b1b94 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagInfo.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/TagInfo.java
@@ -15,16 +15,20 @@
 package com.google.gerrit.extensions.api.projects;
 
 import com.google.gerrit.extensions.common.GitPerson;
+import com.google.gerrit.extensions.common.WebLinkInfo;
+import java.util.List;
 
 public class TagInfo extends RefInfo {
   public String object;
   public String message;
   public GitPerson tagger;
+  public List<WebLinkInfo> webLinks;
 
-  public TagInfo(String ref, String revision, boolean canDelete) {
+  public TagInfo(String ref, String revision, boolean canDelete, List<WebLinkInfo> webLinks) {
     this.ref = ref;
     this.revision = revision;
     this.canDelete = canDelete;
+    this.webLinks = webLinks;
   }
 
   public TagInfo(
@@ -33,10 +37,12 @@
       String object,
       String message,
       GitPerson tagger,
-      boolean canDelete) {
-    this(ref, revision, canDelete);
+      boolean canDelete,
+      List<WebLinkInfo> webLinks) {
+    this(ref, revision, canDelete, webLinks);
     this.object = object;
     this.message = message;
     this.tagger = tagger;
+    this.webLinks = webLinks;
   }
 }
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/EditPreferencesInfo.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/EditPreferencesInfo.java
index 84c61b7..7ab22e1 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/EditPreferencesInfo.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/EditPreferencesInfo.java
@@ -27,6 +27,7 @@
   public Boolean hideLineNumbers;
   public Boolean matchBrackets;
   public Boolean lineWrapping;
+  public Boolean indentWithTabs;
   public Boolean autoCloseBrackets;
   public Boolean showBase;
   public Theme theme;
@@ -45,6 +46,7 @@
     i.hideLineNumbers = false;
     i.matchBrackets = true;
     i.lineWrapping = false;
+    i.indentWithTabs = false;
     i.autoCloseBrackets = false;
     i.showBase = false;
     i.theme = Theme.DEFAULT;
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/webui/TagWebLink.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/webui/TagWebLink.java
new file mode 100644
index 0000000..14ccb4a
--- /dev/null
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/webui/TagWebLink.java
@@ -0,0 +1,38 @@
+// 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.extensions.webui;
+
+import com.google.gerrit.extensions.annotations.ExtensionPoint;
+import com.google.gerrit.extensions.common.WebLinkInfo;
+
+@ExtensionPoint
+public interface TagWebLink extends WebLink {
+
+  /**
+   * {@link com.google.gerrit.extensions.common.WebLinkInfo} describing a link from a tag to an
+   * external service.
+   *
+   * <p>In order for the web link to be visible {@link
+   * com.google.gerrit.extensions.common.WebLinkInfo#url} and {@link
+   * com.google.gerrit.extensions.common.WebLinkInfo#name} must be set.
+   *
+   * <p>
+   *
+   * @param projectName Name of the project
+   * @param tagName Name of the tag
+   * @return WebLinkInfo that links to tag in external service, null if there should be no link.
+   */
+  WebLinkInfo getTagWebLink(String projectName, String tagName);
+}
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/DeleteGpgKey.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/DeleteGpgKey.java
index 50bf57b..f95cee2 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/DeleteGpgKey.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/DeleteGpgKey.java
@@ -25,7 +25,6 @@
 import com.google.gerrit.gpg.server.DeleteGpgKey.Input;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.ExternalId;
 import com.google.gerrit.server.account.ExternalIdsUpdate;
 import com.google.gwtorm.server.OrmException;
@@ -45,7 +44,6 @@
   private final Provider<PersonIdent> serverIdent;
   private final Provider<ReviewDb> db;
   private final Provider<PublicKeyStore> storeProvider;
-  private final AccountCache accountCache;
   private final ExternalIdsUpdate.User externalIdsUpdateFactory;
 
   @Inject
@@ -53,12 +51,10 @@
       @GerritPersonIdent Provider<PersonIdent> serverIdent,
       Provider<ReviewDb> db,
       Provider<PublicKeyStore> storeProvider,
-      AccountCache accountCache,
       ExternalIdsUpdate.User externalIdsUpdateFactory) {
     this.serverIdent = serverIdent;
     this.db = db;
     this.storeProvider = storeProvider;
-    this.accountCache = accountCache;
     this.externalIdsUpdateFactory = externalIdsUpdateFactory;
   }
 
@@ -74,7 +70,6 @@
             rsrc.getUser().getAccountId(),
             ExternalId.Key.create(
                 SCHEME_GPGKEY, BaseEncoding.base16().encode(key.getFingerprint())));
-    accountCache.evict(rsrc.getUser().getAccountId());
 
     try (PublicKeyStore store = storeProvider.get()) {
       store.remove(rsrc.getKeyRing().getPublicKey().getFingerprint());
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/PostGpgKeys.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/PostGpgKeys.java
index 7b825b1..165402c 100644
--- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/PostGpgKeys.java
+++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/server/PostGpgKeys.java
@@ -44,7 +44,6 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.account.AccountResource;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.ExternalId;
@@ -89,7 +88,6 @@
   private final Provider<PublicKeyStore> storeProvider;
   private final GerritPublicKeyChecker.Factory checkerFactory;
   private final AddKeySender.Factory addKeyFactory;
-  private final AccountCache accountCache;
   private final Provider<InternalAccountQuery> accountQueryProvider;
   private final ExternalIdsUpdate.User externalIdsUpdateFactory;
 
@@ -101,7 +99,6 @@
       Provider<PublicKeyStore> storeProvider,
       GerritPublicKeyChecker.Factory checkerFactory,
       AddKeySender.Factory addKeyFactory,
-      AccountCache accountCache,
       Provider<InternalAccountQuery> accountQueryProvider,
       ExternalIdsUpdate.User externalIdsUpdateFactory) {
     this.serverIdent = serverIdent;
@@ -110,7 +107,6 @@
     this.storeProvider = storeProvider;
     this.checkerFactory = checkerFactory;
     this.addKeyFactory = addKeyFactory;
-    this.accountCache = accountCache;
     this.accountQueryProvider = accountQueryProvider;
     this.externalIdsUpdateFactory = externalIdsUpdateFactory;
   }
@@ -148,7 +144,6 @@
       externalIdsUpdateFactory
           .create()
           .replace(db.get(), rsrc.getUser().getAccountId(), extIdKeysToRemove, newExtIds);
-      accountCache.evict(rsrc.getUser().getAccountId());
       return toJson(newKeys, toRemove, store, rsrc.getUser());
     }
   }
diff --git a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index 862930f..d1bbc5e 100644
--- a/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/gerrit-gpg/src/test/java/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -407,7 +407,6 @@
     assertThat(store.save(cb)).isAnyOf(NEW, FAST_FORWARD, FORCED);
 
     externalIdsUpdateFactory.create().insert(db, newExtIds);
-    accountCache.evict(user.getAccountId());
   }
 
   private TestKey add(TestKey k, IdentifiedUser user) throws Exception {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
index 9f87672..20bc2746 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchSuggestOracle.java
@@ -54,7 +54,6 @@
                           if ("self".startsWith(request.getQuery())) {
                             final ArrayList<SuggestOracle.Suggestion> r =
                                 new ArrayList<>(response.getSuggestions().size() + 1);
-                            r.addAll(response.getSuggestions());
                             r.add(
                                 new SuggestOracle.Suggestion() {
                                   @Override
@@ -67,6 +66,7 @@
                                     return "self";
                                   }
                                 });
+                            r.addAll(response.getSuggestions());
                             response.setSuggestions(r);
                           }
                           done.onSuggestionsReady(request, response);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java
index 8fcea85..9cd2f17 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/EditPreferences.java
@@ -33,6 +33,7 @@
     p.hideLineNumbers(in.hideLineNumbers);
     p.matchBrackets(in.matchBrackets);
     p.lineWrapping(in.lineWrapping);
+    p.indentWithTabs(in.indentWithTabs);
     p.autoCloseBrackets(in.autoCloseBrackets);
     p.showBase(in.showBase);
     p.theme(in.theme);
@@ -52,6 +53,7 @@
     p.hideLineNumbers = hideLineNumbers();
     p.matchBrackets = matchBrackets();
     p.lineWrapping = lineWrapping();
+    p.indentWithTabs = indentWithTabs();
     p.autoCloseBrackets = autoCloseBrackets();
     p.showBase = showBase();
     p.theme = theme();
@@ -94,6 +96,8 @@
 
   public final native void lineWrapping(boolean w) /*-{ this.line_wrapping = w }-*/;
 
+  public final native void indentWithTabs(boolean w) /*-{ this.indent_with_tabs = w }-*/;
+
   public final native void autoCloseBrackets(boolean c) /*-{ this.auto_close_brackets = c }-*/;
 
   public final native void showBase(boolean s) /*-{ this.show_base = s }-*/;
@@ -144,6 +148,8 @@
 
   public final native boolean lineWrapping() /*-{ return this.line_wrapping || false }-*/;
 
+  public final native boolean indentWithTabs() /*-{ return this.indent_with_tabs || false }-*/;
+
   public final native boolean
       autoCloseBrackets() /*-{ return this.auto_close_brackets || false }-*/;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
index d7fb072..cc6a136 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
@@ -179,6 +179,8 @@
 
   String initialRevision();
 
+  String revision();
+
   String buttonAddBranch();
 
   String buttonDeleteBranch();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index 465bcfc..1588ea6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -85,6 +85,7 @@
 columnTagName = Tag Name
 columnTagRevision = Revision
 initialRevision = Initial Revision
+revision = Revision
 buttonAddBranch = Create Branch
 buttonAddTag = Create Tag
 buttonDeleteBranch = Delete
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
index dd46c5c..092c6e1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/CreateProjectScreen.java
@@ -212,6 +212,7 @@
 
           @Override
           protected void populate(final int row, final ProjectInfo k) {
+            populateState(row, k);
             final Anchor projectLink = new Anchor(k.name());
             projectLink.addClickHandler(
                 new ClickHandler() {
@@ -222,8 +223,8 @@
                   }
                 });
 
-            table.setWidget(row, 2, projectLink);
-            table.setText(row, 3, k.description());
+            table.setWidget(row, ProjectsTable.C_NAME, projectLink);
+            table.setText(row, ProjectsTable.C_DESCRIPTION, k.description());
 
             setRowItem(row, k);
           }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
index 604a0dc..9166c56 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java
@@ -35,7 +35,6 @@
 import com.google.gwt.user.client.History;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 import java.util.List;
@@ -109,25 +108,8 @@
           }
 
           @Override
-          protected void populate(final int row, final ProjectInfo k) {
-            Image state = new Image();
-            switch (k.state()) {
-              case HIDDEN:
-                state.setResource(Gerrit.RESOURCES.redNot());
-                state.setTitle(Util.toLongString(k.state()));
-                table.setWidget(row, ProjectsTable.C_STATE, state);
-                break;
-              case READ_ONLY:
-                state.setResource(Gerrit.RESOURCES.readOnly());
-                state.setTitle(Util.toLongString(k.state()));
-                table.setWidget(row, ProjectsTable.C_STATE, state);
-                break;
-              case ACTIVE:
-              default:
-                // Intentionally left blank, do not show an icon when active.
-                break;
-            }
-
+          protected void populate(int row, ProjectInfo k) {
+            populateState(row, k);
             FlowPanel fp = new FlowPanel();
             fp.add(new ProjectSearchLink(k.name_key()));
             fp.add(new HighlightingInlineHyperlink(k.name(), link(k), match));
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
index b89139c..45d0fdb 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectTagsScreen.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.client.VoidResult;
 import com.google.gerrit.client.access.AccessMap;
 import com.google.gerrit.client.access.ProjectAccessInfo;
+import com.google.gerrit.client.info.WebLinkInfo;
 import com.google.gerrit.client.projects.ProjectApi;
 import com.google.gerrit.client.projects.TagInfo;
 import com.google.gerrit.client.rpc.GerritCallback;
@@ -150,7 +151,7 @@
             }
           }
         });
-    addGrid.setText(1, 0, AdminConstants.I.initialRevision() + ":");
+    addGrid.setText(1, 0, AdminConstants.I.revision() + ":");
     addGrid.setWidget(1, 1, irevTxtBox);
 
     addTag = new Button(AdminConstants.I.buttonAddTag());
@@ -301,6 +302,7 @@
       fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
       fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
       fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
+      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
 
       updateDeleteHandler =
           new ValueChangeHandler<Boolean>() {
@@ -431,12 +433,21 @@
         table.setText(row, 3, "");
       }
 
+      FlowPanel actionsPanel = new FlowPanel();
+      if (k.webLinks() != null) {
+        for (WebLinkInfo webLink : Natives.asList(k.webLinks())) {
+          actionsPanel.add(webLink.toAnchor());
+        }
+      }
+      table.setWidget(row, 4, actionsPanel);
+
       FlexCellFormatter fmt = table.getFlexCellFormatter();
       String iconCellStyle = Gerrit.RESOURCES.css().iconCell();
       String dataCellStyle = Gerrit.RESOURCES.css().dataCell();
       fmt.addStyleName(row, 1, iconCellStyle);
       fmt.addStyleName(row, 2, dataCellStyle);
       fmt.addStyleName(row, 3, dataCellStyle);
+      fmt.addStyleName(row, 4, dataCellStyle);
 
       setRowItem(row, k);
     }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java
index de2c739..6ef71e6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.java
@@ -69,6 +69,7 @@
   @UiField ToggleButton lineNumbers;
   @UiField ToggleButton matchBrackets;
   @UiField ToggleButton lineWrapping;
+  @UiField ToggleButton indentWithTabs;
   @UiField ToggleButton autoCloseBrackets;
   @UiField ToggleButton showBase;
   @UiField ListBox theme;
@@ -106,6 +107,7 @@
     lineNumbers.setValue(prefs.hideLineNumbers());
     matchBrackets.setValue(prefs.matchBrackets());
     lineWrapping.setValue(prefs.lineWrapping());
+    indentWithTabs.setValue(prefs.indentWithTabs());
     autoCloseBrackets.setValue(prefs.autoCloseBrackets());
     showBase.setValue(prefs.showBase());
     setTheme(prefs.theme());
@@ -215,6 +217,14 @@
     }
   }
 
+  @UiHandler("indentWithTabs")
+  void onIndentWithTabs(ValueChangeEvent<Boolean> e) {
+    prefs.indentWithTabs(e.getValue());
+    if (view != null) {
+      view.getEditor().setOption("indentWithTabs", prefs.indentWithTabs());
+    }
+  }
+
   @UiHandler("autoCloseBrackets")
   void onCloseBrackets(ValueChangeEvent<Boolean> e) {
     prefs.autoCloseBrackets(e.getValue());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml
index 6379b67..f5ec71e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditPreferencesBox.ui.xml
@@ -246,6 +246,13 @@
         </g:ToggleButton></td>
       </tr>
       <tr>
+        <th><ui:msg>Indent With Tabs</ui:msg></th>
+        <td><g:ToggleButton ui:field='indentWithTabs'>
+          <g:upFace><ui:msg>Off</ui:msg></g:upFace>
+          <g:downFace><ui:msg>On</ui:msg></g:downFace>
+        </g:ToggleButton></td>
+      </tr>
+      <tr>
         <th><ui:msg>Auto Close Brackets</ui:msg></th>
         <td><g:ToggleButton ui:field='autoCloseBrackets'>
           <g:upFace><ui:msg>Off</ui:msg></g:upFace>
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
index 511944b..027fb40 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
@@ -571,26 +571,32 @@
         mode = ModeInfo.findMode(content.getContentType(), path);
       }
     }
-    mv =
-        MergeView.create(
-            editor,
-            Configuration.create()
-                .set("autoCloseBrackets", prefs.autoCloseBrackets())
-                .set("cursorBlinkRate", prefs.cursorBlinkRate())
-                .set("cursorHeight", 0.85)
-                .set("indentUnit", prefs.indentUnit())
-                .set("keyMap", prefs.keyMapType().name().toLowerCase())
-                .set("lineNumbers", prefs.hideLineNumbers())
-                .set("lineWrapping", false)
-                .set("matchBrackets", prefs.matchBrackets())
-                .set("mode", mode != null ? mode.mime() : null)
-                .set("origLeft", editContent)
-                .set("scrollbarStyle", "overlay")
-                .set("showTrailingSpace", prefs.showWhitespaceErrors())
-                .set("styleSelectedText", true)
-                .set("tabSize", prefs.tabSize())
-                .set("theme", prefs.theme().name().toLowerCase())
-                .set("value", ""));
+
+    Configuration cfg =
+        Configuration.create()
+            .set("autoCloseBrackets", prefs.autoCloseBrackets())
+            .set("cursorBlinkRate", prefs.cursorBlinkRate())
+            .set("cursorHeight", 0.85)
+            .set("indentUnit", prefs.indentUnit())
+            .set("keyMap", prefs.keyMapType().name().toLowerCase())
+            .set("lineNumbers", prefs.hideLineNumbers())
+            .set("lineWrapping", prefs.lineWrapping())
+            .set("indentWithTabs", prefs.indentWithTabs())
+            .set("matchBrackets", prefs.matchBrackets())
+            .set("mode", mode != null ? mode.mime() : null)
+            .set("origLeft", editContent)
+            .set("scrollbarStyle", "overlay")
+            .set("showTrailingSpace", prefs.showWhitespaceErrors())
+            .set("styleSelectedText", true)
+            .set("tabSize", prefs.tabSize())
+            .set("theme", prefs.theme().name().toLowerCase())
+            .set("value", "");
+
+    if (editContent.contains("\r\n")) {
+      cfg.set("lineSeparator", "\r\n");
+    }
+
+    mv = MergeView.create(editor, cfg);
 
     cmBase = mv.leftOriginal();
     cmBase.getWrapperElement().addClassName(style.base());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java
index 24487ae..fc13fe1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/TagInfo.java
@@ -14,9 +14,14 @@
 
 package com.google.gerrit.client.projects;
 
+import com.google.gerrit.client.info.WebLinkInfo;
+import com.google.gwt.core.client.JsArray;
+
 public class TagInfo extends RefInfo {
   public final native boolean canDelete() /*-{ return this['can_delete'] ? true : false; }-*/;
 
+  public final native JsArray<WebLinkInfo> webLinks() /*-{ return this.web_links; }-*/;
+
   // TODO(dpursehouse) add extra tag-related fields (message, tagger, etc)
   protected TagInfo() {}
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java
index 06d1cf8..643c766 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HighlightingProjectsTable.java
@@ -28,8 +28,10 @@
 
   @Override
   protected void populate(final int row, final ProjectInfo k) {
-    table.setWidget(row, 1, new InlineHTML(Util.highlight(k.name(), toHighlight)));
-    table.setText(row, 2, k.description());
+    populateState(row, k);
+    table.setWidget(
+        row, ProjectsTable.C_NAME, new InlineHTML(Util.highlight(k.name(), toHighlight)));
+    table.setText(row, ProjectsTable.C_DESCRIPTION, k.description());
 
     setRowItem(row, k);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
index 17d02ca..99d0e8e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ProjectsTable.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.client.projects.ProjectMap;
 import com.google.gerrit.client.rpc.Natives;
 import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
+import com.google.gwt.user.client.ui.Image;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -98,10 +99,30 @@
   }
 
   protected void populate(final int row, final ProjectInfo k) {
-    table.setText(row, C_STATE, k.state().toString());
+    populateState(row, k);
     table.setText(row, C_NAME, k.name());
     table.setText(row, C_DESCRIPTION, k.description());
 
     setRowItem(row, k);
   }
+
+  protected void populateState(int row, ProjectInfo k) {
+    Image state = new Image();
+    switch (k.state()) {
+      case HIDDEN:
+        state.setResource(Gerrit.RESOURCES.redNot());
+        state.setTitle(com.google.gerrit.client.admin.Util.toLongString(k.state()));
+        table.setWidget(row, ProjectsTable.C_STATE, state);
+        break;
+      case READ_ONLY:
+        state.setResource(Gerrit.RESOURCES.readOnly());
+        state.setTitle(com.google.gerrit.client.admin.Util.toLongString(k.state()));
+        table.setWidget(row, ProjectsTable.C_STATE, state);
+        break;
+      case ACTIVE:
+      default:
+        // Intentionally left blank, do not show an icon when active.
+        break;
+    }
+  }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
index b6719e6..8dfe38c 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/UrlModule.java
@@ -88,7 +88,8 @@
     serve("/starred").with(query("is:starred"));
 
     serveRegex("^/settings/?$").with(screen(PageLinks.SETTINGS));
-    serveRegex("^/register(/.*)?$").with(registerScreen());
+    serveRegex("^/register$").with(registerScreen(false));
+    serveRegex("^/register/(.+)$").with(registerScreen(true));
     serveRegex("^/([1-9][0-9]*)/?$").with(directChangeById());
     serveRegex("^/p/(.*)$").with(queryProjectNew());
     serveRegex("^/r/(.+)/?$").with(DirectChangeByCommit.class);
@@ -251,7 +252,7 @@
     return srv;
   }
 
-  private Key<HttpServlet> registerScreen() {
+  private Key<HttpServlet> registerScreen(final Boolean slash) {
     return key(
         new HttpServlet() {
           private static final long serialVersionUID = 1L;
@@ -259,7 +260,8 @@
           @Override
           protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
               throws IOException {
-            toGerrit("/register" + req.getPathInfo(), req, rsp);
+            String path = String.format("/register%s", slash ? req.getPathInfo() : "");
+            toGerrit(path, req, rsp);
           }
         });
   }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
index 5352904..803a146 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java
@@ -47,6 +47,7 @@
 import com.google.gerrit.pgm.util.LogFileCompressor;
 import com.google.gerrit.pgm.util.RuntimeShutdown;
 import com.google.gerrit.pgm.util.SiteProgram;
+import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.StartupChecks;
 import com.google.gerrit.server.account.InternalAccountDirectory;
 import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
@@ -74,6 +75,7 @@
 import com.google.gerrit.server.mime.MimeUtil2Module;
 import com.google.gerrit.server.patch.DiffExecutorModule;
 import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
+import com.google.gerrit.server.plugins.PluginModule;
 import com.google.gerrit.server.plugins.PluginRestApiModule;
 import com.google.gerrit.server.schema.DataSourceProvider;
 import com.google.gerrit.server.schema.H2AccountPatchReviewStore;
@@ -353,6 +355,19 @@
     modules.add(new DropWizardMetricMaker.RestModule());
     modules.add(new LogFileCompressor.Module());
 
+    // Plugin module needs to be inserted *before* the index module.
+    // There is the concept of LifecycleModule, in Gerrit's own extension
+    // to Guice, which has these:
+    //  listener().to(SomeClassImplementingLifecycleListener.class);
+    // and the start() methods of each such listener are executed in the
+    // order they are declared.
+    // Makes sure that PluginLoader.start() is executed before the
+    // LuceneIndexModule.start() so that plugins get loaded and the respective
+    // Guice modules installed so that the on-line reindexing will happen
+    // with the proper classes (e.g. group backends, custom Prolog
+    // predicates) and the associated rules ready to be evaluated.
+    modules.add(new PluginModule());
+
     // Index module shutdown must happen before work queue shutdown, otherwise
     // work queue can get stuck waiting on index futures that will never return.
     modules.add(createIndexModule());
@@ -422,6 +437,7 @@
     if (!slave) {
       modules.add(new ChangeCleanupRunner.Module());
     }
+    modules.addAll(LibModuleLoader.loadModules(cfgInjector));
     return cfgInjector.createChildInjector(modules);
   }
 
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
index 7457f40..2ca75c3 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
@@ -22,12 +22,14 @@
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.account.ExternalId;
 import com.google.gerrit.server.account.ExternalIdsBatchUpdate;
+import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
 import com.google.gerrit.server.schema.SchemaVersionCheck;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import java.util.Collection;
 import java.util.Locale;
+import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.TextProgressMonitor;
 
 /** Converts the local username for all accounts to lower case */
@@ -58,8 +60,10 @@
       externalIdsBatchUpdate.commit(db, "Convert local usernames to lower case");
     }
     monitor.endTask();
+
+    int exitCode = reindexAccounts();
     manager.stop();
-    return 0;
+    return exitCode;
   }
 
   private void convertLocalUserToLowerCase(ExternalId extId) {
@@ -78,4 +82,17 @@
       }
     }
   }
+
+  private int reindexAccounts() throws Exception {
+    monitor.beginTask("Reindex accounts", ProgressMonitor.UNKNOWN);
+    String[] reindexArgs = {
+      "--site-path", getSitePath().toString(), "--index", AccountSchemaDefinitions.NAME
+    };
+    System.out.println("Migration complete, reindexing accounts with:");
+    System.out.println("  reindex " + String.join(" ", reindexArgs));
+    Reindex reindexPgm = new Reindex();
+    int exitCode = reindexPgm.main(reindexArgs);
+    monitor.endTask();
+    return exitCode;
+  }
 }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
index 410d058..232d71b 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
@@ -84,8 +84,7 @@
     globalConfig = dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
     threads = ThreadLimiter.limitThreads(dbInjector, threads);
     checkNotSlaveMode();
-    disableLuceneAutomaticCommit();
-    disableChangeCache();
+    overrideConfig();
     LifecycleManager dbManager = new LifecycleManager();
     dbManager.add(dbInjector);
     dbManager.start();
@@ -177,15 +176,18 @@
     return dbInjector.createChildInjector(modules);
   }
 
-  private void disableLuceneAutomaticCommit() {
+  private void overrideConfig() {
+    // Disable auto-commit for speed; committing will happen at the end of the process.
     if (IndexModule.getIndexType(dbInjector) == IndexType.LUCENE) {
       globalConfig.setLong("index", "changes_open", "commitWithin", -1);
       globalConfig.setLong("index", "changes_closed", "commitWithin", -1);
     }
-  }
 
-  private void disableChangeCache() {
+    // Disable change cache.
     globalConfig.setLong("cache", "changes", "maximumWeight", 0);
+
+    // Disable auto-reindexing if stale, since there are no concurrent writes to race with.
+    globalConfig.setBoolean("index", null, "autoReindexIfStale", false);
   }
 
   private <K, V, I extends Index<K, V>> boolean reindex(IndexDefinition<K, V, I> def)
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
index 279584a..e7f5ffc 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -24,7 +24,6 @@
 import com.google.gerrit.metrics.DisabledMetricMaker;
 import com.google.gerrit.metrics.MetricMaker;
 import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
-import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
@@ -185,7 +184,6 @@
     modules.add(new SchemaModule());
     modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
     modules.add(new ConfigNotesMigration.Module());
-    modules.addAll(LibModuleLoader.loadModules(cfgInjector));
 
     try {
       return Guice.createInjector(PRODUCTION, modules);
diff --git a/gerrit-plugin-api/pom.xml b/gerrit-plugin-api/pom.xml
index 8964b94..b6d1dc9 100644
--- a/gerrit-plugin-api/pom.xml
+++ b/gerrit-plugin-api/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-api</artifactId>
-  <version>2.14.1-SNAPSHOT</version>
+  <version>2.14.1</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Plugin API</name>
   <description>API for Gerrit Plugins</description>
diff --git a/gerrit-plugin-gwtui/pom.xml b/gerrit-plugin-gwtui/pom.xml
index dbfda13..ba2dbf6 100644
--- a/gerrit-plugin-gwtui/pom.xml
+++ b/gerrit-plugin-gwtui/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-plugin-gwtui</artifactId>
-  <version>2.14.1-SNAPSHOT</version>
+  <version>2.14.1</version>
   <packaging>jar</packaging>
   <name>Gerrit Code Review - Plugin GWT UI</name>
   <description>Common Classes for Gerrit GWT UI Plugins</description>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/WebLinks.java b/gerrit-server/src/main/java/com/google/gerrit/server/WebLinks.java
index 533ed9d..18fdf8f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/WebLinks.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/WebLinks.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.extensions.webui.ParentWebLink;
 import com.google.gerrit.extensions.webui.PatchSetWebLink;
 import com.google.gerrit.extensions.webui.ProjectWebLink;
+import com.google.gerrit.extensions.webui.TagWebLink;
 import com.google.gerrit.extensions.webui.WebLink;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.inject.Inject;
@@ -70,6 +71,7 @@
   private final DynamicSet<DiffWebLink> diffLinks;
   private final DynamicSet<ProjectWebLink> projectLinks;
   private final DynamicSet<BranchWebLink> branchLinks;
+  private final DynamicSet<TagWebLink> tagLinks;
 
   @Inject
   public WebLinks(
@@ -79,7 +81,8 @@
       DynamicSet<FileHistoryWebLink> fileLogLinks,
       DynamicSet<DiffWebLink> diffLinks,
       DynamicSet<ProjectWebLink> projectLinks,
-      DynamicSet<BranchWebLink> branchLinks) {
+      DynamicSet<BranchWebLink> branchLinks,
+      DynamicSet<TagWebLink> tagLinks) {
     this.patchSetLinks = patchSetLinks;
     this.parentLinks = parentLinks;
     this.fileLinks = fileLinks;
@@ -87,6 +90,7 @@
     this.diffLinks = diffLinks;
     this.projectLinks = projectLinks;
     this.branchLinks = branchLinks;
+    this.tagLinks = tagLinks;
   }
 
   /**
@@ -194,6 +198,15 @@
     return filterLinks(branchLinks, webLink -> webLink.getBranchWebLink(project, branch));
   }
 
+  /**
+   * @param project Project name
+   * @param tag Tag name
+   * @return Links for tags.
+   */
+  public List<WebLinkInfo> getTagLinks(String project, String tag) {
+    return filterLinks(tagLinks, webLink -> webLink.getTagWebLink(project, tag));
+  }
+
   private <T extends WebLink> List<WebLinkInfo> filterLinks(
       DynamicSet<T> links, Function<T, WebLinkInfo> transformer) {
     return FluentIterable.from(links).transform(transformer).filter(INVALID_WEBLINK).toList();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
index c28021c..df6b122 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCache.java
@@ -14,13 +14,42 @@
 
 package com.google.gerrit.server.account;
 
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.reviewdb.client.Account;
 import java.io.IOException;
 
 /** Caches important (but small) account state to avoid database hits. */
 public interface AccountCache {
+  /**
+   * Returns an {@code AccountState} instance for the given account ID. If not cached yet the
+   * account is loaded. Returns an empty {@code AccountState} instance to represent a missing
+   * account.
+   *
+   * @param accountId ID of the account that should be retrieved
+   * @return {@code AccountState} instance for the given account ID, if no account with this ID
+   *     exists an empty {@code AccountState} instance is returned to represent the missing account
+   */
   AccountState get(Account.Id accountId);
 
+  /**
+   * Returns an {@code AccountState} instance for the given account ID. If not cached yet the
+   * account is loaded. Returns {@code null} if the account is missing.
+   *
+   * @param accountId ID of the account that should be retrieved
+   * @return {@code AccountState} instance for the given account ID, if no account with this ID
+   *     exists {@code null} is returned
+   */
+  @Nullable
+  AccountState getOrNull(Account.Id accountId);
+
+  /**
+   * Returns an {@code AccountState} instance for the given account ID if it is present in the
+   * cache.
+   *
+   * @param accountId ID of the account that should be retrieved
+   * @return {@code AccountState} instance for the given account ID if it is present in the cache,
+   *     otherwise {@code null}
+   */
   AccountState getIfPresent(Account.Id accountId);
 
   AccountState getByUsername(String username);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
index 24b019f..1828cca 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountCacheImpl.java
@@ -19,6 +19,7 @@
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
 import com.google.gerrit.reviewdb.client.Account;
@@ -62,7 +63,8 @@
     return new CacheModule() {
       @Override
       protected void configure() {
-        cache(BYID_NAME, Account.Id.class, AccountState.class).loader(ByIdLoader.class);
+        cache(BYID_NAME, Account.Id.class, new TypeLiteral<Optional<AccountState>>() {})
+            .loader(ByIdLoader.class);
 
         cache(BYUSER_NAME, String.class, new TypeLiteral<Optional<Account.Id>>() {})
             .loader(useReviewdb ? ByNameReviewDbLoader.class : ByNameLoader.class);
@@ -73,13 +75,13 @@
     };
   }
 
-  private final LoadingCache<Account.Id, AccountState> byId;
+  private final LoadingCache<Account.Id, Optional<AccountState>> byId;
   private final LoadingCache<String, Optional<Account.Id>> byName;
   private final Provider<AccountIndexer> indexer;
 
   @Inject
   AccountCacheImpl(
-      @Named(BYID_NAME) LoadingCache<Account.Id, AccountState> byId,
+      @Named(BYID_NAME) LoadingCache<Account.Id, Optional<AccountState>> byId,
       @Named(BYUSER_NAME) LoadingCache<String, Optional<Account.Id>> byUsername,
       Provider<AccountIndexer> indexer) {
     this.byId = byId;
@@ -90,7 +92,7 @@
   @Override
   public AccountState get(Account.Id accountId) {
     try {
-      return byId.get(accountId);
+      return byId.get(accountId).orElse(missing(accountId));
     } catch (ExecutionException e) {
       log.warn("Cannot load AccountState for " + accountId, e);
       return missing(accountId);
@@ -98,15 +100,27 @@
   }
 
   @Override
+  @Nullable
+  public AccountState getOrNull(Account.Id accountId) {
+    try {
+      return byId.get(accountId).orElse(null);
+    } catch (ExecutionException e) {
+      log.warn("Cannot load AccountState for " + accountId, e);
+      return null;
+    }
+  }
+
+  @Override
   public AccountState getIfPresent(Account.Id accountId) {
-    return byId.getIfPresent(accountId);
+    Optional<AccountState> state = byId.getIfPresent(accountId);
+    return state != null ? state.orElse(missing(accountId)) : null;
   }
 
   @Override
   public AccountState getByUsername(String username) {
     try {
       Optional<Account.Id> id = byName.get(username);
-      return id != null && id.isPresent() ? byId.get(id.get()) : null;
+      return id != null && id.isPresent() ? getOrNull(id.get()) : null;
     } catch (ExecutionException e) {
       log.warn("Cannot load AccountState for " + username, e);
       return null;
@@ -144,7 +158,7 @@
         account, anon, Collections.emptySet(), new HashMap<ProjectWatchKey, Set<NotifyType>>());
   }
 
-  static class ByIdLoader extends CacheLoader<Account.Id, AccountState> {
+  static class ByIdLoader extends CacheLoader<Account.Id, Optional<AccountState>> {
     private final SchemaFactory<ReviewDb> schema;
     private final GroupCache groupCache;
     private final GeneralPreferencesLoader loader;
@@ -166,23 +180,25 @@
     }
 
     @Override
-    public AccountState load(Account.Id key) throws Exception {
+    public Optional<AccountState> load(Account.Id key) throws Exception {
       try (ReviewDb db = schema.open()) {
-        final AccountState state = load(db, key);
-        String user = state.getUserName();
+        Optional<AccountState> state = load(db, key);
+        if (!state.isPresent()) {
+          return state;
+        }
+        String user = state.get().getUserName();
         if (user != null) {
-          byName.put(user, Optional.of(state.getAccount().getId()));
+          byName.put(user, Optional.of(state.get().getAccount().getId()));
         }
         return state;
       }
     }
 
-    private AccountState load(final ReviewDb db, final Account.Id who)
+    private Optional<AccountState> load(final ReviewDb db, final Account.Id who)
         throws OrmException, IOException, ConfigInvalidException {
       Account account = db.accounts().get(who);
       if (account == null) {
-        // Account no longer exists? They are anonymous.
-        return missing(who);
+        return Optional.empty();
       }
 
       Set<ExternalId> externalIds =
@@ -205,8 +221,9 @@
         account.setGeneralPreferences(GeneralPreferencesInfo.defaults());
       }
 
-      return new AccountState(
-          account, internalGroups, externalIds, watchConfig.get().getProjectWatches(who));
+      return Optional.of(
+          new AccountState(
+              account, internalGroups, externalIds, watchConfig.get().getProjectWatches(who)));
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
index 77d28f9..b5d0463 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
@@ -111,7 +111,7 @@
     who = realm.authenticate(who);
     try {
       try (ReviewDb db = schema.open()) {
-        ExternalId id = findExternalId(who.getExternalIdKey());
+        ExternalId id = findExternalId(db, who.getExternalIdKey());
         if (id == null) {
           // New account, automatically create and return.
           //
@@ -133,16 +133,8 @@
     }
   }
 
-  private ExternalId findExternalId(ExternalId.Key key) throws OrmException {
-    AccountState accountState = accountQueryProvider.get().oneByExternalId(key);
-    if (accountState != null) {
-      for (ExternalId extId : accountState.getExternalIds()) {
-        if (extId.key().equals(key)) {
-          return extId;
-        }
-      }
-    }
-    return null;
+  private ExternalId findExternalId(ReviewDb db, ExternalId.Key key) throws OrmException {
+    return ExternalId.from(db.accountExternalIds().get(key.asAccountExternalIdKey()));
   }
 
   private void update(ReviewDb db, AuthRequest who, ExternalId extId)
@@ -357,7 +349,7 @@
   public AuthResult link(Account.Id to, AuthRequest who)
       throws AccountException, OrmException, IOException, ConfigInvalidException {
     try (ReviewDb db = schema.open()) {
-      ExternalId extId = findExternalId(who.getExternalIdKey());
+      ExternalId extId = findExternalId(db, who.getExternalIdKey());
       if (extId != null) {
         if (!extId.accountId().equals(to)) {
           throw new AccountException("Identity in use by another account");
@@ -374,13 +366,10 @@
           if (a.getPreferredEmail() == null) {
             a.setPreferredEmail(who.getEmailAddress());
             db.accounts().update(Collections.singleton(a));
+            byIdCache.evict(to);
           }
-        }
-
-        if (who.getEmailAddress() != null) {
           byEmailCache.evict(who.getEmailAddress());
         }
-        byIdCache.evict(to);
       }
 
       return new AuthResult(to, who.getExternalIdKey(), false);
@@ -435,7 +424,7 @@
   public AuthResult unlink(Account.Id from, AuthRequest who)
       throws AccountException, OrmException, IOException, ConfigInvalidException {
     try (ReviewDb db = schema.open()) {
-      ExternalId extId = findExternalId(who.getExternalIdKey());
+      ExternalId extId = findExternalId(db, who.getExternalIdKey());
       if (extId != null) {
         if (!extId.accountId().equals(from)) {
           throw new AccountException(
@@ -449,9 +438,9 @@
               && a.getPreferredEmail().equals(who.getEmailAddress())) {
             a.setPreferredEmail(null);
             db.accounts().update(Collections.singleton(a));
+            byIdCache.evict(from);
           }
           byEmailCache.evict(who.getEmailAddress());
-          byIdCache.evict(from);
         }
 
       } else {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
index f60ee45..978331e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
@@ -120,7 +120,6 @@
       accountCache.evictByUsername(extId.key().id());
     }
 
-    accountCache.evict(user.getAccountId());
     accountCache.evictByUsername(newUsername);
     sshKeyCache.evict(newUsername);
     return VoidResult.INSTANCE;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalIdsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalIdsUpdate.java
index a596a8e..7746709 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalIdsUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ExternalIdsUpdate.java
@@ -84,6 +84,9 @@
  * </pre>
  *
  * For NoteDb each method call results in one commit on refs/meta/external-ids branch.
+ *
+ * <p>On updating external IDs this class takes care to evict affected accounts from the account
+ * cache and thus triggers reindex for them.
  */
 public class ExternalIdsUpdate {
   private static final String COMMIT_MSG = "Update external IDs";
@@ -97,22 +100,25 @@
   @Singleton
   public static class Server {
     private final GitRepositoryManager repoManager;
+    private final AccountCache accountCache;
     private final AllUsersName allUsersName;
     private final Provider<PersonIdent> serverIdent;
 
     @Inject
     public Server(
         GitRepositoryManager repoManager,
+        AccountCache accountCache,
         AllUsersName allUsersName,
         @GerritPersonIdent Provider<PersonIdent> serverIdent) {
       this.repoManager = repoManager;
+      this.accountCache = accountCache;
       this.allUsersName = allUsersName;
       this.serverIdent = serverIdent;
     }
 
     public ExternalIdsUpdate create() {
       PersonIdent i = serverIdent.get();
-      return new ExternalIdsUpdate(repoManager, allUsersName, i, i);
+      return new ExternalIdsUpdate(repoManager, accountCache, allUsersName, i, i);
     }
   }
 
@@ -125,6 +131,7 @@
   @Singleton
   public static class User {
     private final GitRepositoryManager repoManager;
+    private final AccountCache accountCache;
     private final AllUsersName allUsersName;
     private final Provider<PersonIdent> serverIdent;
     private final Provider<IdentifiedUser> identifiedUser;
@@ -132,10 +139,12 @@
     @Inject
     public User(
         GitRepositoryManager repoManager,
+        AccountCache accountCache,
         AllUsersName allUsersName,
         @GerritPersonIdent Provider<PersonIdent> serverIdent,
         Provider<IdentifiedUser> identifiedUser) {
       this.repoManager = repoManager;
+      this.accountCache = accountCache;
       this.allUsersName = allUsersName;
       this.serverIdent = serverIdent;
       this.identifiedUser = identifiedUser;
@@ -144,7 +153,7 @@
     public ExternalIdsUpdate create() {
       PersonIdent i = serverIdent.get();
       return new ExternalIdsUpdate(
-          repoManager, allUsersName, createPersonIdent(i, identifiedUser.get()), i);
+          repoManager, accountCache, allUsersName, createPersonIdent(i, identifiedUser.get()), i);
     }
 
     private PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) {
@@ -166,6 +175,7 @@
   private static final Retryer<Void> RETRYER = retryerBuilder().build();
 
   private final GitRepositoryManager repoManager;
+  private final AccountCache accountCache;
   private final AllUsersName allUsersName;
   private final PersonIdent committerIdent;
   private final PersonIdent authorIdent;
@@ -174,21 +184,31 @@
 
   private ExternalIdsUpdate(
       GitRepositoryManager repoManager,
+      AccountCache accountCache,
       AllUsersName allUsersName,
       PersonIdent committerIdent,
       PersonIdent authorIdent) {
-    this(repoManager, allUsersName, committerIdent, authorIdent, Runnables.doNothing(), RETRYER);
+    this(
+        repoManager,
+        accountCache,
+        allUsersName,
+        committerIdent,
+        authorIdent,
+        Runnables.doNothing(),
+        RETRYER);
   }
 
   @VisibleForTesting
   public ExternalIdsUpdate(
       GitRepositoryManager repoManager,
+      AccountCache accountCache,
       AllUsersName allUsersName,
       PersonIdent committerIdent,
       PersonIdent authorIdent,
       Runnable afterReadRevision,
       Retryer<Void> retryer) {
     this.repoManager = checkNotNull(repoManager, "repoManager");
+    this.accountCache = accountCache;
     this.allUsersName = checkNotNull(allUsersName, "allUsersName");
     this.committerIdent = checkNotNull(committerIdent, "committerIdent");
     this.authorIdent = checkNotNull(authorIdent, "authorIdent");
@@ -222,6 +242,7 @@
             insert(o.rw(), o.ins(), o.noteMap(), extId);
           }
         });
+    evictAccounts(extIds);
   }
 
   /**
@@ -249,6 +270,7 @@
             upsert(o.rw(), o.ins(), o.noteMap(), extId);
           }
         });
+    evictAccounts(extIds);
   }
 
   /**
@@ -279,6 +301,7 @@
             remove(o.rw(), o.noteMap(), extId);
           }
         });
+    evictAccounts(extIds);
   }
 
   /**
@@ -308,6 +331,7 @@
             remove(o.rw(), o.noteMap(), accountId, extIdKey);
           }
         });
+    accountCache.evict(accountId);
   }
 
   /** Deletes all external IDs of the specified account. */
@@ -348,6 +372,7 @@
             insert(o.rw(), o.ins(), o.noteMap(), extId);
           }
         });
+    accountCache.evict(accountId);
   }
 
   /**
@@ -587,6 +612,12 @@
     return ins.insert(OBJ_TREE, new byte[] {});
   }
 
+  private void evictAccounts(Collection<ExternalId> extIds) throws IOException {
+    for (Account.Id id : extIds.stream().map(ExternalId::accountId).collect(toSet())) {
+      accountCache.evict(id);
+    }
+  }
+
   private static interface MyConsumer<T> {
     void accept(T t) throws IOException, ConfigInvalidException, OrmException;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
index 435671f..29aac58 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutHttpPassword.java
@@ -54,18 +54,15 @@
 
   private final Provider<CurrentUser> self;
   private final Provider<ReviewDb> dbProvider;
-  private final AccountCache accountCache;
   private final ExternalIdsUpdate.User externalIdsUpdate;
 
   @Inject
   PutHttpPassword(
       Provider<CurrentUser> self,
       Provider<ReviewDb> dbProvider,
-      AccountCache accountCache,
       ExternalIdsUpdate.User externalIdsUpdate) {
     this.self = self;
     this.dbProvider = dbProvider;
-    this.accountCache = accountCache;
     this.externalIdsUpdate = externalIdsUpdate;
   }
 
@@ -122,7 +119,6 @@
     ExternalId newExtId =
         ExternalId.createWithPassword(extId.key(), extId.accountId(), extId.email(), newPassword);
     externalIdsUpdate.create().upsert(dbProvider.get(), newExtId);
-    accountCache.evict(user.getAccountId());
 
     return Strings.isNullOrEmpty(newPassword) ? Response.<String>none() : Response.ok(newPassword);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 4f948d7..c7d7f8a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -67,6 +67,7 @@
 import com.google.gerrit.extensions.webui.ParentWebLink;
 import com.google.gerrit.extensions.webui.PatchSetWebLink;
 import com.google.gerrit.extensions.webui.ProjectWebLink;
+import com.google.gerrit.extensions.webui.TagWebLink;
 import com.google.gerrit.extensions.webui.TopMenu;
 import com.google.gerrit.extensions.webui.WebUiPlugin;
 import com.google.gerrit.rules.PrologModule;
@@ -366,6 +367,7 @@
     DynamicSet.setOf(binder(), DiffWebLink.class);
     DynamicSet.setOf(binder(), ProjectWebLink.class);
     DynamicSet.setOf(binder(), BranchWebLink.class);
+    DynamicSet.setOf(binder(), TagWebLink.class);
     DynamicMap.mapOf(binder(), OAuthLoginProvider.class);
     DynamicItem.itemOf(binder(), OAuthTokenEncrypter.class);
     DynamicSet.setOf(binder(), AccountExternalIdCreator.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitwebConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitwebConfig.java
index 723e9bf..6c0f769 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GitwebConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GitwebConfig.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.extensions.webui.ParentWebLink;
 import com.google.gerrit.extensions.webui.PatchSetWebLink;
 import com.google.gerrit.extensions.webui.ProjectWebLink;
+import com.google.gerrit.extensions.webui.TagWebLink;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -64,6 +65,10 @@
           DynamicSet.bind(binder(), BranchWebLink.class).to(GitwebLinks.class);
         }
 
+        if (!isNullOrEmpty(type.getTag())) {
+          DynamicSet.bind(binder(), TagWebLink.class).to(GitwebLinks.class);
+        }
+
         if (!isNullOrEmpty(type.getFile()) || !isNullOrEmpty(type.getRootTree())) {
           DynamicSet.bind(binder(), FileWebLink.class).to(GitwebLinks.class);
         }
@@ -101,6 +106,7 @@
     type.setLinkName(
         firstNonNull(cfg.getString("gitweb", null, "linkname"), defaultType.getLinkName()));
     type.setBranch(firstNonNull(cfg.getString("gitweb", null, "branch"), defaultType.getBranch()));
+    type.setTag(firstNonNull(cfg.getString("gitweb", null, "tag"), defaultType.getTag()));
     type.setProject(
         firstNonNull(cfg.getString("gitweb", null, "project"), defaultType.getProject()));
     type.setRevision(
@@ -135,6 +141,7 @@
         type.setProject("?p=${project}.git;a=summary");
         type.setRevision("?p=${project}.git;a=commit;h=${commit}");
         type.setBranch("?p=${project}.git;a=shortlog;h=${branch}");
+        type.setTag("?p=${project}.git;a=tag;h=${tag}");
         type.setRootTree("?p=${project}.git;a=tree;hb=${commit}");
         type.setFile("?p=${project}.git;hb=${commit};f=${file}");
         type.setFileHistory("?p=${project}.git;a=history;hb=${branch};f=${file}");
@@ -144,6 +151,7 @@
         type.setProject("${project}.git/summary");
         type.setRevision("${project}.git/commit/?id=${commit}");
         type.setBranch("${project}.git/log/?h=${branch}");
+        type.setTag("${project}.git/tag/?h=${tag}");
         type.setRootTree("${project}.git/tree/?h=${commit}");
         type.setFile("${project}.git/tree/${file}?h=${commit}");
         type.setFileHistory("${project}.git/log/${file}?h=${branch}");
@@ -154,6 +162,7 @@
         type.setProject("");
         type.setRevision("");
         type.setBranch("");
+        type.setTag("");
         type.setRootTree("");
         type.setFile("");
         type.setFileHistory("");
@@ -236,7 +245,8 @@
           FileWebLink,
           PatchSetWebLink,
           ParentWebLink,
-          ProjectWebLink {
+          ProjectWebLink,
+          TagWebLink {
     private final String url;
     private final GitwebType type;
     private final ParameterizedString branch;
@@ -244,6 +254,7 @@
     private final ParameterizedString fileHistory;
     private final ParameterizedString project;
     private final ParameterizedString revision;
+    private final ParameterizedString tag;
 
     @Inject
     GitwebLinks(GitwebConfig config, GitwebType type) {
@@ -254,6 +265,7 @@
       this.fileHistory = parse(type.getFileHistory());
       this.project = parse(type.getProject());
       this.revision = parse(type.getRevision());
+      this.tag = parse(type.getTag());
     }
 
     @Override
@@ -269,6 +281,15 @@
     }
 
     @Override
+    public WebLinkInfo getTagWebLink(String projectName, String tagName) {
+      if (tag != null) {
+        return link(
+            tag.replace("project", encode(projectName)).replace("tag", encode(tagName)).toString());
+      }
+      return null;
+    }
+
+    @Override
     public WebLinkInfo getFileHistoryWebLink(String projectName, String revision, String fileName) {
       if (fileHistory != null) {
         return link(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOpRepoManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOpRepoManager.java
index cfdba92..ad205f8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOpRepoManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOpRepoManager.java
@@ -206,7 +206,7 @@
       throws NoSuchProjectException, IOException {
     List<BatchUpdate> updates = new ArrayList<>(projects.size());
     for (Project.NameKey project : projects) {
-      updates.add(getRepo(project).getUpdate());
+      updates.add(getRepo(project).getUpdate().setRefLogMessage("merged"));
     }
     return updates;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
index e3b1ad6..b16ccef 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MetaDataUpdate.java
@@ -94,7 +94,7 @@
      * <pre>
      * <code>
      *   try (Repository repo = repoMgr.openRepository(allUsersName);
-     *       RevWalk rw = new RevWalk(repo) {
+     *       RevWalk rw = new RevWalk(repo)) {
      *     BatchRefUpdate batchUpdate = repo.getRefDatabase().newBatchUpdate();
      *     // WRONG: create the MetaDataUpdate instance here and reuse it for
      *     //        all updates in the loop
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
index 536858b..2b9151b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VersionedMetaData.java
@@ -155,7 +155,7 @@
   public void load(RevWalk walk, ObjectId id) throws IOException, ConfigInvalidException {
     this.reader = walk.getObjectReader();
     try {
-      revision = id != null ? new RevWalk(reader).parseCommit(id) : null;
+      revision = id != null ? walk.parseCommit(id) : null;
       onLoad();
     } finally {
       reader = null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
index 58dbd34..8796360 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountIndexerImpl.java
@@ -64,8 +64,13 @@
 
   @Override
   public void index(Account.Id id) throws IOException {
-    for (Index<?, AccountState> i : getWriteIndexes()) {
-      i.replace(byIdCache.get(id));
+    for (Index<Account.Id, AccountState> i : getWriteIndexes()) {
+      AccountState accountState = byIdCache.getOrNull(id);
+      if (accountState != null) {
+        i.replace(accountState);
+      } else {
+        i.delete(id);
+      }
     }
     fireAccountIndexedEvent(id.get());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountSchemaDefinitions.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountSchemaDefinitions.java
index 011f1d1..888ee4a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountSchemaDefinitions.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/account/AccountSchemaDefinitions.java
@@ -38,9 +38,10 @@
 
   static final Schema<AccountState> V4 = schema(V3);
 
+  public static final String NAME = "accounts";
   public static final AccountSchemaDefinitions INSTANCE = new AccountSchemaDefinitions();
 
   private AccountSchemaDefinitions() {
-    super("accounts", AccountState.class);
+    super(NAME, AccountState.class);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexer.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexer.java
index a788f8c..2ff04ae 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexer.java
@@ -107,7 +107,7 @@
   private final ListeningExecutorService executor;
   private final DynamicSet<ChangeIndexedListener> indexedListeners;
   private final StalenessChecker stalenessChecker;
-  private final boolean reindexAfterIndexUpdate;
+  private final boolean autoReindexIfStale;
 
   @AssistedInject
   ChangeIndexer(
@@ -131,7 +131,7 @@
     this.indexedListeners = indexedListeners;
     this.stalenessChecker = stalenessChecker;
     this.batchExecutor = batchExecutor;
-    this.reindexAfterIndexUpdate = reindexAfterIndexUpdate(cfg);
+    this.autoReindexIfStale = autoReindexIfStale(cfg);
     this.index = index;
     this.indexes = null;
   }
@@ -158,13 +158,13 @@
     this.indexedListeners = indexedListeners;
     this.stalenessChecker = stalenessChecker;
     this.batchExecutor = batchExecutor;
-    this.reindexAfterIndexUpdate = reindexAfterIndexUpdate(cfg);
+    this.autoReindexIfStale = autoReindexIfStale(cfg);
     this.index = null;
     this.indexes = indexes;
   }
 
-  private static boolean reindexAfterIndexUpdate(Config cfg) {
-    return cfg.getBoolean("index", null, "testReindexAfterUpdate", true);
+  private static boolean autoReindexIfStale(Config cfg) {
+    return cfg.getBoolean("index", null, "autoReindexIfStale", true);
   }
 
   /**
@@ -221,7 +221,7 @@
     // and fix the staleness. It doesn't matter which order the two
     // reindexIfStale calls actually execute in; we are guaranteed that at least
     // one of them will execute after the second index write, (4).
-    reindexAfterIndexUpdate(cd);
+    autoReindexIfStale(cd);
   }
 
   private void fireChangeIndexedEvent(int id) {
@@ -253,7 +253,7 @@
   public void index(ReviewDb db, Change change) throws IOException, OrmException {
     index(newChangeData(db, change));
     // See comment in #index(ChangeData).
-    reindexAfterIndexUpdate(change.getProject(), change.getId());
+    autoReindexIfStale(change.getProject(), change.getId());
   }
 
   /**
@@ -268,7 +268,7 @@
     ChangeData cd = newChangeData(db, project, changeId);
     index(cd);
     // See comment in #index(ChangeData).
-    reindexAfterIndexUpdate(cd);
+    autoReindexIfStale(cd);
   }
 
   /**
@@ -304,16 +304,16 @@
     return submit(new ReindexIfStaleTask(project, id), batchExecutor);
   }
 
-  private void reindexAfterIndexUpdate(ChangeData cd) throws IOException {
+  private void autoReindexIfStale(ChangeData cd) throws IOException {
     try {
-      reindexAfterIndexUpdate(cd.project(), cd.getId());
+      autoReindexIfStale(cd.project(), cd.getId());
     } catch (OrmException e) {
       throw new IOException(e);
     }
   }
 
-  private void reindexAfterIndexUpdate(Project.NameKey project, Change.Id id) {
-    if (reindexAfterIndexUpdate) {
+  private void autoReindexIfStale(Project.NameKey project, Change.Id id) {
+    if (autoReindexIfStale) {
       // Don't retry indefinitely; if this fails the change will be stale.
       @SuppressWarnings("unused")
       Future<?> possiblyIgnoredError = reindexIfStale(project, id);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/ChangeEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/ChangeEmail.java
index bc09488..3753334 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/ChangeEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/ChangeEmail.java
@@ -458,10 +458,10 @@
     changeData.put("subject", subject);
     // shortSubject is the subject limited to 63 characters, with an ellipsis if
     // it exceeds that.
-    if (subject.length() < 64) {
+    if (subject.length() < 73) {
       changeData.put("shortSubject", subject);
     } else {
-      changeData.put("shortSubject", subject.substring(0, 60) + "...");
+      changeData.put("shortSubject", subject.substring(0, 69) + "...");
     }
 
     Map<String, Object> patchSetData = new HashMap<>();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
index 80e6bb8..48aff2e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
@@ -30,6 +30,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.Writer;
 import java.text.SimpleDateFormat;
@@ -45,6 +46,7 @@
 import org.apache.commons.net.smtp.AuthSMTPClient;
 import org.apache.commons.net.smtp.SMTPClient;
 import org.apache.commons.net.smtp.SMTPReply;
+import org.apache.james.mime4j.codec.QuotedPrintableOutputStream;
 import org.eclipse.jgit.lib.Config;
 
 /** Sends email via a nearby SMTP server. */
@@ -169,33 +171,6 @@
       throw new EmailException("Sending email is disabled");
     }
 
-    final Map<String, EmailHeader> hdrs = new LinkedHashMap<>(callerHeaders);
-    setMissingHeader(hdrs, "MIME-Version", "1.0");
-    setMissingHeader(hdrs, "Content-Transfer-Encoding", "8bit");
-    setMissingHeader(hdrs, "Content-Disposition", "inline");
-    setMissingHeader(hdrs, "User-Agent", "Gerrit/" + Version.getVersion());
-    if (importance != null) {
-      setMissingHeader(hdrs, "Importance", importance);
-    }
-    if (expiryDays > 0) {
-      Date expiry = new Date(TimeUtil.nowMs() + expiryDays * 24 * 60 * 60 * 1000L);
-      setMissingHeader(
-          hdrs, "Expiry-Date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(expiry));
-    }
-
-    String encodedBody;
-    if (htmlBody == null) {
-      setMissingHeader(hdrs, "Content-Type", "text/plain; charset=UTF-8");
-      encodedBody = textBody;
-    } else {
-      String boundary = generateMultipartBoundary(textBody, htmlBody);
-      setMissingHeader(
-          hdrs,
-          "Content-Type",
-          "multipart/alternative; boundary=\"" + boundary + "\"; charset=UTF-8");
-      encodedBody = buildMultipartBody(boundary, textBody, htmlBody);
-    }
-
     StringBuffer rejected = new StringBuffer();
     try {
       final SMTPClient client = open();
@@ -238,20 +213,8 @@
                   + " rejected DATA command: "
                   + client.getReplyString());
         }
-        try (Writer w = new BufferedWriter(messageDataWriter)) {
-          for (Map.Entry<String, EmailHeader> h : hdrs.entrySet()) {
-            if (!h.getValue().isEmpty()) {
-              w.write(h.getKey());
-              w.write(": ");
-              h.getValue().write(w);
-              w.write("\r\n");
-            }
-          }
 
-          w.write("\r\n");
-          w.write(encodedBody);
-          w.flush();
-        }
+        render(messageDataWriter, callerHeaders, textBody, htmlBody);
 
         if (!client.completePendingCommand()) {
           throw new EmailException(
@@ -270,6 +233,55 @@
     }
   }
 
+  private void render(
+      Writer out,
+      Map<String, EmailHeader> callerHeaders,
+      String textBody,
+      @Nullable String htmlBody)
+      throws IOException, EmailException {
+    final Map<String, EmailHeader> hdrs = new LinkedHashMap<>(callerHeaders);
+    setMissingHeader(hdrs, "MIME-Version", "1.0");
+    setMissingHeader(hdrs, "Content-Transfer-Encoding", "8bit");
+    setMissingHeader(hdrs, "Content-Disposition", "inline");
+    setMissingHeader(hdrs, "User-Agent", "Gerrit/" + Version.getVersion());
+    if (importance != null) {
+      setMissingHeader(hdrs, "Importance", importance);
+    }
+    if (expiryDays > 0) {
+      Date expiry = new Date(TimeUtil.nowMs() + expiryDays * 24 * 60 * 60 * 1000L);
+      setMissingHeader(
+          hdrs, "Expiry-Date", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(expiry));
+    }
+
+    String encodedBody;
+    if (htmlBody == null) {
+      setMissingHeader(hdrs, "Content-Type", "text/plain; charset=UTF-8");
+      encodedBody = textBody;
+    } else {
+      String boundary = generateMultipartBoundary(textBody, htmlBody);
+      setMissingHeader(
+          hdrs,
+          "Content-Type",
+          "multipart/alternative; boundary=\"" + boundary + "\"; charset=UTF-8");
+      encodedBody = buildMultipartBody(boundary, textBody, htmlBody);
+    }
+
+    try (Writer w = new BufferedWriter(out)) {
+      for (Map.Entry<String, EmailHeader> h : hdrs.entrySet()) {
+        if (!h.getValue().isEmpty()) {
+          w.write(h.getKey());
+          w.write(": ");
+          h.getValue().write(w);
+          w.write("\r\n");
+        }
+      }
+
+      w.write("\r\n");
+      w.write(encodedBody);
+      w.flush();
+    }
+  }
+
   public static String generateMultipartBoundary(String textBody, String htmlBody)
       throws EmailException {
     byte[] bytes = new byte[8];
@@ -292,16 +304,26 @@
     throw new EmailException("Gave up generating unique MIME boundary");
   }
 
-  protected String buildMultipartBody(String boundary, String textPart, String htmlPart) {
+  protected String buildMultipartBody(String boundary, String textPart, String htmlPart)
+      throws IOException {
+    String encodedTextPart = quotedPrintableEncode(textPart);
+    String encodedHtmlPart = quotedPrintableEncode(htmlPart);
+
+    // Only declare quoted-printable encoding if there are characters that need to be encoded.
+    String textTransferEncoding = textPart.equals(encodedTextPart) ? "7bit" : "quoted-printable";
+    String htmlTransferEncoding = htmlPart.equals(encodedHtmlPart) ? "7bit" : "quoted-printable";
+
     return
     // Output the text part:
     "--"
         + boundary
         + "\r\n"
         + "Content-Type: text/plain; charset=UTF-8\r\n"
-        + "Content-Transfer-Encoding: 8bit\r\n"
+        + "Content-Transfer-Encoding: "
+        + textTransferEncoding
         + "\r\n"
-        + textPart
+        + "\r\n"
+        + encodedTextPart
         + "\r\n"
 
         // Output the HTML part:
@@ -309,9 +331,11 @@
         + boundary
         + "\r\n"
         + "Content-Type: text/html; charset=UTF-8\r\n"
-        + "Content-Transfer-Encoding: 8bit\r\n"
+        + "Content-Transfer-Encoding: "
+        + htmlTransferEncoding
         + "\r\n"
-        + htmlPart
+        + "\r\n"
+        + encodedHtmlPart
         + "\r\n"
 
         // Output the closing boundary.
@@ -320,8 +344,15 @@
         + "--\r\n";
   }
 
-  private void setMissingHeader(
-      final Map<String, EmailHeader> hdrs, final String name, final String value) {
+  protected String quotedPrintableEncode(String input) throws IOException {
+    ByteArrayOutputStream s = new ByteArrayOutputStream();
+    try (QuotedPrintableOutputStream qp = new QuotedPrintableOutputStream(s, false)) {
+      qp.write(input.getBytes(UTF_8));
+    }
+    return s.toString();
+  }
+
+  private static void setMissingHeader(Map<String, EmailHeader> hdrs, String name, String value) {
     if (!hdrs.containsKey(name) || hdrs.get(name).isEmpty()) {
       hdrs.put(name, new EmailHeader.String(value));
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginRestApiModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
index 6b52a59..8e162ba 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginRestApiModule.java
@@ -22,7 +22,6 @@
 public class PluginRestApiModule extends RestApiModule {
   @Override
   protected void configure() {
-    install(new PluginModule());
     bind(PluginsCollection.class);
     DynamicMap.mapOf(binder(), PLUGIN_KIND);
     put(PLUGIN_KIND).to(InstallPlugin.Overwrite.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateTag.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateTag.java
index f674d17..3a6db40 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateTag.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateTag.java
@@ -28,6 +28,7 @@
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.WebLinks;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.TagCache;
@@ -60,6 +61,7 @@
   private final GitRepositoryManager repoManager;
   private final TagCache tagCache;
   private final GitReferenceUpdated referenceUpdated;
+  private final WebLinks links;
   private String ref;
 
   @Inject
@@ -68,11 +70,13 @@
       GitRepositoryManager repoManager,
       TagCache tagCache,
       GitReferenceUpdated referenceUpdated,
+      WebLinks webLinks,
       @Assisted String ref) {
     this.identifiedUser = identifiedUser;
     this.repoManager = repoManager;
     this.tagCache = tagCache;
     this.referenceUpdated = referenceUpdated;
+    this.links = webLinks;
     this.ref = ref;
   }
 
@@ -134,7 +138,8 @@
             result.getObjectId(),
             identifiedUser.get().getAccount());
         try (RevWalk w = new RevWalk(repo)) {
-          return ListTags.createTagInfo(result, w, refControl);
+          ProjectControl pctl = resource.getControl();
+          return ListTags.createTagInfo(result, w, refControl, pctl, links);
         }
       }
     } catch (InvalidRevisionException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
index 4601bfe..049e2e3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.server.project;
 
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
@@ -51,7 +53,7 @@
       throw new ResourceConflictException("branch " + rsrc.getBranchKey() + " has open changes");
     }
 
-    deleteRefFactory.create(rsrc).ref(rsrc.getRef()).delete();
+    deleteRefFactory.create(rsrc).ref(rsrc.getRef()).prefix(R_HEADS).delete();
     return Response.none();
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java
index f5e55b1..4c54423 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranches.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.server.project;
 
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+
 import com.google.gerrit.extensions.api.projects.DeleteBranchesInput;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.Response;
@@ -41,7 +43,7 @@
       throw new BadRequestException("branches must be specified");
     }
 
-    deleteRefFactory.create(project).refs(input.branches).delete();
+    deleteRefFactory.create(project).refs(input.branches).prefix(R_HEADS).delete();
     return Response.none();
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
index 7f1ee60..d7385fe 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListTags.java
@@ -17,6 +17,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.api.projects.TagInfo;
+import com.google.gerrit.extensions.common.WebLinkInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -24,6 +25,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.CommonConverters;
+import com.google.gerrit.server.WebLinks;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.SearchingChangeCacheImpl;
 import com.google.gerrit.server.git.TagCache;
@@ -54,6 +56,7 @@
   private final TagCache tagCache;
   private final ChangeNotes.Factory changeNotesFactory;
   @Nullable private final SearchingChangeCacheImpl changeCache;
+  private final WebLinks links;
 
   @Option(
     name = "--limit",
@@ -106,12 +109,14 @@
       Provider<ReviewDb> dbProvider,
       TagCache tagCache,
       ChangeNotes.Factory changeNotesFactory,
-      @Nullable SearchingChangeCacheImpl changeCache) {
+      @Nullable SearchingChangeCacheImpl changeCache,
+      WebLinks webLinks) {
     this.repoManager = repoManager;
     this.dbProvider = dbProvider;
     this.tagCache = tagCache;
     this.changeNotesFactory = changeNotesFactory;
     this.changeCache = changeCache;
+    this.links = webLinks;
   }
 
   @Override
@@ -121,11 +126,11 @@
 
     try (Repository repo = getRepository(resource.getNameKey());
         RevWalk rw = new RevWalk(repo)) {
-      ProjectControl control = resource.getControl();
+      ProjectControl pctl = resource.getControl();
       Map<String, Ref> all =
-          visibleTags(control, repo, repo.getRefDatabase().getRefs(Constants.R_TAGS));
+          visibleTags(pctl, repo, repo.getRefDatabase().getRefs(Constants.R_TAGS));
       for (Ref ref : all.values()) {
-        tags.add(createTagInfo(ref, rw, control.controlForRef(ref.getName())));
+        tags.add(createTagInfo(ref, rw, pctl.controlForRef(ref.getName()), pctl, links));
       }
     }
 
@@ -155,18 +160,19 @@
         tagName = Constants.R_TAGS + tagName;
       }
       Ref ref = repo.getRefDatabase().exactRef(tagName);
-      ProjectControl control = resource.getControl();
-      if (ref != null
-          && !visibleTags(control, repo, ImmutableMap.of(ref.getName(), ref)).isEmpty()) {
-        return createTagInfo(ref, rw, control.controlForRef(ref.getName()));
+      ProjectControl pctl = resource.getControl();
+      if (ref != null && !visibleTags(pctl, repo, ImmutableMap.of(ref.getName(), ref)).isEmpty()) {
+        return createTagInfo(ref, rw, pctl.controlForRef(ref.getName()), pctl, links);
       }
     }
     throw new ResourceNotFoundException(id);
   }
 
-  public static TagInfo createTagInfo(Ref ref, RevWalk rw, RefControl control)
+  public static TagInfo createTagInfo(
+      Ref ref, RevWalk rw, RefControl control, ProjectControl pctl, WebLinks links)
       throws MissingObjectException, IOException {
     RevObject object = rw.parseAny(ref.getObjectId());
+    List<WebLinkInfo> webLinks = links.getTagLinks(pctl.getProject().getName(), ref.getName());
     if (object instanceof RevTag) {
       // Annotated or signed tag
       RevTag tag = (RevTag) object;
@@ -177,10 +183,15 @@
           tag.getObject().getName(),
           tag.getFullMessage().trim(),
           tagger != null ? CommonConverters.toGitPerson(tag.getTaggerIdent()) : null,
-          control.canDelete());
+          control.canDelete(),
+          webLinks.isEmpty() ? null : webLinks);
     }
     // Lightweight tag
-    return new TagInfo(ref.getName(), ref.getObjectId().getName(), control.canDelete());
+    return new TagInfo(
+        ref.getName(),
+        ref.getObjectId().getName(),
+        control.canDelete(),
+        webLinks.isEmpty() ? null : webLinks);
   }
 
   private Repository getRepository(Project.NameKey project)
@@ -193,9 +204,9 @@
   }
 
   private Map<String, Ref> visibleTags(
-      ProjectControl control, Repository repo, Map<String, Ref> tags) {
+      ProjectControl pctl, Repository repo, Map<String, Ref> tags) {
     return new VisibleRefFilter(
-            tagCache, changeNotesFactory, changeCache, repo, control, dbProvider.get(), false)
+            tagCache, changeNotesFactory, changeCache, repo, pctl, dbProvider.get(), false)
         .filter(tags, true);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
index e9976c5..5684082 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
@@ -336,7 +336,9 @@
 
   /** @return true if the user can upload to at least one reference */
   public Capable canPushToAtLeastOneRef() {
-    if (!canPerformOnAnyRef(Permission.PUSH) && !canPerformOnAnyRef(Permission.CREATE_TAG)) {
+    if (!canPerformOnAnyRef(Permission.PUSH)
+        && !canPerformOnAnyRef(Permission.CREATE_TAG)
+        && !isOwner()) {
       String pName = state.getProject().getName();
       return new Capable("Upload denied for project '" + pName + "'");
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefFilter.java
index a789a7b..76bafc0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefFilter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefFilter.java
@@ -56,6 +56,9 @@
   }
 
   public List<T> filter(List<T> refs) throws BadRequestException {
+    if (!Strings.isNullOrEmpty(matchSubstring) && !Strings.isNullOrEmpty(matchRegex)) {
+      throw new BadRequestException("specify exactly one of m/r");
+    }
     FluentIterable<T> results = FluentIterable.from(refs);
     if (!Strings.isNullOrEmpty(matchSubstring)) {
       results = results.filter(new SubstringPredicate(matchSubstring));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index af2cb60..5c3e8c9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -471,11 +471,6 @@
 
   @Operator
   public Predicate<ChangeData> change(String query) throws QueryParseException {
-    if (PAT_LEGACY_ID.matcher(query).matches()) {
-      return new LegacyChangeIdPredicate(Change.Id.parse(query));
-    } else if (PAT_CHANGE_ID.matcher(query).matches()) {
-      return new ChangeIdPredicate(parseChangeId(query));
-    }
     Optional<ChangeTriplet> triplet = ChangeTriplet.parse(query);
     if (triplet.isPresent()) {
       return Predicate.and(
@@ -483,6 +478,11 @@
           branch(triplet.get().branch().get()),
           new ChangeIdPredicate(parseChangeId(triplet.get().id().get())));
     }
+    if (PAT_LEGACY_ID.matcher(query).matches()) {
+      return new LegacyChangeIdPredicate(Change.Id.parse(query));
+    } else if (PAT_CHANGE_ID.matcher(query).matches()) {
+      return new ChangeIdPredicate(parseChangeId(query));
+    }
 
     throw new QueryParseException("Invalid change format");
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
index f34c22cb..e7a7013 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -168,6 +168,7 @@
   protected Order order;
   protected OnSubmitValidators onSubmitValidators;
   protected RequestId requestId;
+  protected String refLogMessage;
 
   private boolean updateChangesInParallel;
   private boolean closeRepo;
@@ -218,6 +219,11 @@
     return this;
   }
 
+  public BatchUpdate setRefLogMessage(String refLogMessage) {
+    this.refLogMessage = refLogMessage;
+    return this;
+  }
+
   public BatchUpdate setOrder(Order order) {
     this.order = order;
     return this;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
index 2b07280..67d1e7e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
@@ -471,6 +471,10 @@
     // May not be opened if the caller added ref updates but no new objects.
     initRepository();
     batchRefUpdate = repo.getRefDatabase().newBatchUpdate();
+    batchRefUpdate.setRefLogMessage(refLogMessage, true);
+    if (user.isIdentifiedUser()) {
+      batchRefUpdate.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
+    }
     commands.addTo(batchRefUpdate);
     logDebug("Executing batch of {} ref updates", batchRefUpdate.getCommands().size());
     if (dryrun) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
index 3ad0116..5a72d5c 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
@@ -160,9 +160,19 @@
 
   public static PermissionRule blockLabel(
       ProjectConfig project, String labelName, AccountGroup.UUID group, String ref) {
+    return blockLabel(project, labelName, -1, 1, group, ref);
+  }
+
+  public static PermissionRule blockLabel(
+      ProjectConfig project,
+      String labelName,
+      int min,
+      int max,
+      AccountGroup.UUID group,
+      String ref) {
     PermissionRule r = grant(project, Permission.LABEL + labelName, newRule(project, group), ref);
     r.setBlock();
-    r.setRange(-1, 1);
+    r.setRange(min, max);
     return r;
   }
 
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index cd179b5..d0c8df3 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -256,25 +256,25 @@
 
   @Test
   public void byTriplet() throws Exception {
-    TestRepository<Repo> repo = createProject("repo");
+    TestRepository<Repo> repo = createProject("iabcde");
     Change change = insert(repo, newChangeForBranch(repo, "branch"));
     String k = change.getKey().get();
 
-    assertQuery("repo~branch~" + k, change);
-    assertQuery("change:repo~branch~" + k, change);
-    assertQuery("repo~refs/heads/branch~" + k, change);
-    assertQuery("change:repo~refs/heads/branch~" + k, change);
-    assertQuery("repo~branch~" + k.substring(0, 10), change);
-    assertQuery("change:repo~branch~" + k.substring(0, 10), change);
+    assertQuery("iabcde~branch~" + k, change);
+    assertQuery("change:iabcde~branch~" + k, change);
+    assertQuery("iabcde~refs/heads/branch~" + k, change);
+    assertQuery("change:iabcde~refs/heads/branch~" + k, change);
+    assertQuery("iabcde~branch~" + k.substring(0, 10), change);
+    assertQuery("change:iabcde~branch~" + k.substring(0, 10), change);
 
     assertQuery("foo~bar");
     assertThatQueryException("change:foo~bar").hasMessageThat().isEqualTo("Invalid change format");
     assertQuery("otherrepo~branch~" + k);
     assertQuery("change:otherrepo~branch~" + k);
-    assertQuery("repo~otherbranch~" + k);
-    assertQuery("change:repo~otherbranch~" + k);
-    assertQuery("repo~branch~I0000000000000000000000000000000000000000");
-    assertQuery("change:repo~branch~I0000000000000000000000000000000000000000");
+    assertQuery("iabcde~otherbranch~" + k);
+    assertQuery("change:iabcde~otherbranch~" + k);
+    assertQuery("iabcde~branch~I0000000000000000000000000000000000000000");
+    assertQuery("change:iabcde~branch~I0000000000000000000000000000000000000000");
   }
 
   @Test
diff --git a/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAccountCache.java b/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAccountCache.java
index d81d441..3c5bc85 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAccountCache.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/testutil/FakeAccountCache.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.testutil;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.server.account.AccountCache;
@@ -42,6 +43,12 @@
   }
 
   @Override
+  @Nullable
+  public synchronized AccountState getOrNull(Account.Id accountId) {
+    return byId.get(accountId);
+  }
+
+  @Override
   public synchronized AccountState getIfPresent(Account.Id accountId) {
     return byId.get(accountId);
   }
diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml
index 2dcf3c1..2a0abdb 100644
--- a/gerrit-war/pom.xml
+++ b/gerrit-war/pom.xml
@@ -2,7 +2,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.google.gerrit</groupId>
   <artifactId>gerrit-war</artifactId>
-  <version>2.14.1-SNAPSHOT</version>
+  <version>2.14.1</version>
   <packaging>war</packaging>
   <name>Gerrit Code Review - WAR</name>
   <description>Gerrit WAR</description>
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
index 0535f26..e1eb9de 100644
--- a/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
+++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/SitePathFromSystemConfigProvider.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.reviewdb.client.SystemConfig;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.config.SitePath;
+import com.google.gerrit.server.schema.ReviewDbFactory;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
@@ -30,7 +31,8 @@
   private final Path path;
 
   @Inject
-  SitePathFromSystemConfigProvider(SchemaFactory<ReviewDb> schemaFactory) throws OrmException {
+  SitePathFromSystemConfigProvider(@ReviewDbFactory SchemaFactory<ReviewDb> schemaFactory)
+      throws OrmException {
     path = read(schemaFactory);
   }
 
diff --git a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
index a4e8e3c..634abb9 100644
--- a/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
+++ b/gerrit-war/src/main/java/com/google/gerrit/httpd/WebAppInitializer.java
@@ -61,6 +61,7 @@
 import com.google.gerrit.server.notedb.ConfigNotesMigration;
 import com.google.gerrit.server.patch.DiffExecutorModule;
 import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
+import com.google.gerrit.server.plugins.PluginModule;
 import com.google.gerrit.server.plugins.PluginRestApiModule;
 import com.google.gerrit.server.schema.DataSourceModule;
 import com.google.gerrit.server.schema.DataSourceProvider;
@@ -321,7 +322,21 @@
     modules.add(cfgInjector.getInstance(MailReceiver.Module.class));
     modules.add(new SmtpEmailSender.Module());
     modules.add(new SignedTokenEmailTokenVerifier.Module());
+
+    // Plugin module needs to be inserted *before* the index module.
+    // There is the concept of LifecycleModule, in Gerrit's own extension
+    // to Guice, which has these:
+    //  listener().to(SomeClassImplementingLifecycleListener.class);
+    // and the start() methods of each such listener are executed in the
+    // order they are declared.
+    // Makes sure that PluginLoader.start() is executed before the
+    // LuceneIndexModule.start() so that plugins get loaded and the respective
+    // Guice modules installed so that the on-line reindexing will happen
+    // with the proper classes (e.g. group backends, custom Prolog
+    // predicates) and the associated rules ready to be evaluated.
+    modules.add(new PluginModule());
     modules.add(new PluginRestApiModule());
+
     modules.add(new RestCacheAdminModule());
     modules.add(new GpgModule(config));
     modules.add(new StartupChecks.Module());
diff --git a/lib/highlightjs/building.md b/lib/highlightjs/building.md
index 8cb9e8b..b35592f 100644
--- a/lib/highlightjs/building.md
+++ b/lib/highlightjs/building.md
@@ -30,22 +30,27 @@
           css \
           d \
           dart \
+          erb \
           go \
           haskell \
           java \
           javascript \
           json \
+          kotlin \
           lisp \
           lua \
           markdown \
           objectivec \
           ocaml \
           perl \
+          php \
           protobuf \
+          puppet \
           python \
           ruby \
           rust \
           scala \
+          shell \
           sql \
           swift \
           typescript \
diff --git a/lib/highlightjs/highlight.min.js b/lib/highlightjs/highlight.min.js
index cfc8c1c..069a018 100644
--- a/lib/highlightjs/highlight.min.js
+++ b/lib/highlightjs/highlight.min.js
@@ -1,105 +1,124 @@
-/*! highlight.js v9.5.0 | BSD3 License | git.io/hljslicense */
-(function(b){var p="object"===typeof window&&window||"object"===typeof self&&self;"undefined"!==typeof exports?b(exports):p&&(p.hljs=b({}),"function"===typeof define&&define.amd&&define([],function(){return p.hljs}))})(function(b){function p(a){return a.replace(/[&<>]/gm,function(a){return M[a]})}function C(a,c){var e=a&&a.exec(c);return e&&0===e.index}function v(a,c){var e,b={};for(e in a)b[e]=a[e];if(c)for(e in c)b[e]=c[e];return b}function H(a){var c=[];(function g(a,b){for(var k=a.firstChild;k;k=
-k.nextSibling)3===k.nodeType?b+=k.nodeValue.length:1===k.nodeType&&(c.push({event:"start",offset:b,node:k}),b=g(k,b),k.nodeName.toLowerCase().match(/br|hr|img|input/)||c.push({event:"stop",offset:b,node:k}));return b})(a,0);return c}function N(a,c,e){function b(){return a.length&&c.length?a[0].offset!==c[0].offset?a[0].offset<c[0].offset?a:c:"start"===c[0].event?a:c:a.length?a:c}function d(a){n+="<"+a.nodeName.toLowerCase()+I.map.call(a.attributes,function(a){return" "+a.nodeName+'="'+p(a.value)+
-'"'}).join("")+">"}function f(a){n+="</"+a.nodeName.toLowerCase()+">"}function k(a){("start"===a.event?d:f)(a.node)}for(var l=0,n="",m=[];a.length||c.length;){var h=b(),n=n+p(e.substr(l,h[0].offset-l)),l=h[0].offset;if(h===a){m.reverse().forEach(f);do k(h.splice(0,1)[0]),h=b();while(h===a&&h.length&&h[0].offset===l);m.reverse().forEach(d)}else"start"===h[0].event?m.push(h[0].node):m.pop(),k(h.splice(0,1)[0])}return n+p(e.substr(l))}function O(a){function c(a){return a&&a.source||a}function e(e,b){return new RegExp(c(e),
-"m"+(a.case_insensitive?"i":"")+(b?"g":""))}function b(d,f){if(!d.compiled){d.compiled=!0;d.keywords=d.keywords||d.beginKeywords;if(d.keywords){var k={},l=function(c,e){a.case_insensitive&&(e=e.toLowerCase());e.split(" ").forEach(function(a){a=a.split("|");k[a[0]]=[c,a[1]?Number(a[1]):1]})};"string"===typeof d.keywords?l("keyword",d.keywords):D(d.keywords).forEach(function(a){l(a,d.keywords[a])});d.keywords=k}d.lexemesRe=e(d.lexemes||/\w+/,!0);f&&(d.beginKeywords&&(d.begin="\\b("+d.beginKeywords.split(" ").join("|")+
-")\\b"),d.begin||(d.begin=/\B|\b/),d.beginRe=e(d.begin),d.end||d.endsWithParent||(d.end=/\B|\b/),d.end&&(d.endRe=e(d.end)),d.terminator_end=c(d.end)||"",d.endsWithParent&&f.terminator_end&&(d.terminator_end+=(d.end?"|":"")+f.terminator_end));d.illegal&&(d.illegalRe=e(d.illegal));null==d.relevance&&(d.relevance=1);d.contains||(d.contains=[]);var n=[];d.contains.forEach(function(a){a.variants?a.variants.forEach(function(c){n.push(v(a,c))}):n.push("self"===a?d:a)});d.contains=n;d.contains.forEach(function(a){b(a,
-d)});d.starts&&b(d.starts,f);var m=d.contains.map(function(a){return a.beginKeywords?"\\.?("+a.begin+")\\.?":a.begin}).concat([d.terminator_end,d.illegal]).map(c).filter(Boolean);d.terminators=m.length?e(m.join("|"),!0):{exec:function(){return null}}}}b(a)}function A(a,c,e,b){function d(a,c){if(C(a.endRe,c)){for(;a.endsParent&&a.parent;)a=a.parent;return a}if(a.endsWithParent)return d(a.parent,c)}function f(a,c,e,b){return'<span class="'+(b?"":t.classPrefix)+(a+'">')+c+(e?"":"</span>")}function k(){var a=
-r,c;if(null!=h.subLanguage)if((c="string"===typeof h.subLanguage)&&!w[h.subLanguage])c=p(q);else{var e=c?A(h.subLanguage,q,!0,u[h.subLanguage]):F(q,h.subLanguage.length?h.subLanguage:void 0);0<h.relevance&&(B+=e.relevance);c&&(u[h.subLanguage]=e.top);c=f(e.language,e.value,!1,!0)}else{var b;if(h.keywords){e="";b=0;h.lexemesRe.lastIndex=0;for(c=h.lexemesRe.exec(q);c;){e+=p(q.substr(b,c.index-b));b=h;var d=c,d=m.case_insensitive?d[0].toLowerCase():d[0];(b=b.keywords.hasOwnProperty(d)&&b.keywords[d])?
-(B+=b[1],e+=f(b[0],p(c[0]))):e+=p(c[0]);b=h.lexemesRe.lastIndex;c=h.lexemesRe.exec(q)}c=e+p(q.substr(b))}else c=p(q)}r=a+c;q=""}function l(a){r+=a.className?f(a.className,"",!0):"";h=Object.create(a,{parent:{value:h}})}function n(a,c){q+=a;if(null==c)return k(),0;var b;a:{b=h;var f,g;f=0;for(g=b.contains.length;f<g;f++)if(C(b.contains[f].beginRe,c)){b=b.contains[f];break a}b=void 0}if(b)return b.skip?q+=c:(b.excludeBegin&&(q+=c),k(),b.returnBegin||b.excludeBegin||(q=c)),l(b,c),b.returnBegin?0:c.length;
-if(b=d(h,c)){f=h;f.skip?q+=c:(f.returnEnd||f.excludeEnd||(q+=c),k(),f.excludeEnd&&(q=c));do h.className&&(r+="</span>"),h.skip||(B+=h.relevance),h=h.parent;while(h!==b.parent);b.starts&&l(b.starts,"");return f.returnEnd?0:c.length}if(!e&&C(h.illegalRe,c))throw Error('Illegal lexeme "'+c+'" for mode "'+(h.className||"<unnamed>")+'"');q+=c;return c.length||1}var m=x(a);if(!m)throw Error('Unknown language: "'+a+'"');O(m);var h=b||m,u={},r="";for(b=h;b!==m;b=b.parent)b.className&&(r=f(b.className,"",
-!0)+r);var q="",B=0;try{for(var y,v,z=0;;){h.terminators.lastIndex=z;y=h.terminators.exec(c);if(!y)break;v=n(c.substr(z,y.index-z),y[0]);z=y.index+v}n(c.substr(z));for(b=h;b.parent;b=b.parent)b.className&&(r+="</span>");return{relevance:B,value:r,language:a,top:h}}catch(E){if(E.message&&-1!==E.message.indexOf("Illegal"))return{relevance:0,value:p(c)};throw E;}}function F(a,c){c=c||t.languages||D(w);var b={relevance:0,value:p(a)},g=b;c.filter(x).forEach(function(c){var f=A(c,a,!1);f.language=c;f.relevance>
-g.relevance&&(g=f);f.relevance>b.relevance&&(g=b,b=f)});g.language&&(b.second_best=g);return b}function J(a){return t.tabReplace||t.useBR?a.replace(P,function(a,b){if(t.useBR&&"\n"===a)return"<br>";if(t.tabReplace)return b.replace(/\t/g,t.tabReplace)}):a}function K(a){var c,b,g,d,f;a:if(b=a.className+" ",b+=a.parentNode?a.parentNode.className:"",f=Q.exec(b))f=x(f[1])?f[1]:"no-highlight";else{b=b.split(/\s+/);f=0;for(d=b.length;f<d;f++)if(c=b[f],L.test(c)||x(c)){f=c;break a}f=void 0}L.test(f)||(t.useBR?
-(c=document.createElementNS("http://www.w3.org/1999/xhtml","div"),c.innerHTML=a.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):c=a,d=c.textContent,b=f?A(f,d,!0):F(d),c=H(c),c.length&&(g=document.createElementNS("http://www.w3.org/1999/xhtml","div"),g.innerHTML=b.value,b.value=N(c,H(g),d)),b.value=J(b.value),a.innerHTML=b.value,d=a.className,f=f?G[f]:b.language,c=[d.trim()],d.match(/\bhljs\b/)||c.push("hljs"),-1===d.indexOf(f)&&c.push(f),f=c.join(" ").trim(),a.className=f,a.result={language:b.language,
-re:b.relevance},b.second_best&&(a.second_best={language:b.second_best.language,re:b.second_best.relevance}))}function u(){if(!u.called){u.called=!0;var a=document.querySelectorAll("pre code");I.forEach.call(a,K)}}function x(a){a=(a||"").toLowerCase();return w[a]||w[G[a]]}var I=[],D=Object.keys,w={},G={},L=/^(no-?highlight|plain|text)$/i,Q=/\blang(?:uage)?-([\w-]+)\b/i,P=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,t={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},M={"&":"&amp;","<":"&lt;",">":"&gt;"};
-b.highlight=A;b.highlightAuto=F;b.fixMarkup=J;b.highlightBlock=K;b.configure=function(a){t=v(t,a)};b.initHighlighting=u;b.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",u,!1);addEventListener("load",u,!1)};b.registerLanguage=function(a,c){var e=w[a]=c(b);e.aliases&&e.aliases.forEach(function(c){G[c]=a})};b.listLanguages=function(){return D(w)};b.getLanguage=x;b.inherit=v;b.IDENT_RE="[a-zA-Z]\\w*";b.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*";b.NUMBER_RE="\\b\\d+(\\.\\d+)?";b.C_NUMBER_RE=
-"(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";b.BINARY_NUMBER_RE="\\b(0b[01]+)";b.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";b.BACKSLASH_ESCAPE={begin:"\\\\[\\s\\S]",relevance:0};b.APOS_STRING_MODE={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[b.BACKSLASH_ESCAPE]};b.QUOTE_STRING_MODE={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[b.BACKSLASH_ESCAPE]};
-b.PHRASAL_WORDS_MODE={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/};b.COMMENT=function(a,c,e){a=b.inherit({className:"comment",begin:a,end:c,contains:[]},e||{});a.contains.push(b.PHRASAL_WORDS_MODE);a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0});return a};b.C_LINE_COMMENT_MODE=b.COMMENT("//","$");b.C_BLOCK_COMMENT_MODE=b.COMMENT("/\\*","\\*/");b.HASH_COMMENT_MODE=b.COMMENT("#",
-"$");b.NUMBER_MODE={className:"number",begin:b.NUMBER_RE,relevance:0};b.C_NUMBER_MODE={className:"number",begin:b.C_NUMBER_RE,relevance:0};b.BINARY_NUMBER_MODE={className:"number",begin:b.BINARY_NUMBER_RE,relevance:0};b.CSS_NUMBER_MODE={className:"number",begin:b.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0};b.REGEXP_MODE={className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[b.BACKSLASH_ESCAPE,{begin:/\[/,
-end:/\]/,relevance:0,contains:[b.BACKSLASH_ESCAPE]}]};b.TITLE_MODE={className:"title",begin:b.IDENT_RE,relevance:0};b.UNDERSCORE_TITLE_MODE={className:"title",begin:b.UNDERSCORE_IDENT_RE,relevance:0};b.METHOD_GUARD={begin:"\\.\\s*"+b.UNDERSCORE_IDENT_RE,relevance:0};b.registerLanguage("bash",function(a){var c={className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{(.*?)}/}]},b={className:"string",begin:/"/,end:/"/,contains:[a.BACKSLASH_ESCAPE,c,{className:"variable",begin:/\$\(/,
-end:/\)/,contains:[a.BACKSLASH_ESCAPE]}]};return{aliases:["sh","zsh"],lexemes:/-?[a-z\.]+/,keywords:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",
-_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[{className:"meta",begin:/^#![^\n]+sh\s*$/,relevance:10},{className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0},a.HASH_COMMENT_MODE,b,{className:"string",begin:/'/,end:/'/},c]}});b.registerLanguage("clojure",function(a){var c={className:"number",begin:"[-+]?\\d+(\\.\\d+)?",relevance:0},b=a.inherit(a.QUOTE_STRING_MODE,{illegal:null}),g=a.COMMENT(";","$",{relevance:0}),
-d={className:"literal",begin:/\b(true|false|nil)\b/},f={begin:"[\\[\\{]",end:"[\\]\\}]"},k={className:"comment",begin:"\\^[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*"},l=a.COMMENT("\\^\\{","\\}"),n={className:"symbol",begin:"[:]{1,2}[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*"},m={begin:"\\(",end:"\\)"},h={endsWithParent:!0,relevance:0},p={keywords:{"builtin-name":"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},
-lexemes:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",className:"name",begin:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",starts:h},r=[m,b,k,l,g,n,f,c,d,{begin:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",relevance:0}];m.contains=[a.COMMENT("comment",""),p,h];h.contains=r;f.contains=r;return{aliases:["clj"],illegal:/\S/,contains:[m,b,k,l,g,n,f,c,d]}});b.registerLanguage("cpp",function(a){var c={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},b={className:"string",variants:[{begin:'(u8?|U)?L?"',
-end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:'(u8?|U)?R"',end:'"',contains:[a.BACKSLASH_ESCAPE]},{begin:"'\\\\?.",end:"'",illegal:"."}]},g={className:"number",variants:[{begin:"\\b(0b[01'_]+)"},{begin:"\\b([\\d'_]+(\\.[\\d'_]*)?|\\.[\\d'_]+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9'_]+|(\\b[\\d'_]+(\\.[\\d'_]*)?|\\.[\\d'_]+)([eE][-+]?[\\d'_]+)?)"}],relevance:0},d={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},
-contains:[{begin:/\\\n/,relevance:0},a.inherit(b,{className:"meta-string"}),{className:"meta-string",begin:"<",end:">",illegal:"\\n"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},f=a.IDENT_RE+"\\s*\\(",k={keyword:"int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return",
+/*
+ highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */
+var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(b,g,l){b!=Array.prototype&&b!=Object.prototype&&(b[g]=l.value)};$jscomp.getGlobal=function(b){return"undefined"!=typeof window&&window===b?b:"undefined"!=typeof global&&null!=global?global:b};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_";
+$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(b){return $jscomp.SYMBOL_PREFIX+(b||"")+$jscomp.symbolCounter_++};
+$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var b=$jscomp.global.Symbol.iterator;b||(b=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[b]&&$jscomp.defineProperty(Array.prototype,b,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(b){var g=0;return $jscomp.iteratorPrototype(function(){return g<b.length?{done:!1,value:b[g++]}:{done:!0}})};
+$jscomp.iteratorPrototype=function(b){$jscomp.initSymbolIterator();b={next:b};b[$jscomp.global.Symbol.iterator]=function(){return this};return b};$jscomp.iteratorFromArray=function(b,g){$jscomp.initSymbolIterator();b instanceof String&&(b+="");var l=0,k={next:function(){if(l<b.length){var m=l++;return{value:g(m,b[m]),done:!1}}k.next=function(){return{done:!0,value:void 0}};return k.next()}};k[Symbol.iterator]=function(){return k};return k};
+$jscomp.polyfill=function(b,g,l,k){if(g){l=$jscomp.global;b=b.split(".");for(k=0;k<b.length-1;k++){var m=b[k];m in l||(l[m]={});l=l[m]}b=b[b.length-1];k=l[b];g=g(k);g!=k&&null!=g&&$jscomp.defineProperty(l,b,{configurable:!0,writable:!0,value:g})}};$jscomp.polyfill("Array.prototype.keys",function(b){return b?b:function(){return $jscomp.iteratorFromArray(this,function(b){return b})}},"es6","es3");
+(function(b){var g="object"===typeof window&&window||"object"===typeof self&&self;"undefined"!==typeof exports?b(exports):g&&(g.hljs=b({}),"function"===typeof define&&define.amd&&define([],function(){return g.hljs}))})(function(b){function g(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function l(a,f){return(a=a&&a.exec(f))&&0===a.index}function k(a){var f,b={},e=Array.prototype.slice.call(arguments,1);for(f in a)b[f]=a[f];e.forEach(function(a){for(f in a)b[f]=a[f]});
+return b}function m(a){var f=[];(function e(a,b){for(a=a.firstChild;a;a=a.nextSibling)3===a.nodeType?b+=a.nodeValue.length:1===a.nodeType&&(f.push({event:"start",offset:b,node:a}),b=e(a,b),a.nodeName.toLowerCase().match(/br|hr|img|input/)||f.push({event:"stop",offset:b,node:a}));return b})(a,0);return f}function L(a,f,b){function d(){return a.length&&f.length?a[0].offset!==f[0].offset?a[0].offset<f[0].offset?a:f:"start"===f[0].event?a:f:a.length?a:f}function c(a){B+="<"+a.nodeName.toLowerCase()+H.map.call(a.attributes,
+function(a){return" "+a.nodeName+'="'+g(a.value).replace('"',"&quot;")+'"'}).join("")+">"}function q(a){B+="</"+a.nodeName.toLowerCase()+">"}function w(a){("start"===a.event?c:q)(a.node)}for(var r=0,B="",n=[];a.length||f.length;){var h=d();B+=g(b.substring(r,h[0].offset));r=h[0].offset;if(h===a){n.reverse().forEach(q);do w(h.splice(0,1)[0]),h=d();while(h===a&&h.length&&h[0].offset===r);n.reverse().forEach(c)}else"start"===h[0].event?n.push(h[0].node):n.pop(),w(h.splice(0,1)[0])}return B+g(b.substr(r))}
+function M(a){a.variants&&!a.cached_variants&&(a.cached_variants=a.variants.map(function(f){return k(a,{variants:null},f)}));return a.cached_variants||a.endsWithParent&&[k(a)]||[a]}function N(a){function f(a){return a&&a.source||a}function b(b,d){return new RegExp(f(b),"m"+(a.case_insensitive?"i":"")+(d?"g":""))}function e(c,d){if(!c.compiled){c.compiled=!0;c.keywords=c.keywords||c.beginKeywords;if(c.keywords){var q={},g=function(f,b){a.case_insensitive&&(b=b.toLowerCase());b.split(" ").forEach(function(a){a=
+a.split("|");q[a[0]]=[f,a[1]?Number(a[1]):1]})};"string"===typeof c.keywords?g("keyword",c.keywords):x(c.keywords).forEach(function(a){g(a,c.keywords[a])});c.keywords=q}c.lexemesRe=b(c.lexemes||/\w+/,!0);d&&(c.beginKeywords&&(c.begin="\\b("+c.beginKeywords.split(" ").join("|")+")\\b"),c.begin||(c.begin=/\B|\b/),c.beginRe=b(c.begin),c.end||c.endsWithParent||(c.end=/\B|\b/),c.end&&(c.endRe=b(c.end)),c.terminator_end=f(c.end)||"",c.endsWithParent&&d.terminator_end&&(c.terminator_end+=(c.end?"|":"")+
+d.terminator_end));c.illegal&&(c.illegalRe=b(c.illegal));null==c.relevance&&(c.relevance=1);c.contains||(c.contains=[]);c.contains=Array.prototype.concat.apply([],c.contains.map(function(a){return M("self"===a?c:a)}));c.contains.forEach(function(a){e(a,c)});c.starts&&e(c.starts,d);d=c.contains.map(function(a){return a.beginKeywords?"\\.?("+a.begin+")\\.?":a.begin}).concat([c.terminator_end,c.illegal]).map(f).filter(Boolean);c.terminators=d.length?b(d.join("|"),!0):{exec:function(){return null}}}}
+e(a)}function C(a,f,b,e){function c(a,b){if(l(a.endRe,b)){for(;a.endsParent&&a.parent;)a=a.parent;return a}if(a.endsWithParent)return c(a.parent,b)}function d(a,b,f,d){return'<span class="'+(d?"":t.classPrefix)+(a+'">')+b+(f?"":"</span>")}function w(){var a=v,b;if(null!=h.subLanguage)if((b="string"===typeof h.subLanguage)&&!y[h.subLanguage])b=g(p);else{var f=b?C(h.subLanguage,p,!0,m[h.subLanguage]):F(p,h.subLanguage.length?h.subLanguage:void 0);0<h.relevance&&(u+=f.relevance);b&&(m[h.subLanguage]=
+f.top);b=d(f.language,f.value,!1,!0)}else if(h.keywords){f="";var c=0;h.lexemesRe.lastIndex=0;for(b=h.lexemesRe.exec(p);b;){f+=g(p.substring(c,b.index));c=h;var e=b;e=n.case_insensitive?e[0].toLowerCase():e[0];(c=c.keywords.hasOwnProperty(e)&&c.keywords[e])?(u+=c[1],f+=d(c[0],g(b[0]))):f+=g(b[0]);c=h.lexemesRe.lastIndex;b=h.lexemesRe.exec(p)}b=f+g(p.substr(c))}else b=g(p);v=a+b;p=""}function r(a){v+=a.className?d(a.className,"",!0):"";h=Object.create(a,{parent:{value:h}})}function k(a,f){p+=a;if(null==
+f)return w(),0;a:{a=h;var d;var e=0;for(d=a.contains.length;e<d;e++)if(l(a.contains[e].beginRe,f)){a=a.contains[e];break a}a=void 0}if(a)return a.skip?p+=f:(a.excludeBegin&&(p+=f),w(),a.returnBegin||a.excludeBegin||(p=f)),r(a,f),a.returnBegin?0:f.length;if(a=c(h,f)){e=h;e.skip?p+=f:(e.returnEnd||e.excludeEnd||(p+=f),w(),e.excludeEnd&&(p=f));do h.className&&(v+="</span>"),h.skip||(u+=h.relevance),h=h.parent;while(h!==a.parent);a.starts&&r(a.starts,"");return e.returnEnd?0:f.length}if(!b&&l(h.illegalRe,
+f))throw Error('Illegal lexeme "'+f+'" for mode "'+(h.className||"<unnamed>")+'"');p+=f;return f.length||1}var n=z(a);if(!n)throw Error('Unknown language: "'+a+'"');N(n);var h=e||n,m={},v="";for(e=h;e!==n;e=e.parent)e.className&&(v=d(e.className,"",!0)+v);var p="",u=0;try{for(var A,x,D=0;;){h.terminators.lastIndex=D;A=h.terminators.exec(f);if(!A)break;x=k(f.substring(D,A.index),A[0]);D=A.index+x}k(f.substr(D));for(e=h;e.parent;e=e.parent)e.className&&(v+="</span>");return{relevance:u,value:v,language:a,
+top:h}}catch(E){if(E.message&&-1!==E.message.indexOf("Illegal"))return{relevance:0,value:g(f)};throw E;}}function F(a,f){f=f||t.languages||x(y);var b={relevance:0,value:g(a)},e=b;f.filter(z).forEach(function(f){var c=C(f,a,!1);c.language=f;c.relevance>e.relevance&&(e=c);c.relevance>b.relevance&&(e=b,b=c)});e.language&&(b.second_best=e);return b}function I(a){return t.tabReplace||t.useBR?a.replace(O,function(a,b){return t.useBR&&"\n"===a?"<br>":t.tabReplace?b.replace(/\t/g,t.tabReplace):""}):a}function J(a){var b,
+d;a:{var e=a.className+" ";e+=a.parentNode?a.parentNode.className:"";if(d=P.exec(e))d=z(d[1])?d[1]:"no-highlight";else{e=e.split(/\s+/);d=0;for(b=e.length;d<b;d++){var c=e[d];if(K.test(c)||z(c)){d=c;break a}}d=void 0}}if(!K.test(d)){t.useBR?(c=document.createElementNS("http://www.w3.org/1999/xhtml","div"),c.innerHTML=a.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):c=a;b=c.textContent;e=d?C(d,b,!0):F(b);c=m(c);if(c.length){var q=document.createElementNS("http://www.w3.org/1999/xhtml","div");
+q.innerHTML=e.value;e.value=L(c,m(q),b)}e.value=I(e.value);a.innerHTML=e.value;b=a.className;d=d?G[d]:e.language;c=[b.trim()];b.match(/\bhljs\b/)||c.push("hljs");-1===b.indexOf(d)&&c.push(d);d=c.join(" ").trim();a.className=d;a.result={language:e.language,re:e.relevance};e.second_best&&(a.second_best={language:e.second_best.language,re:e.second_best.relevance})}}function u(){if(!u.called){u.called=!0;var a=document.querySelectorAll("pre code");H.forEach.call(a,J)}}function z(a){a=(a||"").toLowerCase();
+return y[a]||y[G[a]]}var H=[],x=Object.keys,y={},G={},K=/^(no-?highlight|plain|text)$/i,P=/\blang(?:uage)?-([\w-]+)\b/i,O=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,t={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};b.highlight=C;b.highlightAuto=F;b.fixMarkup=I;b.highlightBlock=J;b.configure=function(a){t=k(t,a)};b.initHighlighting=u;b.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",u,!1);addEventListener("load",u,!1)};b.registerLanguage=function(a,f){f=y[a]=f(b);f.aliases&&
+f.aliases.forEach(function(b){G[b]=a})};b.listLanguages=function(){return x(y)};b.getLanguage=z;b.inherit=k;b.IDENT_RE="[a-zA-Z]\\w*";b.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*";b.NUMBER_RE="\\b\\d+(\\.\\d+)?";b.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";b.BINARY_NUMBER_RE="\\b(0b[01]+)";b.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";b.BACKSLASH_ESCAPE=
+{begin:"\\\\[\\s\\S]",relevance:0};b.APOS_STRING_MODE={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[b.BACKSLASH_ESCAPE]};b.QUOTE_STRING_MODE={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[b.BACKSLASH_ESCAPE]};b.PHRASAL_WORDS_MODE={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/};b.COMMENT=function(a,f,d){a=b.inherit({className:"comment",begin:a,end:f,contains:[]},d||{});
+a.contains.push(b.PHRASAL_WORDS_MODE);a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|XXX):",relevance:0});return a};b.C_LINE_COMMENT_MODE=b.COMMENT("//","$");b.C_BLOCK_COMMENT_MODE=b.COMMENT("/\\*","\\*/");b.HASH_COMMENT_MODE=b.COMMENT("#","$");b.NUMBER_MODE={className:"number",begin:b.NUMBER_RE,relevance:0};b.C_NUMBER_MODE={className:"number",begin:b.C_NUMBER_RE,relevance:0};b.BINARY_NUMBER_MODE={className:"number",begin:b.BINARY_NUMBER_RE,relevance:0};b.CSS_NUMBER_MODE={className:"number",
+begin:b.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0};b.REGEXP_MODE={className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[b.BACKSLASH_ESCAPE,{begin:/\[/,end:/\]/,relevance:0,contains:[b.BACKSLASH_ESCAPE]}]};b.TITLE_MODE={className:"title",begin:b.IDENT_RE,relevance:0};b.UNDERSCORE_TITLE_MODE={className:"title",begin:b.UNDERSCORE_IDENT_RE,relevance:0};b.METHOD_GUARD={begin:"\\.\\s*"+b.UNDERSCORE_IDENT_RE,relevance:0};
+b.registerLanguage("bash",function(a){var b={className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{(.*?)}/}]},d={className:"string",begin:/"/,end:/"/,contains:[a.BACKSLASH_ESCAPE,b,{className:"variable",begin:/\$\(/,end:/\)/,contains:[a.BACKSLASH_ESCAPE]}]};return{aliases:["sh","zsh"],lexemes:/\b-?[a-z\._]+\b/,keywords:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",
+_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[{className:"meta",begin:/^#![^\n]+sh\s*$/,relevance:10},{className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0},a.HASH_COMMENT_MODE,d,{className:"string",begin:/'/,end:/'/},b]}});b.registerLanguage("clojure",function(a){var b={className:"number",begin:"[-+]?\\d+(\\.\\d+)?",relevance:0},d=a.inherit(a.QUOTE_STRING_MODE,{illegal:null}),e=a.COMMENT(";","$",{relevance:0}),
+c={className:"literal",begin:/\b(true|false|nil)\b/},q={begin:"[\\[\\{]",end:"[\\]\\}]"},g={className:"comment",begin:"\\^[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*"},r=a.COMMENT("\\^\\{","\\}"),k={className:"symbol",begin:"[:]{1,2}[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*"},n={begin:"\\(",end:"\\)"},h={endsWithParent:!0,relevance:0},l={keywords:{"builtin-name":"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},
+lexemes:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",className:"name",begin:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",starts:h},m=[n,d,g,r,e,k,q,b,c,{begin:"[a-zA-Z_\\-!.?+*=<>&#'][a-zA-Z_\\-!.?+*=<>&#'0-9/;:]*",relevance:0}];n.contains=[a.COMMENT("comment",""),l,h];h.contains=m;q.contains=m;r.contains=[q];return{aliases:["clj"],illegal:/\S/,contains:[n,d,g,r,e,k,q,b,c]}});b.registerLanguage("cpp",function(a){var b={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},d={className:"string",
+variants:[{begin:'(u8?|U)?L?"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:'(u8?|U)?R"',end:'"',contains:[a.BACKSLASH_ESCAPE]},{begin:"'\\\\?.",end:"'",illegal:"."}]},e={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},
+contains:[{begin:/\\\n/,relevance:0},a.inherit(d,{className:"meta-string"}),{className:"meta-string",begin:/<[^\n>]*>/,end:/$/,illegal:"\\n"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},q=a.IDENT_RE+"\\s*\\(",g={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",
 built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",
-literal:"true false nullptr NULL"},l=[c,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,g,b];return{aliases:"c cc h c++ h++ hpp".split(" "),keywords:k,illegal:"</",contains:l.concat([d,{begin:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",end:">",keywords:k,contains:["self",c]},{begin:a.IDENT_RE+"::",keywords:k},{variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",
-end:/;/}],keywords:k,contains:l.concat([{begin:/\(/,end:/\)/,keywords:k,contains:l.concat(["self"]),relevance:0}]),relevance:0},{className:"function",begin:"("+a.IDENT_RE+"[\\*&\\s]+)+"+f,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:k,illegal:/[^\w\s\*&]/,contains:[{begin:f,returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:k,relevance:0,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,b,g,c]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,
-d]}]),exports:{preprocessor:d,strings:b,keywords:k}}});b.registerLanguage("cs",function(a){var c={keyword:"abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async nameof ascending descending from get group into join let orderby partial select set value var where yield",
-literal:"null false true"},b={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},g=a.inherit(b,{illegal:/\n/}),d={className:"subst",begin:"{",end:"}",keywords:c},f=a.inherit(d,{illegal:/\n/}),k={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},a.BACKSLASH_ESCAPE,f]},l={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},d]},n=a.inherit(l,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},f]});d.contains=
-[l,k,b,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE];f.contains=[n,k,g,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,a.inherit(a.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];b={variants:[l,k,b,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]};g=a.IDENT_RE+"(<"+a.IDENT_RE+">)?(\\[\\])?";return{aliases:["csharp"],keywords:c,illegal:/::/,contains:[a.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:"</?",
-end:">"}]}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},b,a.C_NUMBER_MODE,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:]/,contains:[a.TITLE_MODE,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},
-{beginKeywords:"new return throw await",relevance:0},{className:"function",begin:"("+g+"\\s+)+"+a.IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:c,contains:[{begin:a.IDENT_RE+"\\s*\\(",returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:c,relevance:0,contains:[b,a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}]}});b.registerLanguage("css",function(a){return{case_insensitive:!0,
-illegal:/[=\/|'\$]/,contains:[a.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(font-face|page)",lexemes:"[a-z-]+",keywords:"font-face page"},{begin:"@",end:"[{;]",illegal:/:/,contains:[{className:"keyword",begin:/\w+/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,contains:[a.APOS_STRING_MODE,
-a.QUOTE_STRING_MODE,a.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[a.C_BLOCK_COMMENT_MODE,{begin:/[A-Z\_\.\-]+\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]}]},
-a.CSS_NUMBER_MODE,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,a.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]}]}]}});b.registerLanguage("d",function(a){var b=a.COMMENT("\\/\\+","\\+\\/",{contains:["self"],relevance:10});return{lexemes:a.UNDERSCORE_IDENT_RE,keywords:{keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",
+literal:"true false nullptr NULL"},k=[b,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,e,d];return{aliases:"c cc h c++ h++ hpp".split(" "),keywords:g,illegal:"</",contains:k.concat([c,{begin:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",end:">",keywords:g,contains:["self",b]},{begin:a.IDENT_RE+"::",keywords:g},{variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",
+end:/;/}],keywords:g,contains:k.concat([{begin:/\(/,end:/\)/,keywords:g,contains:k.concat(["self"]),relevance:0}]),relevance:0},{className:"function",begin:"("+a.IDENT_RE+"[\\*&\\s]+)+"+q,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&]/,contains:[{begin:q,returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,d,e,b]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,
+c]},{className:"class",beginKeywords:"class struct",end:/[{;:]/,contains:[{begin:/</,end:/>/,contains:["self"]},a.TITLE_MODE]}]),exports:{preprocessor:c,strings:d,keywords:g}}});b.registerLanguage("cs",function(a){var b={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",
+literal:"null false true"},d={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},e=a.inherit(d,{illegal:/\n/}),c={className:"subst",begin:"{",end:"}",keywords:b},g=a.inherit(c,{illegal:/\n/}),k={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},a.BACKSLASH_ESCAPE,g]},l={className:"string",begin:/\$@"/,end:'"',contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},c]},m=a.inherit(l,{illegal:/\n/,contains:[{begin:"{{"},{begin:"}}"},{begin:'""'},g]});c.contains=
+[l,k,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE];g.contains=[m,k,e,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,a.inherit(a.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];d={variants:[l,k,d,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]};e=a.IDENT_RE+"(<"+a.IDENT_RE+"(\\s*,\\s*"+a.IDENT_RE+")*>)?(\\[\\])?";return{aliases:["csharp"],keywords:b,illegal:/::/,contains:[a.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},
+{begin:"\x3c!--|--\x3e"},{begin:"</?",end:">"}]}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},d,a.C_NUMBER_MODE,{beginKeywords:"class interface",end:/[{;=]/,illegal:/[^\s:]/,contains:[a.TITLE_MODE,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",end:/[{;=]/,illegal:/[^\s:]/,contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),
+a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"meta-string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+e+"\\s+)+"+a.IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:b,contains:[{begin:a.IDENT_RE+"\\s*\\(",returnBegin:!0,contains:[a.TITLE_MODE],relevance:0},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,
+keywords:b,relevance:0,contains:[d,a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}]}});b.registerLanguage("css",function(a){return{case_insensitive:!0,illegal:/[=\/|'\$]/,contains:[a.C_BLOCK_COMMENT_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:/\.[A-Za-z0-9_-]+/},{className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$"},{className:"selector-pseudo",begin:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{begin:"@(font-face|page)",
+lexemes:"[a-z-]+",keywords:"font-face page"},{begin:"@",end:"[{;]",illegal:/:/,contains:[{className:"keyword",begin:/\w+/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},{begin:"{",end:"}",illegal:/\S/,contains:[a.C_BLOCK_COMMENT_MODE,{begin:/[A-Z\_\.\-]+\s*:/,returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute",begin:/\S/,end:":",
+excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0,contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in",begin:/[\w-]+/},{begin:/\(/,end:/\)/,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]}]},a.CSS_NUMBER_MODE,a.QUOTE_STRING_MODE,a.APOS_STRING_MODE,a.C_BLOCK_COMMENT_MODE,{className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}]}}]}]}]}});b.registerLanguage("d",function(a){var b=a.COMMENT("\\/\\+","\\+\\/",{contains:["self"],relevance:10});return{lexemes:a.UNDERSCORE_IDENT_RE,
+keywords:{keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",
 built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"},contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,b,{className:"string",begin:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',relevance:10},{className:"string",begin:'"',contains:[{begin:"\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};",relevance:0}],
 end:'"[cwd]?'},{className:"string",begin:'[rq]"',end:'"[cwd]?',relevance:5},{className:"string",begin:"`",end:"`[cwd]?"},{className:"string",begin:'q"\\{',end:'\\}"'},{className:"number",begin:"\\b(((0[xX](([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)\\.([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)|\\.?([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))[pP][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))|((0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(\\.\\d*|([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)))|\\d+\\.(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)|\\.(0|[1-9][\\d_]*)([eE][+-]?(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d))?))([fF]|L|i|[fF]i|Li)?|((0|[1-9][\\d_]*)|0[bB][01_]+|0[xX]([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))(i|[fF]i|Li))",
 relevance:0},{className:"number",begin:"\\b((0|[1-9][\\d_]*)|0[bB][01_]+|0[xX]([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*))(L|u|U|Lu|LU|uL|UL)?",relevance:0},{className:"string",begin:"'(\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};|.)",end:"'",illegal:"."},{className:"meta",begin:"^#!",end:"$",relevance:5},{className:"meta",begin:"#(line)",end:"$",relevance:5},{className:"keyword",begin:"@[a-zA-Z_][a-zA-Z_\\d]*"}]}});b.registerLanguage("markdown",
 function(a){return{aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$"},{begin:"^.+?\\n[=-]{2,}$"}]},{begin:"<",end:">",subLanguage:"xml",relevance:0},{className:"bullet",begin:"^([*+-]|(\\d+\\.))\\s+"},{className:"strong",begin:"[*_]{2}.+?[*_]{2}"},{className:"emphasis",variants:[{begin:"\\*.+?\\*"},{begin:"_.+?_",relevance:0}]},{className:"quote",begin:"^>\\s+",end:"$"},{className:"code",variants:[{begin:"^```w*s*$",end:"^```s*$"},{begin:"`.+?`"},{begin:"^( {4}|\t)",
 end:"$",relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},{begin:"\\[.+?\\][\\(\\[].*?[\\)\\]]",returnBegin:!0,contains:[{className:"string",begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0,relevance:0},{className:"link",begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}],relevance:10},{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",
-begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}});b.registerLanguage("dart",function(a){var b={className:"subst",begin:"\\$\\{",end:"}",keywords:"true false null this is new super"},e={className:"string",variants:[{begin:"r'''",end:"'''"},{begin:'r"""',end:'"""'},{begin:"r'",end:"'",illegal:"\\n"},{begin:'r"',end:'"',illegal:"\\n"},{begin:"'''",end:"'''",contains:[a.BACKSLASH_ESCAPE,b]},{begin:'"""',end:'"""',contains:[a.BACKSLASH_ESCAPE,b]},{begin:"'",end:"'",illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,
-b]},{begin:'"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b]}]};b.contains=[a.C_NUMBER_MODE,e];return{keywords:{keyword:"assert async await break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch sync this throw true try var void while with yield abstract as dynamic export external factory get implements import library operator part set static typedef",built_in:"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList"},
-contains:[e,a.COMMENT("/\\*\\*","\\*/",{subLanguage:"markdown"}),a.COMMENT("///","$",{subLanguage:"markdown"}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"},{begin:"=>"}]}});b.registerLanguage("go",function(a){var b={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",
+begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}});b.registerLanguage("dart",function(a){var b={className:"subst",begin:"\\$\\{",end:"}",keywords:"true false null this is new super"},d={className:"string",variants:[{begin:"r'''",end:"'''"},{begin:'r"""',end:'"""'},{begin:"r'",end:"'",illegal:"\\n"},{begin:'r"',end:'"',illegal:"\\n"},{begin:"'''",end:"'''",contains:[a.BACKSLASH_ESCAPE,b]},{begin:'"""',end:'"""',contains:[a.BACKSLASH_ESCAPE,b]},{begin:"'",end:"'",illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,
+b]},{begin:'"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b]}]};b.contains=[a.C_NUMBER_MODE,d];return{keywords:{keyword:"assert async await break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch sync this throw true try var void while with yield abstract as dynamic export external factory get implements import library operator part set static typedef",built_in:"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList"},
+contains:[d,a.COMMENT("/\\*\\*","\\*/",{subLanguage:"markdown"}),a.COMMENT("///","$",{subLanguage:"markdown"}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"},{begin:"=>"}]}});b.registerLanguage("xml",function(a){var b={endsWithParent:!0,illegal:/</,relevance:0,contains:[{className:"attr",begin:"[A-Za-z0-9\\._:-]+",
+relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/[^\s"'=<>`]+/}]}]}]};return{aliases:"html xhtml rss atom xjb xsd xsl plist".split(" "),case_insensitive:!0,contains:[{className:"meta",begin:"<!DOCTYPE",end:">",relevance:10,contains:[{begin:"\\[",end:"\\]"}]},a.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",
+end:"\\*/",skip:!0}]},{className:"tag",begin:"<style(?=\\s|>|$)",end:">",keywords:{name:"style"},contains:[b],starts:{end:"</style>",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:"<script(?=\\s|>|$)",end:">",keywords:{name:"script"},contains:[b],starts:{end:"\x3c/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"meta",variants:[{begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?\w+/,end:/\?>/}]},{className:"tag",begin:"</?",end:"/?>",
+contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},b]}]}});b.registerLanguage("ruby",function(a){var b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},d={className:"doctag",begin:"@[A-Za-z]+"},e={begin:"#<",end:">"};d=[a.COMMENT("#","$",{contains:[d]}),a.COMMENT("^\\=begin",
+"^\\=end",{contains:[d],relevance:10}),a.COMMENT("^__END__","\\n$")];var c={className:"subst",begin:"#\\{",end:"}",keywords:b},g={className:"string",contains:[a.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},
+{begin:/<<(-?)\w+$/,end:/^\s*\w+$/}]},k={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:b};a=[g,e,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE}]}].concat(d)},{className:"function",beginKeywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}),
+k].concat(d)},{begin:a.IDENT_RE+"::"},{className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[g,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:b},{begin:"("+a.RE_STARTERS_RE+
+"|unless)\\s*",keywords:"unless",contains:[e,{className:"regexp",contains:[a.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(d),relevance:0}].concat(d);c.contains=a;k.contains=a;return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:b,illegal:/\/\*/,contains:d.concat([{begin:/^\s*=>/,starts:{end:"$",contains:a}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",
+starts:{end:"$",contains:a}}]).concat(a)}});b.registerLanguage("erb",function(a){return{subLanguage:"xml",contains:[a.COMMENT("<%#","%>"),{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0}]}});b.registerLanguage("go",function(a){var b={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",
 literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],keywords:b,illegal:"</",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",variants:[a.QUOTE_STRING_MODE,{begin:"'",end:"[^\\\\]'"},{begin:"`",end:"`"}]},{className:"number",variants:[{begin:a.C_NUMBER_RE+"[dflsi]",relevance:1},a.C_NUMBER_MODE]},{begin:/:=/},{className:"function",beginKeywords:"func",end:/\s*\{/,excludeEnd:!0,
-contains:[a.TITLE_MODE,{className:"params",begin:/\(/,end:/\)/,keywords:b,illegal:/["']/}]}]}});b.registerLanguage("haskell",function(a){var b={variants:[a.COMMENT("--","$"),a.COMMENT("{-","-}",{contains:["self"]})]},e={className:"meta",begin:"{-#",end:"#-}"},g={className:"meta",begin:"^#",end:"$"},d={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},f={begin:"\\(",end:"\\)",illegal:'"',contains:[e,g,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},a.inherit(a.TITLE_MODE,{begin:"[_a-z][\\w']*"}),
-b]};return{aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[f,b],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[f,b],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",
-end:"where",keywords:"class family instance where",contains:[d,f,b]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[e,d,f,{begin:"{",end:"}",contains:f.contains},b]},{beginKeywords:"default",end:"$",contains:[d,f,b]},{beginKeywords:"infix infixl infixr",end:"$",contains:[a.C_NUMBER_MODE,b]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[d,a.QUOTE_STRING_MODE,
-b]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},e,g,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,d,a.inherit(a.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),b,{begin:"->|<-"}]}});b.registerLanguage("java",function(a){var b=a.UNDERSCORE_IDENT_RE+"(<"+a.UNDERSCORE_IDENT_RE+"(\\s*,\\s*"+a.UNDERSCORE_IDENT_RE+")*>)?";return{aliases:["jsp"],keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",
-illegal:/<\/|#/,contains:[a.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"function",begin:"("+
-b+"\\s+)+"+a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",contains:[{begin:a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,
-relevance:0,contains:[a.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",relevance:0,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,
-a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{className:"number",begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",relevance:0},{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("javascript",function(a){return{aliases:["js","jsx"],keywords:{keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",
+contains:[a.TITLE_MODE,{className:"params",begin:/\(/,end:/\)/,keywords:b,illegal:/["']/}]}]}});b.registerLanguage("haskell",function(a){var b={variants:[a.COMMENT("--","$"),a.COMMENT("{-","-}",{contains:["self"]})]},d={className:"meta",begin:"{-#",end:"#-}"},e={className:"meta",begin:"^#",end:"$"},c={className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},g={begin:"\\(",end:"\\)",illegal:'"',contains:[d,e,{className:"type",begin:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},a.inherit(a.TITLE_MODE,{begin:"[_a-z][\\w']*"}),
+b]};return{aliases:["hs"],keywords:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",contains:[{beginKeywords:"module",end:"where",keywords:"module where",contains:[g,b],illegal:"\\W\\.|;"},{begin:"\\bimport\\b",end:"$",keywords:"import qualified as hiding",contains:[g,b],illegal:"\\W\\.|;"},{className:"class",begin:"^(\\s*)?(class|instance)\\b",
+end:"where",keywords:"class family instance where",contains:[c,g,b]},{className:"class",begin:"\\b(data|(new)?type)\\b",end:"$",keywords:"data family type newtype deriving",contains:[d,c,g,{begin:"{",end:"}",contains:g.contains},b]},{beginKeywords:"default",end:"$",contains:[c,g,b]},{beginKeywords:"infix infixl infixr",end:"$",contains:[a.C_NUMBER_MODE,b]},{begin:"\\bforeign\\b",end:"$",keywords:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",contains:[c,a.QUOTE_STRING_MODE,
+b]},{className:"meta",begin:"#!\\/usr\\/bin\\/env runhaskell",end:"$"},d,e,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,c,a.inherit(a.TITLE_MODE,{begin:"^[_a-z][\\w']*"}),b,{begin:"->|<-"}]}});b.registerLanguage("java",function(a){return{aliases:["jsp"],keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",
+illegal:/<\/|#/,contains:[a.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"class",beginKeywords:"class interface",end:/[{;=]/,excludeEnd:!0,keywords:"class interface",illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"new throw return else",relevance:0},{className:"function",begin:"([\u00c0-\u02b8a-zA-Z_$][\u00c0-\u02b8a-zA-Z_$0-9]*(<[\u00c0-\u02b8a-zA-Z_$][\u00c0-\u02b8a-zA-Z_$0-9]*(\\s*,\\s*[\u00c0-\u02b8a-zA-Z_$][\u00c0-\u02b8a-zA-Z_$0-9]*)*>)?\\s+)+"+
+a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",contains:[{begin:a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,
+contains:[a.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/,keywords:"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",relevance:0,contains:[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,a.C_NUMBER_MODE,
+a.C_BLOCK_COMMENT_MODE]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]},{className:"number",begin:"\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",relevance:0},{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("javascript",function(a){var b={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",
 literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},
-contains:[{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},{className:"meta",begin:/^#!/,end:/$/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"`",end:"`",contains:[a.BACKSLASH_ESCAPE,{className:"subst",begin:"\\$\\{",end:"\\}"}]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:a.C_NUMBER_RE}],relevance:0},{begin:"("+a.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",
-contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.REGEXP_MODE,{begin:/</,end:/(\/\w+|\w+\/)>/,subLanguage:"xml",contains:[{begin:/<\w+\s*\/>/,skip:!0},{begin:/<\w+/,end:/(\/\w+|\w+\/)>/,skip:!0,contains:["self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}],
-illegal:/\[|%/},{begin:/\$[(.]/},a.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0}],illegal:/#(?!!)/}});b.registerLanguage("json",function(a){var b={literal:"true false null"},e=[a.QUOTE_STRING_MODE,a.C_NUMBER_MODE],g={end:",",endsWithParent:!0,excludeEnd:!0,contains:e,keywords:b},d={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,
-end:/"/,contains:[a.BACKSLASH_ESCAPE],illegal:"\\n"},a.inherit(g,{begin:/:/})],illegal:"\\S"};a={begin:"\\[",end:"\\]",contains:[a.inherit(g)],illegal:"\\S"};e.splice(e.length,0,d,a);return{contains:e,keywords:b,illegal:"\\S"}});b.registerLanguage("lisp",function(a){var b={className:"literal",begin:"\\b(t{1}|nil)\\b"},e={className:"number",variants:[{begin:"(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?",relevance:0},{begin:"#(b|B)[0-1]+(/[0-1]+)?"},{begin:"#(o|O)[0-7]+(/[0-7]+)?"},
-{begin:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},{begin:"#(c|C)\\((\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)? +(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?",end:"\\)"}]},g=a.inherit(a.QUOTE_STRING_MODE,{illegal:null});a=a.COMMENT(";","$",{relevance:0});var d={begin:"\\*",end:"\\*"},f={className:"symbol",begin:"[:&][a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},k={begin:"[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*",
-relevance:0},l={contains:[e,g,d,f,{begin:"\\(",end:"\\)",contains:["self",b,g,e,k]},k],variants:[{begin:"['`]\\(",end:"\\)"},{begin:"\\(quote ",end:"\\)",keywords:{name:"quote"}},{begin:"'\\|[^]*?\\|"}]},n={variants:[{begin:"'[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},{begin:"#'[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*(::[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*)*"}]},m={begin:"\\(\\s*",end:"\\)"},
-h={endsWithParent:!0,relevance:0};m.contains=[{className:"name",variants:[{begin:"[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},{begin:"\\|[^]*?\\|"}]},h];h.contains=[l,n,m,b,e,g,a,d,f,{begin:"\\|[^]*?\\|"},k];return{illegal:/\S/,contains:[e,{className:"meta",begin:"^#!",end:"$"},b,g,a,l,n,m,k]}});b.registerLanguage("lua",function(a){var b={begin:"\\[=*\\[",end:"\\]=*\\]",contains:["self"]},e=[a.COMMENT("--(?!\\[=*\\[)","$"),a.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[b],
-relevance:10})];return{lexemes:a.UNDERSCORE_IDENT_RE,keywords:{keyword:"and break do else elseif end false for if in local nil not or repeat return then true until while",built_in:"_G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall coroutine debug io math os package string table"},contains:e.concat([{className:"function",beginKeywords:"function",
-end:"\\)",contains:[a.inherit(a.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:e}].concat(e)},a.C_NUMBER_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[b],relevance:5}])}});b.registerLanguage("xml",function(a){var b={endsWithParent:!0,illegal:/</,relevance:0,contains:[{className:"attr",begin:"[A-Za-z0-9\\._:-]+",relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",
-endsParent:!0,variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/},{begin:/[^\s"'=<>`]+/}]}]}]};return{aliases:"html xhtml rss atom xjb xsd xsl plist".split(" "),case_insensitive:!0,contains:[{className:"meta",begin:"<!DOCTYPE",end:">",relevance:10,contains:[{begin:"\\[",end:"\\]"}]},a.COMMENT("\x3c!--","--\x3e",{relevance:10}),{begin:"<\\!\\[CDATA\\[",end:"\\]\\]>",relevance:10},{begin:/<\?(php)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0}]},{className:"tag",begin:"<style(?=\\s|>|$)",
-end:">",keywords:{name:"style"},contains:[b],starts:{end:"</style>",returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:"<script(?=\\s|>|$)",end:">",keywords:{name:"script"},contains:[b],starts:{end:"\x3c/script>",returnEnd:!0,subLanguage:["actionscript","javascript","handlebars","xml"]}},{className:"meta",variants:[{begin:/<\?xml/,end:/\?>/,relevance:10},{begin:/<\?\w+/,end:/\?>/}]},{className:"tag",begin:"</?",end:"/?>",contains:[{className:"name",begin:/[^\/><\s]+/,relevance:0},b]}]}});
-b.registerLanguage("objectivec",function(a){var b=/[a-zA-Z@][a-zA-Z0-9_]*/;return{aliases:["mm","objc","obj-c"],keywords:{keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",
+d={className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:a.C_NUMBER_RE}],relevance:0},e={className:"subst",begin:"\\$\\{",end:"\\}",keywords:b,contains:[]},c={className:"string",begin:"`",end:"`",contains:[a.BACKSLASH_ESCAPE,e]};e.contains=[a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,c,d,a.REGEXP_MODE];e=e.contains.concat([a.C_BLOCK_COMMENT_MODE,a.C_LINE_COMMENT_MODE]);return{aliases:["js","jsx"],keywords:b,contains:[{className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},
+{className:"meta",begin:/^#!/,end:/$/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,c,a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,d,{begin:/[{,]\s*/,relevance:0,contains:[{begin:"[A-Za-z$_][0-9A-Za-z$_]*\\s*:",returnBegin:!0,relevance:0,contains:[{className:"attr",begin:"[A-Za-z$_][0-9A-Za-z$_]*",relevance:0}]}]},{begin:"("+a.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|[A-Za-z$_][0-9A-Za-z$_]*)\\s*=>",
+returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:"[A-Za-z$_][0-9A-Za-z$_]*"},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,contains:e}]}]},{begin:/</,end:/(\/\w+|\w+\/)>/,subLanguage:"xml",contains:[{begin:/<\w+\s*\/>/,skip:!0},{begin:/<\w+/,end:/(\/\w+|\w+\/)>/,skip:!0,contains:[{begin:/<\w+\s*\/>/,skip:!0},"self"]}]}],relevance:0},{className:"function",beginKeywords:"function",end:/\{/,excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z$_][0-9A-Za-z$_]*"}),
+{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,contains:e}],illegal:/\[|%/},{begin:/\$[(.]/},a.METHOD_GUARD,{className:"class",beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"extends"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0}],illegal:/#(?!!)/}});b.registerLanguage("json",function(a){var b={literal:"true false null"},d=[a.QUOTE_STRING_MODE,a.C_NUMBER_MODE],e={end:",",endsWithParent:!0,excludeEnd:!0,
+contains:d,keywords:b},c={begin:"{",end:"}",contains:[{className:"attr",begin:/"/,end:/"/,contains:[a.BACKSLASH_ESCAPE],illegal:"\\n"},a.inherit(e,{begin:/:/})],illegal:"\\S"};a={begin:"\\[",end:"\\]",contains:[a.inherit(e)],illegal:"\\S"};d.splice(d.length,0,c,a);return{contains:d,keywords:b,illegal:"\\S"}});b.registerLanguage("kotlin",function(a){var b={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit initinterface annotation data sealed internal infix operator out by constructor super trait volatile transient native default",
+built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},d={className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"@"},e={className:"subst",begin:"\\${",end:"}",contains:[a.APOS_STRING_MODE,a.C_NUMBER_MODE]},c={className:"variable",begin:"\\$"+a.UNDERSCORE_IDENT_RE};e={className:"string",variants:[{begin:'"""',end:'"""',contains:[c,e]},{begin:"'",end:"'",illegal:/\n/,contains:[a.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[a.BACKSLASH_ESCAPE,c,
+e]}]};c={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+a.UNDERSCORE_IDENT_RE+")?"};var g={className:"meta",begin:"@"+a.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[a.inherit(e,{className:"meta-string"})]}]};return{keywords:b,contains:[a.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"keyword",begin:/\b(break|continue|return|this)\b/,
+starts:{contains:[{className:"symbol",begin:/@\w+/}]}},d,c,g,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:b,illegal:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,relevance:5,contains:[{begin:a.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[a.UNDERSCORE_TITLE_MODE]},{className:"type",begin:/</,end:/>/,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:b,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,
+endsWithParent:!0,contains:[{className:"type",begin:a.UNDERSCORE_IDENT_RE},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE],relevance:0},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,c,g,e,a.C_NUMBER_MODE]},a.C_BLOCK_COMMENT_MODE]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},a.UNDERSCORE_TITLE_MODE,{className:"type",begin:/</,end:/>/,excludeBegin:!0,excludeEnd:!0,
+relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},c,g]},e,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},a.C_NUMBER_MODE]}});b.registerLanguage("lisp",function(a){var b={className:"literal",begin:"\\b(t{1}|nil)\\b"},d={className:"number",variants:[{begin:"(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?",relevance:0},{begin:"#(b|B)[0-1]+(/[0-1]+)?"},{begin:"#(o|O)[0-7]+(/[0-7]+)?"},{begin:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},
+{begin:"#(c|C)\\((\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)? +(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?",end:"\\)"}]},e=a.inherit(a.QUOTE_STRING_MODE,{illegal:null});a=a.COMMENT(";","$",{relevance:0});var c={begin:"\\*",end:"\\*"},g={className:"symbol",begin:"[:&][a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},k={begin:"[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*",relevance:0},
+l={contains:[d,e,c,g,{begin:"\\(",end:"\\)",contains:["self",b,e,d,k]},k],variants:[{begin:"['`]\\(",end:"\\)"},{begin:"\\(quote ",end:"\\)",keywords:{name:"quote"}},{begin:"'\\|[^]*?\\|"}]},m={variants:[{begin:"'[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},{begin:"#'[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*(::[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*)*"}]},n={begin:"\\(\\s*",end:"\\)"},h={endsWithParent:!0,
+relevance:0};n.contains=[{className:"name",variants:[{begin:"[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*"},{begin:"\\|[^]*?\\|"}]},h];h.contains=[l,m,n,b,d,e,a,c,g,{begin:"\\|[^]*?\\|"},k];return{illegal:/\S/,contains:[d,{className:"meta",begin:"^#!",end:"$"},b,e,a,l,m,n,k]}});b.registerLanguage("lua",function(a){var b={begin:"\\[=*\\[",end:"\\]=*\\]",contains:["self"]},d=[a.COMMENT("--(?!\\[=*\\[)","$"),a.COMMENT("--\\[=*\\[","\\]=*\\]",{contains:[b],relevance:10})];
+return{lexemes:a.UNDERSCORE_IDENT_RE,keywords:{literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstringmodule next pairs pcall print rawequal rawget rawset require select setfenvsetmetatable tonumber tostring type unpack xpcall arg selfcoroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},
+contains:d.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[a.inherit(a.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:d}].concat(d)},a.C_NUMBER_MODE,a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"\\[=*\\[",end:"\\]=*\\]",contains:[b],relevance:5}])}});b.registerLanguage("objectivec",function(a){var b=/[a-zA-Z@][a-zA-Z0-9_]*/;return{aliases:["mm","objc","obj-c"],keywords:{keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",
 literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},lexemes:b,illegal:"</",contains:[{className:"built_in",begin:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.C_NUMBER_MODE,a.QUOTE_STRING_MODE,{className:"string",variants:[{begin:'@"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:"'",end:"[^\\\\]'",illegal:"[^\\\\][^']"}]},
 {className:"meta",begin:"#",end:"$",contains:[{className:"meta-string",variants:[{begin:'"',end:'"'},{begin:"<",end:">"}]}]},{className:"class",begin:"(@interface|@class|@protocol|@implementation)\\b",end:"({|$)",excludeEnd:!0,keywords:"@interface @class @protocol @implementation",lexemes:b,contains:[a.UNDERSCORE_TITLE_MODE]},{begin:"\\."+a.UNDERSCORE_IDENT_RE,relevance:0}]}});b.registerLanguage("ocaml",function(a){return{aliases:["ml"],keywords:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",
 built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",literal:"true false"},illegal:/\/\/|>>/,lexemes:"[a-z_]\\w*!?",contains:[{className:"literal",begin:"\\[(\\|\\|)?\\]|\\(\\)",relevance:0},a.COMMENT("\\(\\*","\\*\\)",{contains:["self"]}),{className:"symbol",begin:"'[A-Za-z_](?!')[\\w']*"},{className:"type",begin:"`[A-Z][\\w']*"},{className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},{begin:"[a-z_]\\w*'[\\w']*",relevance:0},
 a.inherit(a.APOS_STRING_MODE,{className:"string",relevance:0}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null}),{className:"number",begin:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",relevance:0},{begin:/[-=]>/}]}});b.registerLanguage("perl",function(a){var b={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when"},
-e={begin:"->{",end:"}"},g={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},d=[a.BACKSLASH_ESCAPE,b,g];a=[g,a.HASH_COMMENT_MODE,a.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),e,{className:"string",contains:d,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",
+d={begin:"->{",end:"}"},e={variants:[{begin:/\$\d/},{begin:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{begin:/[\$%@][^\s\w{]/,relevance:0}]},c=[a.BACKSLASH_ESCAPE,b,e];a=[e,a.HASH_COMMENT_MODE,a.COMMENT("^\\=\\w","\\=cut",{endsWithParent:!0}),d,{className:"string",contains:c,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*\\<",
 end:"\\>",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[a.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[a.BACKSLASH_ESCAPE]},{begin:"{\\w+}",contains:[],relevance:0},{begin:"-?\\w+\\s*\\=\\>",contains:[],relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+a.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",
 relevance:0,contains:[a.HASH_COMMENT_MODE,{className:"regexp",begin:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",relevance:10},{className:"regexp",begin:"(m|qr)?/",end:"/[a-z]*",contains:[a.BACKSLASH_ESCAPE],relevance:0}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[a.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];b.contains=
-a;e.contains=a;return{aliases:["pl","pm"],lexemes:/[\w\.]+/,keywords:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",
-contains:a}});b.registerLanguage("php",function(a){var b={begin:"\\$+[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*"},e={className:"meta",begin:/<\?(php)?|\?>/},g={className:"string",contains:[a.BACKSLASH_ESCAPE,e],variants:[{begin:'b"',end:'"'},{begin:"b'",end:"'"},a.inherit(a.APOS_STRING_MODE,{illegal:null}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null})]},d={variants:[a.BINARY_NUMBER_MODE,a.C_NUMBER_MODE]};return{aliases:["php3","php4","php5","php6"],case_insensitive:!0,keywords:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",
-contains:[a.HASH_COMMENT_MODE,a.COMMENT("//","$",{contains:[e]}),a.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),a.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,keywords:"__halt_compiler",lexemes:a.UNDERSCORE_IDENT_RE}),{className:"string",begin:/<<<['"]?\w+['"]?$/,end:/^\w+;?$/,contains:[a.BACKSLASH_ESCAPE,{className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]}]},e,{className:"keyword",begin:/\$this\b/},b,{begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},
-{className:"function",beginKeywords:"function",end:/[;{]/,excludeEnd:!0,illegal:"\\$|\\[|%",contains:[a.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",contains:["self",b,a.C_BLOCK_COMMENT_MODE,g,d]}]},{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",end:";",illegal:/[\.']/,contains:[a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",contains:[a.UNDERSCORE_TITLE_MODE]},
-{begin:"=>"},g,d]}});b.registerLanguage("protobuf",function(a){return{keywords:{keyword:"package import option optional required repeated group",built_in:"double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes",literal:"true false"},contains:[a.QUOTE_STRING_MODE,a.NUMBER_MODE,a.C_LINE_COMMENT_MODE,{className:"class",beginKeywords:"message enum service",end:/\{/,illegal:/\n/,contains:[a.inherit(a.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]},
-{className:"function",beginKeywords:"rpc",end:/;/,excludeEnd:!0,keywords:"rpc returns"},{begin:/^\s*[A-Z_]+/,end:/\s*=/,excludeEnd:!0}]}});b.registerLanguage("python",function(a){var b={className:"meta",begin:/^(>>>|\.\.\.) /},e={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[b],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[b],relevance:10},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},{begin:/(b|br)'/,
-end:/'/},{begin:/(b|br)"/,end:/"/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]},g={className:"number",relevance:0,variants:[{begin:a.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:a.C_NUMBER_RE+"[lLjJ]?"}]};return{aliases:["py","gyp"],keywords:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},
-illegal:/(<\/|->|\?)/,contains:[b,g,e,a.HASH_COMMENT_MODE,{variants:[{className:"function",beginKeywords:"def",relevance:10},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[a.UNDERSCORE_TITLE_MODE,{className:"params",begin:/\(/,end:/\)/,contains:["self",b,g,e]},{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}});b.registerLanguage("ruby",function(a){var b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",
-literal:"true false nil"},e={className:"doctag",begin:"@[A-Za-z]+"},g={begin:"#<",end:">"},e=[a.COMMENT("#","$",{contains:[e]}),a.COMMENT("^\\=begin","^\\=end",{contains:[e],relevance:10}),a.COMMENT("^__END__","\\n$")],d={className:"subst",begin:"#\\{",end:"}",keywords:b},f={className:"string",contains:[a.BACKSLASH_ESCAPE,d],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:"%[qQwWx]?\\(",end:"\\)"},{begin:"%[qQwWx]?\\[",end:"\\]"},{begin:"%[qQwWx]?{",end:"}"},{begin:"%[qQwWx]?<",
-end:">"},{begin:"%[qQwWx]?/",end:"/"},{begin:"%[qQwWx]?%",end:"%"},{begin:"%[qQwWx]?-",end:"-"},{begin:"%[qQwWx]?\\|",end:"\\|"},{begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]},k={className:"params",begin:"\\(",end:"\\)",endsParent:!0,keywords:b};a=[f,g,{className:"class",beginKeywords:"class module",end:"$|;",illegal:/=/,contains:[a.inherit(a.TITLE_MODE,{begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{begin:"<\\s*",contains:[{begin:"("+a.IDENT_RE+"::)?"+a.IDENT_RE}]}].concat(e)},
-{className:"function",beginKeywords:"def",end:"$|;",contains:[a.inherit(a.TITLE_MODE,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}),k].concat(e)},{begin:a.IDENT_RE+"::"},{className:"symbol",begin:a.UNDERSCORE_IDENT_RE+"(\\!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[f,{begin:"[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?"}],relevance:0},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",
-relevance:0},{begin:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{className:"params",begin:/\|/,end:/\|/,keywords:b},{begin:"("+a.RE_STARTERS_RE+")\\s*",contains:[g,{className:"regexp",contains:[a.BACKSLASH_ESCAPE,d],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:"%r{",end:"}[a-z]*"},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(e),relevance:0}].concat(e);d.contains=a;k.contains=a;return{aliases:["rb","gemspec","podspec","thor","irb"],keywords:b,
-illegal:/\/\*/,contains:e.concat([{begin:/^\s*=>/,starts:{end:"$",contains:a}},{className:"meta",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>)",starts:{end:"$",contains:a}}]).concat(a)}});b.registerLanguage("rust",function(a){var b=a.inherit(a.C_BLOCK_COMMENT_MODE);b.contains.push("self");return{aliases:["rs"],keywords:{keyword:"alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield move default int i8 i16 i32 i64 isize uint u8 u32 u64 usize float f32 f64 str char bool",
-literal:"true false Some None Ok Err",built_in:"Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option Result SliceConcatExt String ToString Vec assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules!"},
-lexemes:a.IDENT_RE+"!?",illegal:"</",contains:[a.C_LINE_COMMENT_MODE,b,a.inherit(a.QUOTE_STRING_MODE,{begin:/b?"/,illegal:null}),{className:"string",variants:[{begin:/r(#*)".*?"\1(?!#)/},{begin:/b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/}]},{className:"symbol",begin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:"number",variants:[{begin:"\\b0b([01_]+)([uif](8|16|32|64|size))?"},{begin:"\\b0o([0-7_]+)([uif](8|16|32|64|size))?"},{begin:"\\b0x([A-Fa-f0-9_]+)([uif](8|16|32|64|size))?"},{begin:"\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)([uif](8|16|32|64|size))?"}],
-relevance:0},{className:"function",beginKeywords:"fn",end:"(\\(|<)",excludeEnd:!0,contains:[a.UNDERSCORE_TITLE_MODE]},{className:"meta",begin:"#\\!?\\[",end:"\\]",contains:[{className:"meta-string",begin:/"/,end:/"/}]},{className:"class",beginKeywords:"type",end:";",contains:[a.inherit(a.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"\\S"},{className:"class",beginKeywords:"trait enum struct",end:"{",contains:[a.inherit(a.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"[\\w\\d]"},{begin:a.IDENT_RE+
-"::",keywords:{built_in:"Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option Result SliceConcatExt String ToString Vec assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules!"}},
-{begin:"->"}]}});b.registerLanguage("scala",function(a){var b={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:"\\${",end:"}"}]},e={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},g={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0};return{keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},
-contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",variants:[{begin:'"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:'"""',end:'"""',relevance:10},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[b],relevance:10}]},{className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},e,{className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[g]},{className:"class",beginKeywords:"class object trait type",
-end:/[:={\[\n;]/,excludeEnd:!0,contains:[{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[e]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[e]},g]},a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("sql",function(a){var b=a.COMMENT("--","$");return{case_insensitive:!0,illegal:/[<>{}*#]/,contains:[{beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke",
-end:/;/,endsWithParent:!0,lexemes:/[\w\.]+/,keywords:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",
+a;d.contains=a;return{aliases:["pl","pm"],lexemes:/[\w\.]+/,keywords:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",
+contains:a}});b.registerLanguage("php",function(a){var b={begin:"\\$+[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*"},d={className:"meta",begin:/<\?(php)?|\?>/},e={className:"string",contains:[a.BACKSLASH_ESCAPE,d],variants:[{begin:'b"',end:'"'},{begin:"b'",end:"'"},a.inherit(a.APOS_STRING_MODE,{illegal:null}),a.inherit(a.QUOTE_STRING_MODE,{illegal:null})]},c={variants:[a.BINARY_NUMBER_MODE,a.C_NUMBER_MODE]};return{aliases:["php3","php4","php5","php6"],case_insensitive:!0,keywords:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",
+contains:[a.HASH_COMMENT_MODE,a.COMMENT("//","$",{contains:[d]}),a.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),a.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0,keywords:"__halt_compiler",lexemes:a.UNDERSCORE_IDENT_RE}),{className:"string",begin:/<<<['"]?\w+['"]?$/,end:/^\w+;?$/,contains:[a.BACKSLASH_ESCAPE,{className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]}]},d,{className:"keyword",begin:/\$this\b/},b,{begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},
+{className:"function",beginKeywords:"function",end:/[;{]/,excludeEnd:!0,illegal:"\\$|\\[|%",contains:[a.UNDERSCORE_TITLE_MODE,{className:"params",begin:"\\(",end:"\\)",contains:["self",b,a.C_BLOCK_COMMENT_MODE,e,c]}]},{className:"class",beginKeywords:"class interface",end:"{",excludeEnd:!0,illegal:/[:\(\$"]/,contains:[{beginKeywords:"extends implements"},a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",end:";",illegal:/[\.']/,contains:[a.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use",end:";",contains:[a.UNDERSCORE_TITLE_MODE]},
+{begin:"=>"},e,c]}});b.registerLanguage("protobuf",function(a){return{keywords:{keyword:"package import option optional required repeated group",built_in:"double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes",literal:"true false"},contains:[a.QUOTE_STRING_MODE,a.NUMBER_MODE,a.C_LINE_COMMENT_MODE,{className:"class",beginKeywords:"message enum service",end:/\{/,illegal:/\n/,contains:[a.inherit(a.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]},
+{className:"function",beginKeywords:"rpc",end:/;/,excludeEnd:!0,keywords:"rpc returns"},{begin:/^\s*[A-Z_]+/,end:/\s*=/,excludeEnd:!0}]}});b.registerLanguage("puppet",function(a){var b=a.COMMENT("#","$"),d=a.inherit(a.TITLE_MODE,{begin:"([A-Za-z_]|::)(\\w|::)*"}),e={className:"variable",begin:"\\$([A-Za-z_]|::)(\\w|::)*"},c={className:"string",contains:[a.BACKSLASH_ESCAPE,e],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/}]};return{aliases:["pp"],contains:[b,e,c,{beginKeywords:"class",end:"\\{|;",
+illegal:/=/,contains:[d,b]},{beginKeywords:"define",end:/\{/,contains:[{className:"section",begin:a.IDENT_RE,endsParent:!0}]},{begin:a.IDENT_RE+"\\s+\\{",returnBegin:!0,end:/\S/,contains:[{className:"keyword",begin:a.IDENT_RE},{begin:/\{/,end:/\}/,keywords:{keyword:"and case default else elsif false if in import enherits node or true undef unless main settings $string ",literal:"alias audit before loglevel noop require subscribe tag owner ensure group mode name|0 changes context force incl lens load_path onlyif provider returns root show_diff type_check en_address ip_address realname command environment hour monute month monthday special target weekday creates cwd ogoutput refresh refreshonly tries try_sleep umask backup checksum content ctime force ignore links mtime purge recurse recurselimit replace selinux_ignore_defaults selrange selrole seltype seluser source souirce_permissions sourceselect validate_cmd validate_replacement allowdupe attribute_membership auth_membership forcelocal gid ia_load_module members system host_aliases ip allowed_trunk_vlans description device_url duplex encapsulation etherchannel native_vlan speed principals allow_root auth_class auth_type authenticate_user k_of_n mechanisms rule session_owner shared options device fstype enable hasrestart directory present absent link atboot blockdevice device dump pass remounts poller_tag use message withpath adminfile allow_virtual allowcdrom category configfiles flavor install_options instance package_settings platform responsefile status uninstall_options vendor unless_system_user unless_uid binary control flags hasstatus manifest pattern restart running start stop allowdupe auths expiry gid groups home iterations key_membership keys managehome membership password password_max_age password_min_age profile_membership profiles project purge_ssh_keys role_membership roles salt shell uid baseurl cost descr enabled enablegroups exclude failovermethod gpgcheck gpgkey http_caching include includepkgs keepalive metadata_expire metalink mirrorlist priority protect proxy proxy_password proxy_username repo_gpgcheck s3_enabled skip_if_unavailable sslcacert sslclientcert sslclientkey sslverify mounted",
+built_in:"architecture augeasversion blockdevices boardmanufacturer boardproductname boardserialnumber cfkey dhcp_servers domain ec2_ ec2_userdata facterversion filesystems ldom fqdn gid hardwareisa hardwaremodel hostname id|0 interfaces ipaddress ipaddress_ ipaddress6 ipaddress6_ iphostnumber is_virtual kernel kernelmajversion kernelrelease kernelversion kernelrelease kernelversion lsbdistcodename lsbdistdescription lsbdistid lsbdistrelease lsbmajdistrelease lsbminordistrelease lsbrelease macaddress macaddress_ macosx_buildversion macosx_productname macosx_productversion macosx_productverson_major macosx_productversion_minor manufacturer memoryfree memorysize netmask metmask_ network_ operatingsystem operatingsystemmajrelease operatingsystemrelease osfamily partitions path physicalprocessorcount processor processorcount productname ps puppetversion rubysitedir rubyversion selinux selinux_config_mode selinux_config_policy selinux_current_mode selinux_current_mode selinux_enforced selinux_policyversion serialnumber sp_ sshdsakey sshecdsakey sshrsakey swapencrypted swapfree swapsize timezone type uniqueid uptime uptime_days uptime_hours uptime_seconds uuid virtual vlans xendomains zfs_version zonenae zones zpool_version"},
+relevance:0,contains:[c,b,{begin:"[a-zA-Z_]+\\s*=>",returnBegin:!0,end:"=>",contains:[{className:"attr",begin:a.IDENT_RE}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},e]}],relevance:0}]}});b.registerLanguage("python",function(a){var b={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",
+built_in:"Ellipsis NotImplemented"},d={className:"meta",begin:/^(>>>|\.\.\.) /},e={className:"subst",begin:/\{/,end:/\}/,keywords:b,illegal:/#/},c={className:"string",contains:[a.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[d],relevance:10},{begin:/(u|b)?r?"""/,end:/"""/,contains:[d],relevance:10},{begin:/(fr|rf|f)'''/,end:/'''/,contains:[d,e]},{begin:/(fr|rf|f)"""/,end:/"""/,contains:[d,e]},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)"/,end:/"/,relevance:10},
+{begin:/(b|br)'/,end:/'/},{begin:/(b|br)"/,end:/"/},{begin:/(fr|rf|f)'/,end:/'/,contains:[e]},{begin:/(fr|rf|f)"/,end:/"/,contains:[e]},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE]},g={className:"number",relevance:0,variants:[{begin:a.BINARY_NUMBER_RE+"[lLjJ]?"},{begin:"\\b(0o[0-7]+)[lLjJ]?"},{begin:a.C_NUMBER_RE+"[lLjJ]?"}]},k={className:"params",begin:/\(/,end:/\)/,contains:["self",d,g,c]};e.contains=[c,g,d];return{aliases:["py","gyp"],keywords:b,illegal:/(<\/|->|\?)|=>/,contains:[d,g,c,a.HASH_COMMENT_MODE,
+{variants:[{className:"function",beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/,illegal:/[${=;\n,]/,contains:[a.UNDERSCORE_TITLE_MODE,k,{begin:/->/,endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/,end:/$/},{begin:/\b(print|exec)\(/}]}});b.registerLanguage("rust",function(a){return{aliases:["rs"],keywords:{keyword:"alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield move default",
+literal:"true false Some None Ok Err",built_in:"drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!"},
+lexemes:a.IDENT_RE+"!?",illegal:"</",contains:[a.C_LINE_COMMENT_MODE,a.COMMENT("/\\*","\\*/",{contains:["self"]}),a.inherit(a.QUOTE_STRING_MODE,{begin:/b?"/,illegal:null}),{className:"string",variants:[{begin:/r(#*)"(.|\n)*?"\1(?!#)/},{begin:/b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/}]},{className:"symbol",begin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:"number",variants:[{begin:"\\b0b([01_]+)([ui](8|16|32|64|128|size)|f(32|64))?"},{begin:"\\b0o([0-7_]+)([ui](8|16|32|64|128|size)|f(32|64))?"},{begin:"\\b0x([A-Fa-f0-9_]+)([ui](8|16|32|64|128|size)|f(32|64))?"},
+{begin:"\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)([ui](8|16|32|64|128|size)|f(32|64))?"}],relevance:0},{className:"function",beginKeywords:"fn",end:"(\\(|<)",excludeEnd:!0,contains:[a.UNDERSCORE_TITLE_MODE]},{className:"meta",begin:"#\\!?\\[",end:"\\]",contains:[{className:"meta-string",begin:/"/,end:/"/}]},{className:"class",beginKeywords:"type",end:";",contains:[a.inherit(a.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"\\S"},{className:"class",beginKeywords:"trait enum struct union",end:"{",
+contains:[a.inherit(a.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:"[\\w\\d]"},{begin:a.IDENT_RE+"::",keywords:{built_in:"drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!"}},
+{begin:"->"}]}});b.registerLanguage("scala",function(a){var b={className:"subst",variants:[{begin:"\\$[A-Za-z0-9_]+"},{begin:"\\${",end:"}"}]},d={className:"type",begin:"\\b[A-Z][A-Za-z0-9_]*",relevance:0},e={className:"title",begin:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,relevance:0};return{keywords:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},
+contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"string",variants:[{begin:'"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE]},{begin:'"""',end:'"""',relevance:10},{begin:'[a-z]+"',end:'"',illegal:"\\n",contains:[a.BACKSLASH_ESCAPE,b]},{className:"string",begin:'[a-z]+"""',end:'"""',contains:[b],relevance:10}]},{className:"symbol",begin:"'\\w[\\w\\d_]*(?!')"},d,{className:"function",beginKeywords:"def",end:/[:={\[(\n;]/,excludeEnd:!0,contains:[e]},{className:"class",beginKeywords:"class object trait type",
+end:/[:={\[\n;]/,excludeEnd:!0,contains:[{beginKeywords:"extends with",relevance:10},{begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[d]},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[d]},e]},a.C_NUMBER_MODE,{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("shell",function(a){return{aliases:["console"],contains:[{className:"meta",begin:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{end:"$",subLanguage:"bash"}}]}});b.registerLanguage("sql",
+function(a){var b=a.COMMENT("--","$");return{case_insensitive:!0,illegal:/[<>{}*#]/,contains:[{beginKeywords:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",end:/;/,endsWithParent:!0,
+lexemes:/[\w\.]+/,keywords:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",
 literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},contains:[{className:"string",begin:"'",end:"'",contains:[a.BACKSLASH_ESCAPE,{begin:"''"}]},{className:"string",begin:'"',end:'"',contains:[a.BACKSLASH_ESCAPE,{begin:'""'}]},{className:"string",begin:"`",end:"`",contains:[a.BACKSLASH_ESCAPE]},a.C_NUMBER_MODE,a.C_BLOCK_COMMENT_MODE,b]},
-a.C_BLOCK_COMMENT_MODE,b]}});b.registerLanguage("swift",function(a){var b={keyword:"__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",
+a.C_BLOCK_COMMENT_MODE,b]}});b.registerLanguage("swift",function(a){var b={keyword:"__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false fileprivate final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating open operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",
 literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},
-e=a.COMMENT("/\\*","\\*/",{contains:["self"]}),g={className:"subst",begin:/\\\(/,end:"\\)",keywords:b,contains:[]},d={className:"number",begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",relevance:0},f=a.inherit(a.QUOTE_STRING_MODE,{contains:[g,a.BACKSLASH_ESCAPE]});g.contains=[d];return{keywords:b,contains:[f,a.C_LINE_COMMENT_MODE,e,{className:"type",begin:"\\b[A-Z][\\w']*",relevance:0},d,{className:"function",beginKeywords:"func",end:"{",excludeEnd:!0,
-contains:[a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin:/</,end:/>/},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:b,contains:["self",d,f,a.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],illegal:/\[|%/},{className:"class",beginKeywords:"struct protocol class extension enum",keywords:b,end:"\\{",excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/})]},{className:"meta",begin:"(@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain)"},
-{beginKeywords:"import",end:/$/,contains:[a.C_LINE_COMMENT_MODE,e]}]}});b.registerLanguage("typescript",function(a){var b={keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void"};
+d=a.COMMENT("/\\*","\\*/",{contains:["self"]}),e={className:"subst",begin:/\\\(/,end:"\\)",keywords:b,contains:[]},c={className:"number",begin:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",relevance:0},g=a.inherit(a.QUOTE_STRING_MODE,{contains:[e,a.BACKSLASH_ESCAPE]});e.contains=[c];return{keywords:b,contains:[g,a.C_LINE_COMMENT_MODE,d,{className:"type",begin:"\\b[A-Z][\\w\u00c0-\u02b8']*",relevance:0},c,{className:"function",beginKeywords:"func",end:"{",
+excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin:/</,end:/>/},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:b,contains:["self",c,g,a.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}],illegal:/\[|%/},{className:"class",beginKeywords:"struct protocol class extension enum",keywords:b,end:"\\{",excludeEnd:!0,contains:[a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{className:"meta",begin:"(@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain)"},
+{beginKeywords:"import",end:/$/,contains:[a.C_LINE_COMMENT_MODE,d]}]}});b.registerLanguage("typescript",function(a){var b={keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract as from extends async await",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void Promise"};
 return{aliases:["ts"],keywords:b,contains:[{className:"meta",begin:/^\s*['"]use strict['"]/},a.APOS_STRING_MODE,a.QUOTE_STRING_MODE,{className:"string",begin:"`",end:"`",contains:[a.BACKSLASH_ESCAPE,{className:"subst",begin:"\\$\\{",end:"\\}"}]},a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,{className:"number",variants:[{begin:"\\b(0[bB][01]+)"},{begin:"\\b(0[oO][0-7]+)"},{begin:a.C_NUMBER_RE}],relevance:0},{begin:"("+a.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",
-contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.REGEXP_MODE],relevance:0},{className:"function",begin:"function",end:/[\{;]/,excludeEnd:!0,keywords:b,contains:["self",a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE],illegal:/["'\(]/}],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0},{begin:/module\./,keywords:{built_in:"module"},
-relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+a.IDENT_RE,relevance:0}]}});b.registerLanguage("yaml",function(a){var b={className:"attr",variants:[{begin:"^[ \\-]*[a-zA-Z_][\\w\\-]*:"},{begin:'^[ \\-]*"[a-zA-Z_][\\w\\-]*":'},{begin:"^[ \\-]*'[a-zA-Z_][\\w\\-]*':"}]},e={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/}],contains:[a.BACKSLASH_ESCAPE,
-{className:"template-variable",variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]};return{case_insensitive:!0,aliases:["yml","YAML","yaml"],contains:[b,{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>] *$",returnEnd:!0,contains:e.contains,end:b.variants[0].begin},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!!"+a.UNDERSCORE_IDENT_RE},{className:"meta",begin:"&"+a.UNDERSCORE_IDENT_RE+"$"},
-{className:"meta",begin:"\\*"+a.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"^ *-",relevance:0},e,a.HASH_COMMENT_MODE,a.C_NUMBER_MODE],keywords:{literal:"{ } true false yes no Yes No True False null"}}});return b});
+contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE,a.REGEXP_MODE,{className:"function",begin:"(\\(.*?\\)|"+a.IDENT_RE+")\\s*=>",returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:a.IDENT_RE},{begin:/\(\s*\)/},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,contains:["self",a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE]}]}]}],relevance:0},{className:"function",begin:"function",end:/[\{;]/,excludeEnd:!0,keywords:b,contains:["self",a.inherit(a.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),
+{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE],illegal:/["'\(]/}],illegal:/%/,relevance:0},{beginKeywords:"constructor",end:/\{/,excludeEnd:!0,contains:["self",{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:b,contains:[a.C_LINE_COMMENT_MODE,a.C_BLOCK_COMMENT_MODE],illegal:/["'\(]/}]},{begin:/module\./,keywords:{built_in:"module"},relevance:0},{beginKeywords:"module",end:/\{/,excludeEnd:!0},
+{beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:"interface extends"},{begin:/\$[(.]/},{begin:"\\."+a.IDENT_RE,relevance:0},{className:"meta",begin:"@[A-Za-z]+"}]}});b.registerLanguage("yaml",function(a){var b={className:"attr",variants:[{begin:"^[ \\-]*[a-zA-Z_][\\w\\-]*:"},{begin:'^[ \\-]*"[a-zA-Z_][\\w\\-]*":'},{begin:"^[ \\-]*'[a-zA-Z_][\\w\\-]*':"}]},d={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[a.BACKSLASH_ESCAPE,{className:"template-variable",
+variants:[{begin:"{{",end:"}}"},{begin:"%{",end:"}"}]}]};return{case_insensitive:!0,aliases:["yml","YAML","yaml"],contains:[b,{className:"meta",begin:"^---s*$",relevance:10},{className:"string",begin:"[\\|>] *$",returnEnd:!0,contains:d.contains,end:b.variants[0].begin},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!!"+a.UNDERSCORE_IDENT_RE},{className:"meta",begin:"&"+a.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+
+a.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"^ *-",relevance:0},a.HASH_COMMENT_MODE,{beginKeywords:"true false yes no null",keywords:{literal:"true false yes no null"}},a.C_NUMBER_MODE,d]}});return b});
diff --git a/lib/jgit/jgit.bzl b/lib/jgit/jgit.bzl
index 502c060..869daa8 100644
--- a/lib/jgit/jgit.bzl
+++ b/lib/jgit/jgit.bzl
@@ -1,6 +1,6 @@
 load("//tools/bzl:maven_jar.bzl", "GERRIT", "MAVEN_LOCAL", "MAVEN_CENTRAL", "maven_jar")
 
-_JGIT_VERS = "4.7.0.201704051617-r"
+_JGIT_VERS = "4.7.1.201706071930-r"
 
 _DOC_VERS = _JGIT_VERS # Set to _JGIT_VERS unless using a snapshot
 
@@ -26,28 +26,28 @@
         name = "jgit_lib",
         artifact = "org.eclipse.jgit:org.eclipse.jgit:" + _JGIT_VERS,
         repository = _JGIT_REPO,
-        sha1 = "99be65d1827276b97d4f51668b60f4a38f282bda",
-        src_sha1 = "de519d6f352aaf12e4c65f7590591326ac24d2e8",
+        sha1 = "0023aa574d6ea984e770af60da94da366a0109d2",
+        src_sha1 = "0497d0ac4f7c44eea49a32e7e1d6a5eee6343c33",
         unsign = True,
     )
     maven_jar(
         name = "jgit_servlet",
         artifact = "org.eclipse.jgit:org.eclipse.jgit.http.server:" + _JGIT_VERS,
         repository = _JGIT_REPO,
-        sha1 = "72fa98ebf001aadd3dcb99ca8f7fcd90983da56b",
+        sha1 = "0bacf02e5c9c587f8a6e680278d2b4b7fc8df96d",
         unsign = True,
     )
     maven_jar(
         name = "jgit_archive",
         artifact = "org.eclipse.jgit:org.eclipse.jgit.archive:" + _JGIT_VERS,
         repository = _JGIT_REPO,
-        sha1 = "f825504a903dfe8d3daa61d6ab5c26fbad92c954",
+        sha1 = "83c22720f1b00b4b5e321b9c8b089b91c1d78893",
     )
     maven_jar(
         name = "jgit_junit",
         artifact = "org.eclipse.jgit:org.eclipse.jgit.junit:" + _JGIT_VERS,
         repository = _JGIT_REPO,
-        sha1 = "e0dbc6d3568b2ba65c9421af2f06e4158a624bcb",
+        sha1 = "5a3f2d6cf33e88f3436acfd22a129bc7e2d2655b",
         unsign = True,
     )
 
diff --git a/plugins/hooks b/plugins/hooks
index 60adf57..0e4e41a 160000
--- a/plugins/hooks
+++ b/plugins/hooks
@@ -1 +1 @@
-Subproject commit 60adf5742f44badc5193b42ffc841bb2d0f6e442
+Subproject commit 0e4e41a160afb3553ea0a895500770b290ab569b
diff --git a/plugins/replication b/plugins/replication
index dc18cb6..7dd3d90 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit dc18cb665eb452d71602e1a980d7669a67265dfc
+Subproject commit 7dd3d90e1c4bb92dfde626eaa429fb37afa4d41c
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.js b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
index cc8d478..2ea5bcb 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.js
@@ -81,9 +81,10 @@
         if (data.hash[0] !== '/') {
           data.hash = '/' + data.hash;
         }
-        var newUrl = data.hash;
-        if (newUrl.indexOf('/VE/') === 0) {
-          newUrl = '/settings' + data.hash;
+        var hash = data.hash;
+        var newUrl = base + hash;
+        if (hash.indexOf('/VE/') === 0) {
+          newUrl = base + '/settings' + data.hash;
         }
         page.redirect(newUrl);
         return;
@@ -240,7 +241,8 @@
     page(/^\/register(\/.*)?/, function(ctx) {
       app.params = {justRegistered: true};
       var path = ctx.params[0] || '/';
-      page.show(path);
+      if (path[0] !== '/') { return; }
+      page.show(base + path);
     });
 
     page.start();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index e32d7d6..53eed73 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -94,6 +94,47 @@
       }
     },
 
+    /**
+     * Get current normalized selection.
+     * Merges multiple ranges, accounts for triple click, accounts for
+     * syntax highligh, convert native DOM Range objects to Gerrit concepts
+     * (line, side, etc).
+     * @return {{
+     *   start: {
+     *     node: Node,
+     *     side: string,
+     *     line: Number,
+     *     column: Number
+     *   },
+     *   end: {
+     *     node: Node,
+     *     side: string,
+     *     line: Number,
+     *     column: Number
+     *   }
+     * }}
+     */
+    _getNormalizedRange: function() {
+      var selection = window.getSelection();
+      var rangeCount = selection.rangeCount;
+      if (rangeCount === 0) {
+        return null;
+      } else if (rangeCount === 1) {
+        return this._normalizeRange(selection.getRangeAt(0));
+      } else {
+        var startRange = this._normalizeRange(selection.getRangeAt(0));
+        var endRange = this._normalizeRange(
+            selection.getRangeAt(rangeCount - 1));
+        return {
+          start: startRange.start,
+          end: endRange.end,
+        };
+      }
+    },
+
+    /**
+     * Normalize a specific DOM Range.
+     */
     _normalizeRange: function(domRange) {
       var range = GrRangeNormalizer.normalize(domRange);
       return this._fixTripleClickSelection({
@@ -204,16 +245,13 @@
     },
 
     _handleSelection: function() {
-      var selection = window.getSelection();
-      if (selection.rangeCount != 1) {
+      var normalizedRange = this._getNormalizedRange();
+      if (!normalizedRange) {
         return;
       }
-      var range = selection.getRangeAt(0);
-      if (range.collapsed) {
-        return;
-      }
-      var normalizedRange = this._normalizeRange(range);
+      var domRange = window.getSelection().getRangeAt(0);
       var start = normalizedRange.start;
+
       if (!start) {
         return;
       }
@@ -239,7 +277,7 @@
       };
       actionBox.side = start.side;
       if (start.line === end.line) {
-        actionBox.placeAbove(range);
+        actionBox.placeAbove(domRange);
       } else if (start.node instanceof Text) {
         actionBox.placeAbove(start.node.splitText(start.column));
         start.node.parentElement.normalize(); // Undo splitText from above.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
index 827437c..c4c2993 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
@@ -304,6 +304,37 @@
         assert.equal(getActionSide(), 'right');
       });
 
+      test('multiple ranges aka firefox implementation', () => {
+        var startContent = stubContent(119, 'right');
+        var endContent = stubContent(120, 'right');
+
+        var startRange = document.createRange();
+        startRange.setStart(startContent.firstChild, 10);
+        startRange.setEnd(startContent.firstChild, 11);
+
+        var endRange = document.createRange();
+        endRange.setStart(endContent.lastChild, 6);
+        endRange.setEnd(endContent.lastChild, 7);
+
+        var getRangeAtStub = sandbox.stub();
+        getRangeAtStub
+            .onFirstCall().returns(startRange)
+            .onSecondCall().returns(endRange);
+        sandbox.stub(window, 'getSelection').returns({
+          rangeCount: 2,
+          getRangeAt: getRangeAtStub,
+          removeAllRanges: sandbox.stub(),
+        });
+        element._handleSelection();
+        assert.isTrue(element.isRangeSelected());
+        assert.deepEqual(getActionRange(), {
+          startLine: 119,
+          startChar: 10,
+          endLine: 120,
+          endChar: 36,
+        });
+      });
+
       test('multiline grow end highlight over tabs', function() {
         var startContent = stubContent(119, 'right');
         var endContent = stubContent(120, 'right');
@@ -502,6 +533,7 @@
         result = GrRangeNormalizer._getTextOffset(content, child);
         assert.equal(result, 0);
       });
+
       // TODO (viktard): Selection starts in line number.
       // TODO (viktard): Empty lines in selection start.
       // TODO (viktard): Empty lines in selection end.
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
index 0914846..7dea848 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.js
@@ -18,6 +18,7 @@
     'application/dart': 'dart',
     'application/json': 'json',
     'application/typescript': 'typescript',
+    'application/x-erb': 'erb',
     'text/css': 'css',
     'text/html': 'html',
     'text/javascript': 'js',
@@ -31,16 +32,20 @@
     'text/x-go': 'go',
     'text/x-haskell': 'haskell',
     'text/x-java': 'java',
+    'text/x-kotlin': 'kotlin',
     'text/x-lua': 'lua',
     'text/x-markdown': 'markdown',
     'text/x-objectivec': 'objectivec',
     'text/x-ocaml': 'ocaml',
     'text/x-perl': 'perl',
+    'text/x-php': 'php',
     'text/x-protobuf': 'protobuf',
+    'text/x-puppet': 'puppet',
     'text/x-python': 'python',
     'text/x-ruby': 'ruby',
     'text/x-rustsrc': 'rust',
     'text/x-scala': 'scala',
+    'text/x-shell': 'shell',
     'text/x-sh': 'bash',
     'text/x-sql': 'sql',
     'text/x-swift': 'swift',
diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py
index 6838101..97c2b12 100755
--- a/tools/eclipse/project.py
+++ b/tools/eclipse/project.py
@@ -139,7 +139,7 @@
   plugins = set()
 
   # Classpath entries are absolute for cross-cell support
-  java_library = re.compile('bazel-out/local-fastbuild/bin/(.*)/[^/]+[.]jar$')
+  java_library = re.compile('bazel-out/.*?-fastbuild/bin/(.*)/[^/]+[.]jar$')
   srcs = re.compile('(.*/external/[^/]+)/jar/(.*)[.]jar')
   for p in _query_classpath(MAIN):
     if p.endswith('-src.jar'):
diff --git a/tools/js/bower2bazel.py b/tools/js/bower2bazel.py
index d12129e..745a7de 100755
--- a/tools/js/bower2bazel.py
+++ b/tools/js/bower2bazel.py
@@ -76,7 +76,10 @@
 
   seeds = set(seeds)
   for v in version_targets:
-    fn = os.path.join("bazel-out/local-fastbuild/bin", v.lstrip("/").replace(":", "/"))
+    try:
+      fn = os.path.join("bazel-out/local-fastbuild/bin", v.lstrip("/").replace(":", "/"))
+    except:
+      fn = os.path.join("bazel-out/darwin_x86_64-fastbuild/bin", v.lstrip("/").replace(":", "/"))
     with open(fn) as f:
       j = json.load(f)
       if "" in j:
diff --git a/version.bzl b/version.bzl
index 7dfd46a..4ddfa16 100644
--- a/version.bzl
+++ b/version.bzl
@@ -2,4 +2,4 @@
 # Used by :api_install and :api_deploy targets
 # when talking to the destination repository.
 #
-GERRIT_VERSION = "2.14.1-SNAPSHOT"
+GERRIT_VERSION = "2.14.1"