Merge "Convert gr-autocomplete tests to Karma tests"
diff --git a/Documentation/js_licenses.txt b/Documentation/js_licenses.txt
index 97c2548..956a94d 100644
--- a/Documentation/js_licenses.txt
+++ b/Documentation/js_licenses.txt
@@ -279,36 +279,6 @@
----
-[[es6-promise]]
-es6-promise
-
-* es6-promise
-
-[[es6-promise_license]]
-----
-Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-----
-
-
[[Polymer-2018]]
Polymer-2018
@@ -747,37 +717,6 @@
----
-[[whatwg-fetch]]
-whatwg-fetch
-
-* whatwg-fetch
-
-[[whatwg-fetch_license]]
-----
-Copyright (c) 2014-2016 GitHub, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
[[font-roboto-local-fonts-roboto]]
font-roboto-local-fonts-roboto
diff --git a/Documentation/licenses.txt b/Documentation/licenses.txt
index c1dfb94..d561596 100644
--- a/Documentation/licenses.txt
+++ b/Documentation/licenses.txt
@@ -3221,36 +3221,6 @@
----
-[[es6-promise]]
-es6-promise
-
-* es6-promise
-
-[[es6-promise_license]]
-----
-Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-----
-
-
[[Polymer-2018]]
Polymer-2018
@@ -3689,37 +3659,6 @@
----
-[[whatwg-fetch]]
-whatwg-fetch
-
-* whatwg-fetch
-
-[[whatwg-fetch_license]]
-----
-Copyright (c) 2014-2016 GitHub, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-----
-
-
[[font-roboto-local-fonts-roboto]]
font-roboto-local-fonts-roboto
diff --git a/README.md b/README.md
index a76dac6..084f2b0 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,8 @@
[Gerrit](https://www.gerritcodereview.com) is a code review and project
management tool for Git based projects.
-[![Build Status](https://gerrit-ci.gerritforge.com/job/Gerrit-master/badge/icon)](https://gerrit-ci.gerritforge.com/job/Gerrit-master/)
+[![Build Status](https://gerrit-ci.gerritforge.com/job/Gerrit-bazel-master/badge/icon)](https://gerrit-ci.gerritforge.com/job/Gerrit-bazel-master/)
+![Maven Central](https://img.shields.io/maven-central/v/com.google.gerrit/gerrit-war)
## Objective
diff --git a/WORKSPACE b/WORKSPACE
index 8f9ddf0..91eef76 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -60,8 +60,8 @@
http_archive(
name = "build_bazel_rules_nodejs",
- sha256 = "d14076339deb08e5460c221fae5c5e9605d2ef4848eee1f0c81c9ffdc1ab31c1",
- urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.6.1/rules_nodejs-1.6.1.tar.gz"],
+ sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
+ urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
)
# File is specific to Polymer and copied from the Closure Github -- should be
@@ -82,6 +82,7 @@
# https://github.com/google/closure-templates/pull/155
rules_closure_dependencies(
omit_aopalliance = True,
+ omit_bazel_skylib = True,
omit_javax_inject = True,
omit_rules_cc = True,
)
@@ -91,10 +92,10 @@
# Golang support for PolyGerrit local dev server.
http_archive(
name = "io_bazel_rules_go",
- sha256 = "b34cbe1a7514f5f5487c3bfee7340a4496713ddf4f119f7a225583d6cafd793a",
+ sha256 = "a8d6b1b354d371a646d2f7927319974e0f9e52f73a2452d2b3877118169eb6bb",
urls = [
- "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.21.1/rules_go-v0.21.1.tar.gz",
- "https://github.com/bazelbuild/rules_go/releases/download/v0.21.1/rules_go-v0.21.1.tar.gz",
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.23.3/rules_go-v0.23.3.tar.gz",
+ "https://github.com/bazelbuild/rules_go/releases/download/v0.23.3/rules_go-v0.23.3.tar.gz",
],
)
@@ -106,8 +107,11 @@
http_archive(
name = "bazel_gazelle",
- sha256 = "3c681998538231a2d24d0c07ed5a7658cb72bfb5fd4bf9911157c0e9ac6a2687",
- urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.17.0/bazel-gazelle-0.17.0.tar.gz"],
+ sha256 = "cdb02a887a7187ea4d5a27452311a75ed8637379a1287d8eeb952138ea485f7d",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.21.1/bazel-gazelle-v0.21.1.tar.gz",
+ "https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.21.1/bazel-gazelle-v0.21.1.tar.gz",
+ ],
)
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
diff --git a/java/com/google/gerrit/acceptance/BUILD b/java/com/google/gerrit/acceptance/BUILD
index 541e479..9d8bc57 100644
--- a/java/com/google/gerrit/acceptance/BUILD
+++ b/java/com/google/gerrit/acceptance/BUILD
@@ -39,6 +39,7 @@
"//lib:gson",
"//lib:guava-retrying",
"//lib:jgit",
+ "//lib:jgit-ssh-jsch",
"//lib:jsch",
"//lib/commons:compress",
"//lib/commons:lang",
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index 3593d8a..4e62a0f 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -22,6 +22,7 @@
import com.google.gerrit.common.IoUtil;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.PluginData;
+import com.google.gerrit.index.SchemaDefinitions;
import com.google.gerrit.index.project.ProjectSchemaDefinitions;
import com.google.gerrit.pgm.init.BaseInit;
import com.google.gerrit.pgm.init.Browser;
@@ -31,6 +32,9 @@
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.index.GerritIndexStatus;
+import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
+import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
+import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.gerrit.server.ioutil.HostPlatform;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gerrit.server.util.ReplicaUtil;
@@ -89,7 +93,7 @@
@Inject Browser browser;
- private boolean projectsIndexExists;
+ private GerritIndexStatus indexStatus;
public Init() {
super(new WarDistribution(), null);
@@ -103,7 +107,7 @@
@Override
protected boolean beforeInit(SiteInit init) throws Exception {
- projectsIndexExists = new GerritIndexStatus(init.site).exists(ProjectSchemaDefinitions.NAME);
+ indexStatus = new GerritIndexStatus(init.site);
ErrorLogFile.errorOnlyConsole();
if (!skipPlugins) {
@@ -132,6 +136,12 @@
@Override
protected void afterInit(SiteRun run) throws Exception {
+ List<SchemaDefinitions<?>> schemaDefs =
+ ImmutableList.of(
+ AccountSchemaDefinitions.INSTANCE,
+ ChangeSchemaDefinitions.INSTANCE,
+ GroupSchemaDefinitions.INSTANCE,
+ ProjectSchemaDefinitions.INSTANCE);
List<Module> modules = new ArrayList<>();
modules.add(
new AbstractModule() {
@@ -146,8 +156,12 @@
});
modules.add(new GerritServerConfigModule());
Guice.createInjector(modules).injectMembers(this);
- if (!ReplicaUtil.isReplica(run.flags.cfg) && !projectsIndexExists) {
- reindexProjects();
+ if (!ReplicaUtil.isReplica(run.flags.cfg)) {
+ for (SchemaDefinitions<?> schemaDef : schemaDefs) {
+ if (!indexStatus.exists(schemaDef.getName())) {
+ reindex(schemaDef);
+ }
+ }
}
start(run);
}
@@ -260,8 +274,7 @@
}
}
- private void reindexProjects() throws Exception {
- // Reindex all projects, so that we bootstrap the project index for new installations
+ private void reindex(SchemaDefinitions<?> schemaDef) throws Exception {
List<String> reindexArgs =
ImmutableList.of(
"--site-path",
@@ -269,8 +282,9 @@
"--threads",
Integer.toString(1),
"--index",
- ProjectSchemaDefinitions.NAME);
- getConsoleUI().message("Init complete, reindexing projects with:");
+ schemaDef.getName());
+ getConsoleUI()
+ .message(String.format("Init complete, reindexing %s with:", schemaDef.getName()));
getConsoleUI().message(" reindex " + reindexArgs.stream().collect(joining(" ")));
Reindex reindexPgm = new Reindex();
reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
diff --git a/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java b/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
index 5b3b34c..bca5338 100644
--- a/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
+++ b/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
@@ -50,7 +50,7 @@
setHeader("Subject", "[Gerrit Code Review] HTTP password was " + operation);
setMessageId(
messageIdGenerator.fromReasonAccountIdAndTimestamp(
- "HTTP password change", user.getAccountId(), TimeUtil.nowTs()));
+ "HTTP_password_change", user.getAccountId(), TimeUtil.now()));
add(RecipientType.TO, Address.create(getEmail()));
}
diff --git a/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java b/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
index 01e165d..3a411dc 100644
--- a/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
+++ b/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
@@ -28,7 +28,7 @@
import com.google.gerrit.server.update.RepoView;
import com.google.inject.Inject;
import java.io.IOException;
-import java.sql.Timestamp;
+import java.time.Instant;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -111,7 +111,7 @@
* @return MessageId that depends on the reason, accountId, and timestamp.
*/
public MessageId fromReasonAccountIdAndTimestamp(
- String reason, Account.Id accountId, Timestamp timestamp) {
+ String reason, Account.Id accountId, Instant timestamp) {
return new AutoValue_MessageIdGenerator_MessageId(
reason + "-" + accountId.toString() + "-" + timestamp.toString());
}
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index fdd6b81..8f63177 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -259,9 +259,12 @@
return true;
}
+ // All message ids must start with < and end with >. Also, they must have @domain and no spaces.
private void addMessageId(OutgoingEmailValidationListener.Args va, String suffix) {
if (messageId != null) {
- va.headers.put(FieldName.MESSAGE_ID, new EmailHeader.String(messageId.id() + suffix));
+ String message = "<" + messageId.id() + suffix + "@" + getGerritHost() + ">";
+ message = message.replaceAll("\\s", "");
+ va.headers.put(FieldName.MESSAGE_ID, new EmailHeader.String(message));
}
}
diff --git a/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java b/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
index 057a871..8e08b1c 100644
--- a/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/OutgoingEmailIT.java
@@ -26,6 +26,7 @@
import com.google.gerrit.mail.Address;
import com.google.gerrit.mail.EmailHeader;
import com.google.gerrit.testing.FakeEmailSender;
+import java.net.URL;
import org.eclipse.jgit.lib.Repository;
import org.junit.Test;
@@ -43,23 +44,25 @@
gApi.changes().id(result.getChangeId()).abandon();
assertThat(getMessageId(sender))
.isEqualTo(
- repository
- .getRefDatabase()
- .exactRef(result.getChange().getId().toRefPrefix() + "meta")
- .getObjectId()
- .getName()
- + "-HTML");
+ withPrefixAndSuffixForMessageId(
+ repository
+ .getRefDatabase()
+ .exactRef(result.getChange().getId().toRefPrefix() + "meta")
+ .getObjectId()
+ .getName()
+ + "-HTML"));
sender.clear();
gApi.changes().id(result.getChangeId()).restore();
assertThat(getMessageId(sender))
.isEqualTo(
- repository
- .getRefDatabase()
- .exactRef(result.getChange().getId().toRefPrefix() + "meta")
- .getObjectId()
- .getName()
- + "-HTML");
+ withPrefixAndSuffixForMessageId(
+ repository
+ .getRefDatabase()
+ .exactRef(result.getChange().getId().toRefPrefix() + "meta")
+ .getObjectId()
+ .getName()
+ + "-HTML"));
}
@Test
@@ -80,12 +83,13 @@
assertThat(getMessageId(sender))
.isEqualTo(
- allUsersRepo
- .getRefDatabase()
- .exactRef(RefNames.refsUsers(admin.id()))
- .getObjectId()
- .getName()
- + "-HTML");
+ withPrefixAndSuffixForMessageId(
+ allUsersRepo
+ .getRefDatabase()
+ .exactRef(RefNames.refsUsers(admin.id()))
+ .getObjectId()
+ .getName()
+ + "-HTML"));
}
@Test
@@ -93,7 +97,8 @@
sender.clear();
String newPassword = gApi.accounts().self().generateHttpPassword();
assertThat(newPassword).isNotNull();
- assertThat(getMessageId(sender)).contains("HTTP password change-" + admin.id().toString());
+ assertThat(getMessageId(sender))
+ .containsMatch("<HTTP_password_change-" + admin.id().toString() + ".*@.*>");
}
@Test
@@ -124,4 +129,10 @@
(Iterables.getOnlyElement(sender.getMessages()).headers().get("Message-ID")))
.getString();
}
+
+ // Each message-id must start with '<' and end with '>'. Also, it must contain no spaces and it
+ // must contain a '@'.
+ private String withPrefixAndSuffixForMessageId(String id) throws Exception {
+ return "<" + id + "@" + new URL(canonicalWebUrl.get()).getHost() + ">";
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/MessageIdGeneratorIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/MessageIdGeneratorIT.java
index 3228900..a8fd834 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/MessageIdGeneratorIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/MessageIdGeneratorIT.java
@@ -24,7 +24,6 @@
import com.google.gerrit.mail.MailMessage;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.util.time.TimeUtil;
-import java.sql.Timestamp;
import java.time.Instant;
import javax.inject.Inject;
import org.eclipse.jgit.lib.Repository;
@@ -38,7 +37,7 @@
try (Repository repo = repoManager.openRepository(allUsers)) {
String messageId = messageIdGenerator.fromAccountUpdate(admin.id()).id();
String sha1 =
- repo.getRefDatabase().getRef(RefNames.refsUsers(admin.id())).getObjectId().getName();
+ repo.getRefDatabase().findRef(RefNames.refsUsers(admin.id())).getObjectId().getName();
assertThat(sha1).isEqualTo(messageId);
}
}
@@ -51,7 +50,7 @@
String messageId = messageIdGenerator.fromChangeUpdate(project, patchsetId).id();
String sha1 =
repo.getRefDatabase()
- .getRef(String.format("%smeta", patchsetId.changeId().toRefPrefix()))
+ .findRef(String.format("%smeta", patchsetId.changeId().toRefPrefix()))
.getObjectId()
.getName();
assertThat(sha1).isEqualTo(messageId);
@@ -74,7 +73,7 @@
@Test
public void fromReasonAccountIdAndTimestamp() throws Exception {
String reason = "reason";
- Timestamp timestamp = TimeUtil.nowTs();
+ Instant timestamp = TimeUtil.now();
assertThat(
messageIdGenerator.fromReasonAccountIdAndTimestamp(reason, admin.id(), timestamp).id())
.isEqualTo(reason + "-" + admin.id().toString() + "-" + timestamp.toString());
diff --git a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
index 38b7e0e..cf349ab 100644
--- a/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
+++ b/javatests/com/google/gerrit/acceptance/pgm/ElasticReindexIT.java
@@ -21,7 +21,6 @@
import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Injector;
import org.eclipse.jgit.lib.Config;
-import org.junit.Before;
public class ElasticReindexIT extends AbstractReindexTests {
@@ -39,10 +38,4 @@
public void configureIndex(Injector injector) {
createAllIndexes(injector);
}
-
- @Before
- public void reindexFirstSinceElastic() throws Exception {
- assertServerStartupFails();
- runGerrit("reindex", "-d", sitePaths.site_path.toString(), "--show-stack-trace");
- }
}
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
index 4ae77da..d7d67b8 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/MailProcessorIT.java
@@ -48,6 +48,7 @@
import com.google.gerrit.testing.TestCommentHelper;
import com.google.inject.Inject;
import com.google.inject.Module;
+import java.net.URL;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
@@ -300,7 +301,7 @@
// ensure the message header contains a valid message id.
assertThat(((EmailHeader.String) (message.headers().get("Message-ID"))).getString())
- .isEqualTo("some id-REJECTION-HTML");
+ .containsMatch("<someid-REJECTION-HTML@" + new URL(canonicalWebUrl.get()).getHost() + ">");
}
@Test
diff --git a/lib/BUILD b/lib/BUILD
index f0c0aad..d3ef4b9 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -47,6 +47,13 @@
)
java_library(
+ name = "jgit-ssh-jsch",
+ data = ["//lib:LICENSE-jgit"],
+ visibility = ["//visibility:public"],
+ exports = ["@jgit//org.eclipse.jgit.ssh.jsch:ssh-jsch"],
+)
+
+java_library(
name = "jgit-archive",
data = ["//lib:LICENSE-jgit"],
visibility = ["//visibility:public"],
diff --git a/modules/jgit b/modules/jgit
index 75fccca..55371c5 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 75fcccaea39f7a2112886e04a94458d6b7b7c37f
+Subproject commit 55371c5f063370aeca85acab16f867734ff4226c
diff --git a/plugins/BUILD b/plugins/BUILD
index 5f9c142..a071bde 100644
--- a/plugins/BUILD
+++ b/plugins/BUILD
@@ -71,6 +71,7 @@
"//lib/jackson:jackson-core",
"//lib:jgit-servlet",
"//lib:jgit",
+ "//lib:jgit-ssh-jsch",
"//lib:jsr305",
"//lib/log:api",
"//lib/log:log4j",
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index e211fb1..7357ab4 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit e211fb1bd21043e2574c438a687c8f492d538c97
+Subproject commit 7357ab473599d16ae33cc982bbd65472f08c2dd6
diff --git a/plugins/delete-project b/plugins/delete-project
index 02cced3..7671def 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit 02cced37fd755a1123b1ec18af96503683d88f50
+Subproject commit 7671def07882aab89b19eb7496418588ea7375d9
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 021ce08..7bca96d 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -1,6 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("//tools/bzl:genrule2.bzl", "genrule2")
-load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
package(default_visibility = ["//visibility:public"])
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_html.js b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_html.js
index c46cf30..e9c16241 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section_html.js
@@ -82,7 +82,7 @@
<div id="mainContainer">
<div class="header">
<div class="name">
- <h3>[[_computeSectionName(section.id)]]</h3>
+ <h3 class="heading-3">[[_computeSectionName(section.id)]]</h3>
<gr-button
id="editBtn"
link=""
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_html.js b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_html.js
index c5577c2..47657ac 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_html.js
@@ -63,9 +63,9 @@
Loading...
</div>
<div id="loadedContent" class$="[[_computeLoadingClass(_loading)]]">
- <h1 id="Title">[[_groupName]]</h1>
+ <h1 id="Title" class="heading-1">[[_groupName]]</h1>
<div id="form">
- <h3 id="members">Members</h3>
+ <h3 id="members" class="heading-3">Members</h3>
<fieldset>
<span class="value">
<gr-autocomplete
@@ -112,7 +112,7 @@
</tbody>
</table>
</fieldset>
- <h3 id="includedGroups">Included Groups</h3>
+ <h3 id="includedGroups" class="heading-3">Included Groups</h3>
<fieldset>
<span class="value">
<gr-autocomplete
diff --git a/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.js b/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.js
index 0af87ad..7a843dc 100644
--- a/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-group/gr-group_html.js
@@ -37,18 +37,21 @@
Loading...
</div>
<div id="loadedContent" class$="[[_computeLoadingClass(_loading)]]">
- <h1 id="Title">[[_groupName]]</h1>
- <h2 id="configurations">General</h2>
+ <h1 id="Title" class="heading-1">[[_groupName]]</h1>
+ <h2 id="configurations" class="heading-2">General</h2>
<div id="form">
<fieldset>
- <h3 id="groupUUID">Group UUID</h3>
+ <h3 id="groupUUID" class="heading-3">Group UUID</h3>
<fieldset>
<gr-copy-clipboard
id="uuid"
text="[[_getGroupUUID(_groupConfig.id)]]"
></gr-copy-clipboard>
</fieldset>
- <h3 id="groupName" class$="[[_computeHeaderClass(_rename)]]">
+ <h3
+ id="groupName"
+ class$="heading-3 [[_computeHeaderClass(_rename)]]"
+ >
Group Name
</h3>
<fieldset>
@@ -72,7 +75,10 @@
>
</span>
</fieldset>
- <h3 id="groupOwner" class$="[[_computeHeaderClass(_owner)]]">
+ <h3
+ id="groupOwner"
+ class$="heading-3 [[_computeHeaderClass(_owner)]]"
+ >
Owners
</h3>
<fieldset>
@@ -99,7 +105,7 @@
>
</span>
</fieldset>
- <h3 class$="[[_computeHeaderClass(_description)]]">
+ <h3 class$="heading-3 [[_computeHeaderClass(_description)]]">
Description
</h3>
<fieldset>
@@ -123,7 +129,7 @@
</gr-button>
</span>
</fieldset>
- <h3 id="options" class$="[[_computeHeaderClass(_options)]]">
+ <h3 id="options" class$="heading-3 [[_computeHeaderClass(_options)]]">
Group Options
</h3>
<fieldset>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
index 5f0739a..b46c7c0 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-access/gr-repo-access_html.js
@@ -62,7 +62,10 @@
Loading...
</div>
<div id="loadedContent" class$="[[_computeLoadingClass(_loading)]]">
- <h3 id="inheritsFrom" class$="[[_computeShowInherit(_inheritsFrom)]]">
+ <h3
+ id="inheritsFrom"
+ class$="heading-3 [[_computeShowInherit(_inheritsFrom)]]"
+ >
<span class="rightsText">Rights Inherit From</span>
<a
href$="[[_computeParentHref(_inheritsFrom.name)]]"
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_html.js b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_html.js
index cf934b0..50aca6d 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-command/gr-repo-command_html.js
@@ -23,7 +23,7 @@
margin-bottom: var(--spacing-xxl);
}
</style>
- <h3>[[title]]</h3>
+ <h3 class="heading-3">[[title]]</h3>
<gr-button
title$="[[tooltip]]"
disabled$="[[disabled]]"
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.js b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.js
index b27c36b..66ec740 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_html.js
@@ -27,12 +27,12 @@
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
</style>
<main class="gr-form-styles read-only">
- <h1 id="Title">Repository Commands</h1>
+ <h1 id="Title" class="heading-1">Repository Commands</h1>
<div id="loading" class$="[[_computeLoadingClass(_loading)]]">
Loading...
</div>
<div id="loadedContent" class$="[[_computeLoadingClass(_loading)]]">
- <h2 id="options">Command</h2>
+ <h2 id="options" class="heading-2">Command</h2>
<div id="form">
<gr-repo-command
title="Create change"
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_html.js b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_html.js
index de36e73..ea8a8b9 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_html.js
@@ -50,7 +50,7 @@
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
</style>
<div class="info">
- <h1 id="Title" class$="name">
+ <h1 id="Title" class="heading-1">
[[repo]]
<hr />
</h1>
@@ -63,7 +63,7 @@
</div>
<div id="loadedContent" class$="[[_computeLoadingClass(_loading)]]">
<div id="downloadContent" class$="[[_computeHideClass(_schemes)]]">
- <h2 id="download">Download</h2>
+ <h2 id="download" class="heading-2">Download</h2>
<fieldset>
<gr-download-commands
id="downloadCommands"
@@ -73,12 +73,15 @@
></gr-download-commands>
</fieldset>
</div>
- <h2 id="configurations" class$="[[_computeHeaderClass(_configChanged)]]">
+ <h2
+ id="configurations"
+ class$="heading-2 [[_computeHeaderClass(_configChanged)]]"
+ >
Configurations
</h2>
<div id="form">
<fieldset>
- <h3 id="Description">Description</h3>
+ <h3 id="Description" class="heading-3">Description</h3>
<fieldset>
<iron-autogrow-textarea
id="descriptionInput"
@@ -89,7 +92,7 @@
disabled$="[[_readOnly]]"
></iron-autogrow-textarea>
</fieldset>
- <h3 id="Options">Repository Options</h3>
+ <h3 id="Options" class="heading-3">Repository Options</h3>
<fieldset id="options">
<section>
<span class="title">State</span>
@@ -362,7 +365,7 @@
</span>
</section>
</fieldset>
- <h3 id="Options">Contributor Agreements</h3>
+ <h3 id="Options" class="heading-3">Contributor Agreements</h3>
<fieldset id="agreements">
<section>
<span class="title">
@@ -407,7 +410,7 @@
class$="pluginConfig [[_computeHideClass(_pluginData)]]"
on-plugin-config-changed="_handlePluginConfigChanged"
>
- <h3>Plugins</h3>
+ <h3 class="heading-3">Plugins</h3>
<template is="dom-repeat" items="[[_pluginData]]" as="data">
<gr-repo-plugin-config
plugin-data="[[data]]"
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_html.js b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_html.js
index 4a357af..cc6223d 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help_html.js
@@ -48,12 +48,6 @@
padding-top: var(--spacing-xl);
vertical-align: top;
}
- #help h1 {
- font-family: var(--header-font-family);
- font-size: var(--font-size-h3);
- font-weight: var(--font-weight-h3);
- line-height: var(--line-height-h3);
- }
#help p {
margin-bottom: var(--spacing-m);
max-width: 35em;
@@ -73,7 +67,7 @@
</p>
</div>
<div id="help">
- <h1>Push your first change for code review</h1>
+ <h2 class="heading-3">Push your first change for code review</h2>
<p>
Pushing a change for review is easy, but a little different from other git
code review tools. Click on the \`Create Change' button and follow the
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_html.js b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_html.js
index f6fb1d0..75af51e 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header_html.js
@@ -24,7 +24,7 @@
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
</style>
<div class="info">
- <h1 class$="name">
+ <h1 class="heading-1">
[[repo]]
<hr />
</h1>
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_html.js b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_html.js
index 5a5d590..8207284 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header_html.js
@@ -21,12 +21,6 @@
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
</style>
<style include="dashboard-header-styles">
- .name {
- display: inline-block;
- }
- .name hr {
- width: 100%;
- }
.status.hide,
.name.hide,
.dashboardLink.hide {
@@ -39,7 +33,7 @@
aria-label="Account avatar"
></gr-avatar>
<div class="info">
- <h1 class="name">
+ <h1 class="heading-1">
[[_computeDetail(_accountDetails, 'name')]]
</h1>
<hr />
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index f8580e0..dc207dc 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -1019,10 +1019,7 @@
this.$.fileList.collapseAllDiffs();
}
- _paramsChanged(value, oldValue) {
- const paramsChanged = JSON.stringify(oldValue) !== JSON.stringify(value);
- if (!paramsChanged) return;
-
+ _paramsChanged(value) {
if (value.view !== GerritNav.View.CHANGE) {
this._initialLoadComplete = false;
return;
@@ -1138,6 +1135,14 @@
this.viewState.numFilesShown = numFilesShown;
}
+ _handleMessageAnchorTap(e) {
+ const hash = MSG_PREFIX + e.detail.id;
+ const url = GerritNav.getUrlForChange(this._change,
+ this._patchRange.patchNum, this._patchRange.basePatchNum,
+ this._editMode, hash);
+ history.replaceState(null, '', url);
+ }
+
_maybeScrollToMessage(hash) {
if (hash.startsWith(MSG_PREFIX)) {
this.messagesList.scrollToMessage(hash.substr(MSG_PREFIX.length));
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
index 50b6d2d..f5a0463 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.js
@@ -711,6 +711,7 @@
change-comments="[[_changeComments]]"
project-name="[[_change.project]]"
show-reply-buttons="[[_loggedIn]]"
+ on-message-anchor-tap="_handleMessageAnchorTap"
on-reply="_handleMessageReply"
></gr-messages-list>
</template>
@@ -725,6 +726,7 @@
change-comments="[[_changeComments]]"
project-name="[[_change.project]]"
show-reply-buttons="[[_loggedIn]]"
+ on-message-anchor-tap="_handleMessageAnchorTap"
on-reply="_handleMessageReply"
></gr-messages-list-experimental>
</template>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
index 192ba8f..1362fe3 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.js
@@ -322,6 +322,20 @@
const getCustomCssValue =
cssParam => util.getComputedStyleValue(cssParam, element);
+ test('_handleMessageAnchorTap', () => {
+ element._changeNum = '1';
+ element._patchRange = {
+ basePatchNum: 'PARENT',
+ patchNum: 1,
+ };
+ const getUrlStub = sandbox.stub(GerritNav, 'getUrlForChange');
+ const replaceStateStub = sandbox.stub(history, 'replaceState');
+ element._handleMessageAnchorTap({detail: {id: 'a12345'}});
+
+ assert.equal(getUrlStub.lastCall.args[4], '#message-a12345');
+ assert.isTrue(replaceStateStub.called);
+ });
+
suite('plugins adding to file tab', () => {
setup(done => {
// Resolving it here instead of during setup() as other tests depend
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_html.js b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_html.js
index 9569c03..0446e4e 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_html.js
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_html.js
@@ -56,16 +56,12 @@
.archives a:last-of-type {
margin-right: 0;
}
- .title {
- flex: 1;
- font-weight: var(--font-weight-bold);
- }
.hidden {
display: none;
}
</style>
<section>
- <h3 class="title">
+ <h3 class="heading-3">
Patch set [[patchNum]] of [[_computePatchSetQuantity(change.revisions)]]
</h3>
</section>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index adcf2e2..5e9825a 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -70,6 +70,8 @@
U: 'Unchanged',
};
+const FILE_ROW_CLASS = 'file-row';
+
/**
* Type for FileInfo
*
@@ -676,29 +678,55 @@
}
/**
+ * Returns true if the event e is a click on an element.
+ *
+ * The click is: mouse click or pressing Enter or Space key
+ * P.S> Screen readers sends click event as well
+ */
+ _isClickEvent(e) {
+ if (e.type === 'click') {
+ return true;
+ }
+ const isSpaceOrEnter = (e.key === 'Enter' || e.key === ' ');
+ return e.type === 'keydown' && isSpaceOrEnter;
+ }
+
+ _fileActionClick(e, fileAction) {
+ if (this._isClickEvent(e)) {
+ const fileRow = this._getFileRowFromEvent(e);
+ if (!fileRow) {
+ return;
+ }
+ // Prevent default actions (e.g. scrolling for space key)
+ e.preventDefault();
+ // Prevent _handleFileListClick handler call
+ e.stopPropagation();
+ this.$.fileCursor.setCursor(fileRow.element);
+ fileAction(fileRow.file);
+ }
+ }
+
+ _reviewedClick(e) {
+ this._fileActionClick(e,
+ file => this._reviewFile(file.path));
+ }
+
+ _expandedClick(e) {
+ this._fileActionClick(e,
+ file => this._toggleFileExpanded(file));
+ }
+
+ /**
* Handle all events from the file list dom-repeat so event handleers don't
* have to get registered for potentially very long lists.
*/
_handleFileListClick(e) {
- // Traverse upwards to find the row element if the target is not the row.
- let row = e.target;
- while (!row.classList.contains('row') && row.parentElement) {
- row = row.parentElement;
- }
-
- // No action needed for item without a valid file
- if (!row.dataset.file) {
+ const fileRow = this._getFileRowFromEvent(e);
+ if (!fileRow) {
return;
}
-
- const file = JSON.parse(row.dataset.file);
+ const file = fileRow.file;
const path = file.path;
- // Handle checkbox mark as reviewed.
- if (e.target.classList.contains('markReviewed')) {
- e.preventDefault();
- return this._reviewFile(path);
- }
-
// If a path cannot be interpreted from the click target (meaning it's not
// somewhere in the row, e.g. diff content) or if the user clicked the
// link, defer to the native behavior.
@@ -708,9 +736,28 @@
if (this.descendedFromClass(e.target, 'editFileControls')) { return; }
e.preventDefault();
+ this.$.fileCursor.setCursor(fileRow.element);
this._toggleFileExpanded(file);
}
+ _getFileRowFromEvent(e) {
+ // Traverse upwards to find the row element if the target is not the row.
+ let row = e.target;
+ while (!row.classList.contains(FILE_ROW_CLASS) && row.parentElement) {
+ row = row.parentElement;
+ }
+
+ // No action needed for item without a valid file
+ if (!row.dataset.file) {
+ return null;
+ }
+
+ return {
+ file: JSON.parse(row.dataset.file),
+ element: row,
+ };
+ }
+
/**
* Generates file range from file info object.
*
@@ -1066,7 +1113,7 @@
if (this._files && this._files.length > 0) {
flush();
this.$.fileCursor.stops = Array.from(
- dom(this.root).querySelectorAll('.file-row'));
+ dom(this.root).querySelectorAll(`.${FILE_ROW_CLASS}`));
this.$.fileCursor.setCursorAtIndex(this.selectedIndex, true);
}
}
@@ -1129,10 +1176,29 @@
FileStatus[statusCode] : 'Status Unknown';
}
+ /**
+ * Converts any boolean-like variable to the string 'true' or 'false'
+ *
+ * This method is useful when you bind aria-checked attribute to a boolean
+ * value. The aria-checked attribute is string attribute. Binding directly
+ * to boolean variable causes problem on gerrit-CI.
+ *
+ * @param {object} val
+ * @return {string} 'true' if val is true-like, otherwise false
+ */
+ _booleanToString(val) {
+ return val ? 'true' : 'false';
+ }
+
_isFileExpanded(path, expandedFilesRecord) {
return expandedFilesRecord.base.some(f => f.path === path);
}
+ _isFileExpandedStr(path, expandedFilesRecord) {
+ return this._booleanToString(
+ this._isFileExpanded(path, expandedFilesRecord));
+ }
+
_computeExpandedFiles(expandedCount, totalCount) {
if (expandedCount === 0) {
return GrFileListConstants.FilesExpandedState.NONE;
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.js
index d1238f3..4ac4bb1 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.js
@@ -28,6 +28,20 @@
min-height: calc(var(--line-height-normal) + 2 * var(--spacing-s));
padding: var(--spacing-xs) var(--spacing-l);
}
+ /* The class defines a content visible only to screen readers */
+ .noCommentsScreenReaderText {
+ opacity: 0;
+ max-width: 1px;
+ overflow: hidden;
+ display: none;
+ }
+ div[role='gridcell']
+ > div.comments
+ > span:empty
+ + span:empty
+ + span.noCommentsScreenReaderText {
+ display: inline;
+ }
:host(.loading) .row {
opacity: 0.5;
}
@@ -164,6 +178,9 @@
color: #c62828;
font-weight: var(--font-weight-bold);
}
+ .show-hide-icon:focus {
+ outline: none;
+ }
.show-hide {
margin-left: var(--spacing-s);
width: 1.9em;
@@ -200,27 +217,24 @@
margin-left: var(--spacing-xxl);
width: 15em;
}
- .reviewed label {
+ .reviewedSwitch {
color: var(--link-color);
opacity: 0;
justify-content: flex-end;
width: 100%;
}
- .reviewed label:hover {
+ .reviewedSwitch:hover {
cursor: pointer;
opacity: 100;
}
.row:focus {
outline: none;
}
- .row:hover .reviewed label,
- .row:focus .reviewed label,
- .row.expanded .reviewed label {
+ .row:hover .reviewedSwitch,
+ .row:focus-within .reviewedSwitch,
+ .row.expanded .reviewedSwitch {
opacity: 100;
}
- .reviewed input {
- display: none;
- }
.reviewedLabel {
color: var(--deemphasized-text-color);
margin-right: var(--spacing-l);
@@ -233,6 +247,9 @@
.editFileControls {
width: 7em;
}
+ .markReviewed:focus {
+ outline: none;
+ }
.markReviewed,
.pathLink {
display: inline-block;
@@ -255,10 +272,8 @@
padding: 0px;
}
}
- .pathLink:hover gr-copy-clipboard,
- .pathLink:focus gr-copy-clipboard,
- .oldPath:focus gr-copy-clipboard,
- .oldPath:hover gr-copy-clipboard {
+ .row:focus-within gr-copy-clipboard,
+ .row:hover gr-copy-clipboard {
visibility: visible;
}
@@ -296,8 +311,13 @@
}
}
</style>
- <div id="container" on-click="_handleFileListClick">
- <div class="header-row row">
+ <div
+ id="container"
+ on-click="_handleFileListClick"
+ role="grid"
+ aria-label="Files list"
+ >
+ <div class="header-row row" role="row">
<!-- endpoint: change-view-file-list-header-prepend -->
<template is="dom-if" if="[[_showPrependedDynamicColumns]]">
<template
@@ -305,14 +325,14 @@
items="[[_dynamicPrependedHeaderEndpoints]]"
as="headerEndpoint"
>
- <gr-endpoint-decorator name$="[[headerEndpoint]]">
+ <gr-endpoint-decorator name$="[[headerEndpoint]]" role="columnheader">
</gr-endpoint-decorator>
</template>
</template>
- <div class="path">File</div>
- <div class="comments">Comments</div>
- <div class="sizeBars">Size</div>
- <div class="header-stats">Delta</div>
+ <div class="path" role="columnheader">File</div>
+ <div class="comments" role="columnheader">Comments</div>
+ <div class="sizeBars" role="columnheader">Size</div>
+ <div class="header-stats" role="columnheader">Delta</div>
<!-- endpoint: change-view-file-list-header -->
<template is="dom-if" if="[[_showDynamicColumns]]">
<template
@@ -320,14 +340,18 @@
items="[[_dynamicHeaderEndpoints]]"
as="headerEndpoint"
>
- <gr-endpoint-decorator name$="[[headerEndpoint]]">
+ <gr-endpoint-decorator name$="[[headerEndpoint]]" role="columnheader">
</gr-endpoint-decorator>
</template>
</template>
<!-- Empty div here exists to keep spacing in sync with file rows. -->
- <div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]"></div>
- <div class="editFileControls showOnEdit"></div>
- <div class="show-hide"></div>
+ <div
+ class="reviewed hideOnEdit"
+ hidden$="[[!_loggedIn]]"
+ aria-hidden="true"
+ ></div>
+ <div class="editFileControls showOnEdit" aria-hidden="true"></div>
+ <div class="show-hide" aria-hidden="true"></div>
</div>
<template
@@ -344,6 +368,7 @@
class$="file-row row [[_computePathClass(file.__path, _expandedFiles.*)]]"
data-file$="[[_computeFileRange(file)]]"
tabindex="-1"
+ role="row"
>
<!-- endpoint: change-view-file-list-content-prepend -->
<template is="dom-if" if="[[_showPrependedDynamicColumns]]">
@@ -352,7 +377,7 @@
items="[[_dynamicPrependedContentEndpoints]]"
as="contentEndpoint"
>
- <gr-endpoint-decorator name="[[contentEndpoint]]">
+ <gr-endpoint-decorator name="[[contentEndpoint]]" role="gridcell">
<gr-endpoint-param name="changeNum" value="[[changeNum]]">
</gr-endpoint-param>
<gr-endpoint-param name="patchRange" value="[[patchRange]]">
@@ -366,6 +391,7 @@
<span
data-url="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]"
class="path"
+ role="gridcell"
>
<a
class="pathLink"
@@ -406,66 +432,114 @@
</div>
</template>
</span>
- <div class="comments desktop">
- <span class="drafts">
- [[_computeDraftsString(changeComments, patchRange, file.__path)]]
- </span>
- [[_computeCommentsString(changeComments, patchRange, file.__path)]]
+ <div role="gridcell">
+ <div class="comments desktop">
+ <span class="drafts"
+ ><!-- This comments ensure that span is empty when the function
+ returns empty string.
+ -->[[_computeDraftsString(changeComments, patchRange,
+ file.__path)]]<!-- This comments ensure that span is empty when
+ the function returns empty string.
+ --></span
+ >
+ <span
+ ><!--
+ -->[[_computeCommentsString(changeComments, patchRange,
+ file.__path)]]<!--
+ --></span
+ >
+ <span class="noCommentsScreenReaderText">
+ <!-- Screen readers read the following content only if 2 other
+ spans in the parent div is empty. The content is not visible on
+ the page.
+ Without this span, screen readers don't navigate correctly inside
+ table, because empty div doesn't rendered. For example, VoiceOver
+ jumps back to the whole table.
+ We can use   instead, but it sounds worse.
+ -->
+ No comments
+ </span>
+ </div>
+ <div class="comments mobile">
+ <span class="drafts"
+ ><!-- This comments ensure that span is empty when the function
+ returns empty string.
+ -->[[_computeDraftsStringMobile(changeComments, patchRange,
+ file.__path)]]<!-- This comments ensure that span is empty when
+ the function returns empty string.
+ --></span
+ >
+ <span
+ ><!--
+ -->[[_computeCommentsStringMobile(changeComments, patchRange,
+ file.__path)]]<!--
+ --></span
+ >
+ <span class="noCommentsScreenReaderText">
+ <!-- The same as for desktop comments -->
+ No comments
+ </span>
+ </div>
</div>
- <div class="comments mobile">
- <span class="drafts">
- [[_computeDraftsStringMobile(changeComments, patchRange,
- file.__path)]]
- </span>
- [[_computeCommentsStringMobile(changeComments, patchRange,
- file.__path)]]
+ <div role="gridcell">
+ <!-- The content must be in a separate div. It guarantees, that
+ gridcell always visible for screen readers.
+ For example, without a nested div screen readers pronounce the
+ "Commit message" row content with incorrect column headers.
+ -->
+ <div
+ class$="[[_computeSizeBarsClass(_showSizeBars, file.__path)]]"
+ aria-label="A bar that represents the addition and deletion ratio for the current file"
+ >
+ <svg width="61" height="8">
+ <rect
+ x$="[[_computeBarAdditionX(file, _sizeBarLayout)]]"
+ y="0"
+ height="8"
+ fill="var(--positive-green-text-color)"
+ width$="[[_computeBarAdditionWidth(file, _sizeBarLayout)]]"
+ ></rect>
+ <rect
+ x$="[[_computeBarDeletionX(_sizeBarLayout)]]"
+ y="0"
+ height="8"
+ fill="var(--negative-red-text-color)"
+ width$="[[_computeBarDeletionWidth(file, _sizeBarLayout)]]"
+ ></rect>
+ </svg>
+ </div>
</div>
- <div
- class$="[[_computeSizeBarsClass(_showSizeBars, file.__path)]]"
- aria-label="A bar that represents the addition and deletion ratio for the current file"
- tabindex="0"
- >
- <svg width="61" height="8">
- <rect
- x$="[[_computeBarAdditionX(file, _sizeBarLayout)]]"
- y="0"
- height="8"
- fill="var(--positive-green-text-color)"
- width$="[[_computeBarAdditionWidth(file, _sizeBarLayout)]]"
- ></rect>
- <rect
- x$="[[_computeBarDeletionX(_sizeBarLayout)]]"
- y="0"
- height="8"
- fill="var(--negative-red-text-color)"
- width$="[[_computeBarDeletionWidth(file, _sizeBarLayout)]]"
- ></rect>
- </svg>
- </div>
- <div class$="[[_computeClass('stats', file.__path)]]">
- <span
- class="added"
- tabindex="0"
- aria-label$="[[file.lines_inserted]] lines added"
- hidden$="[[file.binary]]"
- >
- +[[file.lines_inserted]]
- </span>
- <span
- class="removed"
- tabindex="0"
- aria-label$="[[file.lines_deleted]] lines removed"
- hidden$="[[file.binary]]"
- >
- -[[file.lines_deleted]]
- </span>
- <span
- class$="[[_computeBinaryClass(file.size_delta)]]"
- hidden$="[[!file.binary]]"
- >
- [[_formatBytes(file.size_delta)]] [[_formatPercentage(file.size,
- file.size_delta)]]
- </span>
+ <div class="stats" role="gridcell">
+ <!-- The content must be in a separate div. It guarantees, that
+ gridcell always visible for screen readers.
+ For example, without a nested div screen readers pronounce the
+ "Commit message" row content with incorrect column headers.
+ -->
+ <div class$="[[_computeClass('', file.__path)]]">
+ <span
+ class="added"
+ tabindex="0"
+ aria-label$="[[file.lines_inserted]] lines added"
+ hidden$="[[file.binary]]"
+ >
+ +[[file.lines_inserted]]
+ </span>
+ <span
+ class="removed"
+ tabindex="0"
+ aria-label$="[[file.lines_deleted]] lines removed"
+ hidden$="[[file.binary]]"
+ >
+ -[[file.lines_deleted]]
+ </span>
+ <span
+ class$="[[_computeBinaryClass(file.size_delta)]]"
+ hidden$="[[!file.binary]]"
+ >
+ [[_formatBytes(file.size_delta)]] [[_formatPercentage(file.size,
+ file.size_delta)]]
+ </span>
+ </div>
</div>
<!-- endpoint: change-view-file-list-content -->
<template is="dom-if" if="[[_showDynamicColumns]]">
@@ -474,7 +548,7 @@
items="[[_dynamicContentEndpoints]]"
as="contentEndpoint"
>
- <div class$="[[_computeClass('', file.__path)]]">
+ <div class$="[[_computeClass('', file.__path)]]" role="gridcell">
<gr-endpoint-decorator name="[[contentEndpoint]]">
<gr-endpoint-param name="changeNum" value="[[changeNum]]">
</gr-endpoint-param>
@@ -486,25 +560,44 @@
</div>
</template>
</template>
- <div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]" hidden="">
+ <div
+ class="reviewed hideOnEdit"
+ role="gridcell"
+ hidden$="[[!_loggedIn]]"
+ >
<span
class$="reviewedLabel [[_computeReviewedClass(file.isReviewed)]]"
+ aria-hidden$="[[!file.isReviewed]]"
>Reviewed</span
>
- <label>
- <input
- class="reviewed"
- type="checkbox"
- checked="[[file.isReviewed]]"
- />
+ <!-- Do not use input type="checkbox" with hidden input and
+ visible label here. Screen readers don't read/interract
+ correctly with such input.
+ -->
+ <span
+ class="reviewedSwitch"
+ role="switch"
+ tabindex="0"
+ on-click="_reviewedClick"
+ on-keydown="_reviewedClick"
+ aria-label="Reviewed"
+ aria-checked$="[[_booleanToString(file.isReviewed)]]"
+ >
+ <!-- Trick with tabindex to avoid outline on mouse focus, but
+ preserve focus outline for keyboard navigation -->
<span
+ tabindex="-1"
class="markReviewed"
title$="[[_reviewedTitle(file.isReviewed)]]"
>[[_computeReviewedText(file.isReviewed)]]</span
>
- </label>
+ </span>
</div>
- <div class="editFileControls showOnEdit">
+ <div
+ class="editFileControls showOnEdit"
+ role="gridcell"
+ aria-hidden$="[[!editMode]]"
+ >
<template is="dom-if" if="[[editMode]]">
<gr-edit-file-controls
class$="[[_computeClass('', file.__path)]]"
@@ -512,25 +605,32 @@
></gr-edit-file-controls>
</template>
</div>
- <div class="show-hide">
- <label
+ <div class="show-hide" role="gridcell">
+ <!-- Do not use input type="checkbox" with hidden input and
+ visible label here. Screen readers don't read/interract
+ correctly with such input.
+ -->
+ <span
class="show-hide"
data-path$="[[file.__path]]"
data-expand="true"
+ role="switch"
+ tabindex="0"
+ aria-checked$="[[_isFileExpandedStr(file.__path, _expandedFiles.*)]]"
+ aria-label="Expand file"
+ on-click="_expandedClick"
+ on-keydown="_expandedClick"
>
- <input
- type="checkbox"
- class="show-hide"
- checked$="[[_isFileExpanded(file.__path, _expandedFiles.*)]]"
- data-path$="[[file.__path]]"
- data-expand="true"
- />
+ <!-- Trick with tabindex to avoid outline on mouse focus, but
+ preserve focus outline for keyboard navigation -->
<iron-icon
+ class="show-hide-icon"
+ tabindex="-1"
id="icon"
icon="[[_computeShowHideIcon(file.__path, _expandedFiles.*)]]"
>
</iron-icon>
- </label>
+ </span>
</div>
</div>
<template
@@ -560,14 +660,14 @@
<span
class="added"
tabindex="0"
- aria-label$="[[_patchChange.inserted]] lines added"
+ aria-label$="Total [[_patchChange.inserted]] lines added"
>
+[[_patchChange.inserted]]
</span>
<span
class="removed"
tabindex="0"
- aria-label$="[[_patchChange.deleted]] lines removed"
+ aria-label$="Total [[_patchChange.deleted]] lines removed"
>
-[[_patchChange.deleted]]
</span>
@@ -590,12 +690,18 @@
</div>
<div class="row totalChanges" hidden$="[[_hideBinaryChangeTotals]]">
<div class="total-stats">
- <span class="added" aria-label="Total lines added">
+ <span
+ class="added"
+ aria-label$="Total bytes inserted: [[_formatBytes(_patchChange.size_delta_inserted)]] "
+ >
[[_formatBytes(_patchChange.size_delta_inserted)]]
[[_formatPercentage(_patchChange.total_size,
_patchChange.size_delta_inserted)]]
</span>
- <span class="removed" aria-label="Total lines removed">
+ <span
+ class="removed"
+ aria-label$="Total bytes removed: [[_formatBytes(_patchChange.size_delta_deleted)]]"
+ >
[[_formatBytes(_patchChange.size_delta_deleted)]]
[[_formatPercentage(_patchChange.total_size,
_patchChange.size_delta_deleted)]]
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index f038f6c..8e279ae 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -836,36 +836,42 @@
patchNum: '2',
};
element.$.fileCursor.setCursorAtIndex(0);
+ const reviewSpy = sandbox.spy(element, '_reviewFile');
+ const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
flushAsynchronousOperations();
const fileRows =
dom(element.root).querySelectorAll('.row:not(.header-row)');
- const checkSelector = 'input.reviewed[type="checkbox"]';
+ const checkSelector = 'span.reviewedSwitch[role="switch"]';
const commitMsg = fileRows[0].querySelector(checkSelector);
const fileAdded = fileRows[1].querySelector(checkSelector);
const myFile = fileRows[2].querySelector(checkSelector);
- assert.isTrue(commitMsg.checked);
- assert.isFalse(fileAdded.checked);
- assert.isTrue(myFile.checked);
+ assert.equal(commitMsg.getAttribute('aria-checked'), 'true');
+ assert.equal(fileAdded.getAttribute('aria-checked'), 'false');
+ assert.equal(myFile.getAttribute('aria-checked'), 'true');
const commitReviewLabel = fileRows[0].querySelector('.reviewedLabel');
- const markReviewLabel = commitMsg.nextElementSibling;
+ const markReviewLabel = fileRows[0].querySelector('.markReviewed');
assert.isTrue(commitReviewLabel.classList.contains('isReviewed'));
assert.equal(markReviewLabel.textContent, 'MARK UNREVIEWED');
- const clickSpy = sandbox.spy(element, '_handleFileListClick');
+ const clickSpy = sandbox.spy(element, '_reviewedClick');
MockInteractions.tap(markReviewLabel);
- assert.isTrue(saveStub.lastCall.calledWithExactly('/COMMIT_MSG', false));
- assert.isFalse(commitReviewLabel.classList.contains('isReviewed'));
+ // assert.isTrue(saveStub.lastCall.calledWithExactly('/COMMIT_MSG', false));
+ // assert.isFalse(commitReviewLabel.classList.contains('isReviewed'));
assert.equal(markReviewLabel.textContent, 'MARK REVIEWED');
assert.isTrue(clickSpy.lastCall.args[0].defaultPrevented);
+ assert.isTrue(reviewSpy.calledOnce);
MockInteractions.tap(markReviewLabel);
assert.isTrue(saveStub.lastCall.calledWithExactly('/COMMIT_MSG', true));
assert.isTrue(commitReviewLabel.classList.contains('isReviewed'));
assert.equal(markReviewLabel.textContent, 'MARK UNREVIEWED');
assert.isTrue(clickSpy.lastCall.args[0].defaultPrevented);
+ assert.isTrue(reviewSpy.calledTwice);
+
+ assert.isFalse(toggleExpandSpy.called);
});
test('_computeFileStatusLabel', () => {
@@ -906,13 +912,6 @@
assert.isTrue(clickSpy.calledTwice);
assert.isTrue(toggleExpandSpy.calledOnce);
assert.isFalse(reviewStub.called);
-
- // Click the reviewed checkbox, resulting in a call to _reviewFile, but
- // no additional call to _toggleFileExpanded.
- row.querySelector('.markReviewed').click();
- assert.isTrue(clickSpy.calledThrice);
- assert.isTrue(toggleExpandSpy.calledOnce);
- assert.isTrue(reviewStub.calledOnce);
});
test('_handleFileListClick editMode', () => {
@@ -975,12 +974,12 @@
dom(element.root).querySelectorAll('.row:not(.header-row)');
// Because the label surrounds the input, the tap event is triggered
// there first.
- const showHideLabel = fileRows[0].querySelector('label.show-hide');
const showHideCheck = fileRows[0].querySelector(
- 'input.show-hide[type="checkbox"]');
- assert.isNotOk(showHideCheck.checked);
+ 'span.show-hide[role="switch"]');
+ const showHideLabel = showHideCheck.querySelector('.show-hide-icon');
+ assert.equal(showHideCheck.getAttribute('aria-checked'), 'false');
MockInteractions.tap(showHideLabel);
- assert.isOk(showHideCheck.checked);
+ assert.equal(showHideCheck.getAttribute('aria-checked'), 'true');
assert.notEqual(
element._expandedFiles.findIndex(f => f.path === 'myfile.txt'),
-1);
@@ -1001,7 +1000,7 @@
// Tap on a file to generate the diff.
const row = dom(element.root)
- .querySelectorAll('.row:not(.header-row) label.show-hide')[0];
+ .querySelectorAll('.row:not(.header-row) span.show-hide')[0];
MockInteractions.tap(row);
flushAsynchronousOperations();
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_html.js b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_html.js
index 2faac52..4670e6a 100644
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_html.js
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog_html.js
@@ -67,7 +67,7 @@
}
</style>
<header>
- <h1 id="title">Included In:</h1>
+ <h1 id="title" class="heading-1">Included In:</h1>
<span class="closeButtonContainer">
<gr-button id="closeButton" link="" on-click="_handleCloseTap"
>Close</gr-button
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.js b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
index be53652..e065008 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.js
@@ -35,7 +35,6 @@
const PATCH_SET_PREFIX_PATTERN = /^Patch Set \d+:\s*(.*)/;
const LABEL_TITLE_SCORE_PATTERN = /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?$/;
-const MSG_PREFIX = '#message-';
/**
* @extends PolymerElement
@@ -153,10 +152,6 @@
value: false,
},
_isCleanerLogExperimentEnabled: Boolean,
- _changeMessageUrl: {
- type: String,
- computed: '_computeChangeMessageUrl(message)',
- },
};
}
@@ -411,10 +406,13 @@
return classes.join(' ');
}
- _computeChangeMessageUrl(message) {
- if (!message) return '';
- const hash = MSG_PREFIX + message.id;
- return hash;
+ _handleAnchorClick(e) {
+ e.preventDefault();
+ this.dispatchEvent(new CustomEvent('message-anchor-tap', {
+ bubbles: true,
+ composed: true,
+ detail: {id: this.message.id},
+ }));
}
_handleReplyTap(e) {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.js b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.js
index baaf5a3..de4a72a 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.js
@@ -181,9 +181,6 @@
content: 'PS ';
}
}
- .message-link {
- text-decoration: none;
- }
</style>
<div class$="[[_computeClass(_expanded)]]">
<div class="contentContainer">
@@ -303,20 +300,13 @@
</span>
</template>
<template is="dom-if" if="[[message.id]]">
- <span class="date">
+ <span class="date" on-click="_handleAnchorClick">
<gr-date-formatter
has-tooltip=""
show-date-and-time=""
date-str="[[message.date]]"
></gr-date-formatter>
</span>
- <a class="message-link" href="[[_changeMessageUrl]]">
- <iron-icon
- id="icon"
- class="link-icon"
- icon="gr-icons:link"
- ></iron-icon>
- </a>
</template>
<iron-icon
id="expandToggle"
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
index 0bd53c7..332ca52 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.html
@@ -222,6 +222,26 @@
});
});
+ test('clicking on date link fires event', () => {
+ element.message = {
+ type: 'REVIEWER_UPDATE',
+ updated: '2016-01-12 20:24:49.448000000',
+ reviewer: {},
+ id: '47c43261_55aa2c41',
+ expanded: false,
+ };
+ flushAsynchronousOperations();
+ const stub = sinon.stub();
+ element.addEventListener('message-anchor-tap', stub);
+ const dateEl = element.shadowRoot
+ .querySelector('.date');
+ assert.ok(dateEl);
+ MockInteractions.tap(dateEl);
+
+ assert.isTrue(stub.called);
+ assert.deepEqual(stub.lastCall.args[0].detail, {id: element.message.id});
+ });
+
suite('compute messages', () => {
test('empty', () => {
assert.equal(element._computeMessageContent('', '', true), '');
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
index 6aa7ffc..2321deb 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list_html.js
@@ -21,9 +21,6 @@
:host {
display: block;
}
- h3 {
- margin: var(--spacing-m) 0 0;
- }
section {
margin-bottom: 1.4em; /* Same as line height for collapse purposes */
}
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
index 7286678..de11712 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.js
@@ -108,9 +108,6 @@
background: var(--table-header-background-color);
padding: var(--spacing-l);
}
- .draftsContainer h3 {
- margin-top: var(--spacing-xs);
- }
#checkingStatusLabel,
#notLatestLabel {
margin-left: var(--spacing-l);
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_html.js b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_html.js
index 78b576e..e850fbe 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_html.js
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog_html.js
@@ -55,7 +55,7 @@
}
</style>
<header>
- <h3>Keyboard shortcuts</h3>
+ <h3 class="heading-3">Keyboard shortcuts</h3>
<gr-button link="" on-click="_handleCloseTap">Close</gr-button>
</header>
<main>
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
index 8308942..69e2989 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.js
@@ -393,13 +393,12 @@
* @param {number=} opt_patchNum
* @return {string}
*/
- getUrlForChangeById(changeNum, project, opt_patchNum, opt_messageHash) {
+ getUrlForChangeById(changeNum, project, opt_patchNum) {
return this._getUrlFor({
view: GerritNav.View.CHANGE,
changeNum,
project,
patchNum: opt_patchNum,
- messageHash: opt_messageHash,
});
},
diff --git a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_html.js b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_html.js
index 2d371e2..b1a951b7 100644
--- a/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_html.js
+++ b/polygerrit-ui/app/elements/settings/gr-cla-view/gr-cla-view_html.js
@@ -61,8 +61,8 @@
/* Workaround for empty style block - see https://github.com/Polymer/tools/issues/408 */
</style>
<main>
- <h1>New Contributor Agreement</h1>
- <h3>Select an agreement type:</h3>
+ <h1 class="heading-1">New Contributor Agreement</h1>
+ <h3 class="heading-3">Select an agreement type:</h3>
<template
is="dom-repeat"
items="[[_serverConfig.auth.contributor_agreements]]"
@@ -92,7 +92,7 @@
id="claNewAgreement"
class$="[[_computeShowAgreementsClass(_showAgreements)]]"
>
- <h3 class="smallHeading">Review the agreement:</h3>
+ <h3 class="heading-3">Review the agreement:</h3>
<div id="agreementsUrl" class="agreementsUrl">
<a href$="[[_agreementsUrl]]" target="blank" rel="noopener">
Please review the agreement.</a
@@ -101,7 +101,7 @@
<div
class$="agreementsTextBox [[_computeHideAgreementClass(_agreementName, _serverConfig.auth.contributor_agreements)]]"
>
- <h3 class="smallHeading">Complete the agreement:</h3>
+ <h3 class="heading-3">Complete the agreement:</h3>
<iron-input
bind-value="{{_agreementsText}}"
placeholder="Enter 'I agree' here"
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item_html.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item_html.js
index e26faab..26200d4 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item_html.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-item_html.js
@@ -23,6 +23,6 @@
margin-bottom: var(--spacing-xxl);
}
</style>
- <h2 id="[[anchor]]">[[title]]</h2>
+ <h2 id="[[anchor]]" class="heading-2">[[title]]</h2>
<slot></slot>
`;
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
index b22d412..e32a551 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
@@ -21,6 +21,12 @@
:host {
color: var(--primary-text-color);
}
+ h2 {
+ font-family: var(--header-font-family);
+ font-size: var(--font-size-h2);
+ font-weight: var(--font-weight-h2);
+ line-height: var(--line-height-h2);
+ }
.newEmailInput {
width: 20em;
}
@@ -94,7 +100,7 @@
</ul>
</gr-page-nav>
<main class="gr-form-styles">
- <h1>User Settings</h1>
+ <h1 class="heading-1">User Settings</h1>
<section class="darkToggle">
<div class="toggle">
<paper-toggle-button
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_html.js b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_html.js
index b32f871..54b404d 100644
--- a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog_html.js
@@ -60,7 +60,7 @@
}
</style>
<div class="container" on-keydown="_handleKeydown">
- <header class="font-h3"><slot name="header"></slot></header>
+ <header class="heading-3"><slot name="header"></slot></header>
<main>
<div class="overflow-container">
<slot name="main"></slot>
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
index 9c8788b..bbf6a96 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
@@ -70,7 +70,7 @@
<gr-avatar account="[[account]]" image-size="56"></gr-avatar>
</div>
<div class="account">
- <h3 class="name">[[account.name]]</h3>
+ <h3 class="name heading-3">[[account.name]]</h3>
<div class="email">[[account.email]]</div>
</div>
</div>
diff --git a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
index 254fd25..85caa61 100644
--- a/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
+++ b/polygerrit-ui/app/elements/shared/gr-icons/gr-icons.js
@@ -102,8 +102,6 @@
<g id="pets"><circle cx="4.5" cy="9.5" r="2.5"/><circle cx="9" cy="5.5" r="2.5"/><circle cx="15" cy="5.5" r="2.5"/><circle cx="19.5" cy="9.5" r="2.5"/><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.54-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.8z"/><path d="M0 0h24v24H0z" fill="none"/></g>
<!-- This SVG is a copy from material.io https://material.io/icons/#visibility-->
<g id="ready"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g>
- <!-- This SVG is a copy from material.io https://material.io/resources/icons/?icon=link&style=baseline-->
- <g id="link"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g>
</defs>
</svg>
</iron-iconset-svg>`;
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index 2d951d4..de4f12d 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -14,15 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/* NB: es6-promise Needed for IE11 and fetch polyfill support, see Issue 4308 */
/* NB: Order is important, because of namespaced classes. */
import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
-import 'es6-promise/lib/es6-promise.js';
-import 'whatwg-fetch/fetch.js';
import {PatchSetBehavior} from '../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.js';
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
diff --git a/polygerrit-ui/app/node_modules_licenses/licenses.ts b/polygerrit-ui/app/node_modules_licenses/licenses.ts
index 4c259cd..1141d6b 100644
--- a/polygerrit-ui/app/node_modules_licenses/licenses.ts
+++ b/polygerrit-ui/app/node_modules_licenses/licenses.ts
@@ -261,14 +261,6 @@
}
},
{
- name: "es6-promise",
- license: {
- name: "es6-promise",
- type: LicenseTypes.Mit,
- packageLicenseFile: "LICENSE"
- }
- },
- {
name: "isarray",
license: SharedLicenses.IsArray
},
@@ -291,14 +283,6 @@
{
name: "polymer-bridges",
license: SharedLicenses.Polymer2018
- },
- {
- name: "whatwg-fetch",
- license: {
- name: "whatwg-fetch",
- type: LicenseTypes.Mit,
- packageLicenseFile: "LICENSE"
- }
}
];
diff --git a/polygerrit-ui/app/package.json b/polygerrit-ui/app/package.json
index a9668c3..32560ff 100644
--- a/polygerrit-ui/app/package.json
+++ b/polygerrit-ui/app/package.json
@@ -25,12 +25,10 @@
"@polymer/polymer": "^3.3.0",
"@webcomponents/shadycss": "^1.9.2",
"@webcomponents/webcomponentsjs": "^1.3.3",
- "es6-promise": "^3.3.1",
"page": "^1.11.5",
"polymer-bridges": "file:../../polymer-bridges/",
"ba-linkify": "file:../../lib/ba-linkify/src/",
- "polymer-resin": "^2.0.1",
- "whatwg-fetch": "^3.0.0"
+ "polymer-resin": "^2.0.1"
},
"license": "Apache-2.0",
"private": true
diff --git a/polygerrit-ui/app/styles/shared-styles.js b/polygerrit-ui/app/styles/shared-styles.js
index f5e048f..3e81761 100644
--- a/polygerrit-ui/app/styles/shared-styles.js
+++ b/polygerrit-ui/app/styles/shared-styles.js
@@ -103,19 +103,19 @@
font-weight: var(--font-weight-normal);
line-height: var(--line-height-small);
}
- h1, .font-h1 {
+ .heading-1 {
font-family: var(--header-font-family);
font-size: var(--font-size-h1);
font-weight: var(--font-weight-h1);
line-height: var(--line-height-h1);
}
- h2, .font-h2 {
+ .heading-2 {
font-family: var(--header-font-family);
font-size: var(--font-size-h2);
font-weight: var(--font-weight-h2);
line-height: var(--line-height-h2);
}
- h3, .font-h3 {
+ .heading-3 {
font-family: var(--header-font-family);
font-size: var(--font-size-h3);
font-weight: var(--font-weight-h3);
diff --git a/polygerrit-ui/app/yarn.lock b/polygerrit-ui/app/yarn.lock
index 821b724..8fb3eea 100644
--- a/polygerrit-ui/app/yarn.lock
+++ b/polygerrit-ui/app/yarn.lock
@@ -328,11 +328,6 @@
"ba-linkify@file:../../lib/ba-linkify/src":
version "1.0.0"
-es6-promise@^3.3.1:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
- integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=
-
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
@@ -362,8 +357,3 @@
dependencies:
"@polymer/polymer" "^3.0.2"
"@webcomponents/webcomponentsjs" "^2.0.3"
-
-whatwg-fetch@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb"
- integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==
diff --git a/tools/bzl/pkg_war.bzl b/tools/bzl/pkg_war.bzl
index c9ac0fe..2b473bc 100644
--- a/tools/bzl/pkg_war.bzl
+++ b/tools/bzl/pkg_war.bzl
@@ -23,6 +23,7 @@
"//lib/bouncycastle:bcprov",
"//lib/bouncycastle:bcpg",
"//lib/log:impl-log4j",
+ "//lib:jgit-ssh-jsch",
"//prolog:gerrit-prolog-common",
"//resources:log4j-config",
]
diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py
index 9915a6e..f360fa5 100755
--- a/tools/eclipse/project.py
+++ b/tools/eclipse/project.py
@@ -181,6 +181,8 @@
classpathentry('src', 'modules/jgit/org.eclipse.jgit.http.server/src')
classpathentry('src', 'modules/jgit/org.eclipse.jgit.http.server/resources')
classpathentry('src', 'modules/jgit/org.eclipse.jgit.junit/src')
+ classpathentry('src', 'modules/jgit/org.eclipse.jgit.ssh.jsch/src')
+ classpathentry('src', 'modules/jgit/org.eclipse.jgit.ssh.jsch/resources')
def classpathentry(kind, path, src=None, out=None, exported=None, excluding=None):
e = doc.createElement('classpathentry')