Merge "restapi/accounts: clarify permission related behaviors"
diff --git a/BUILD b/BUILD
index c48b3b9..084d383 100644
--- a/BUILD
+++ b/BUILD
@@ -56,19 +56,22 @@
API_DEPS = [
"//java/com/google/gerrit/acceptance:framework_deploy.jar",
"//java/com/google/gerrit/acceptance:libframework-lib-src.jar",
- "//java/com/google/gerrit/acceptance:framework-javadoc",
"//java/com/google/gerrit/extensions:extension-api_deploy.jar",
"//java/com/google/gerrit/extensions:libapi-src.jar",
- "//java/com/google/gerrit/extensions:extension-api-javadoc",
"//plugins:plugin-api_deploy.jar",
"//plugins:plugin-api-sources_deploy.jar",
+]
+
+API_JAVADOC_DEPS = [
+ "//java/com/google/gerrit/acceptance:framework-javadoc",
+ "//java/com/google/gerrit/extensions:extension-api-javadoc",
"//plugins:plugin-api-javadoc",
]
genrule2(
name = "api",
testonly = True,
- srcs = API_DEPS,
+ srcs = API_DEPS + API_JAVADOC_DEPS,
outs = ["api.zip"],
cmd = " && ".join([
"cp $(SRCS) $$TMP",
@@ -76,3 +79,15 @@
"zip -qr $$ROOT/$@ .",
]),
)
+
+genrule2(
+ name = "api-skip-javadoc",
+ testonly = True,
+ srcs = API_DEPS,
+ outs = ["api-skip-javadoc.zip"],
+ cmd = " && ".join([
+ "cp $(SRCS) $$TMP",
+ "cd $$TMP",
+ "zip -qr $$ROOT/$@ .",
+ ]),
+)
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 313092f..b1f9a31 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3394,6 +3394,49 @@
config is backwards compatible with what the default was before the config
was added.
+[[event.comment-added.publishPatchSetLevelComment]][event.comment-added.publishPatchSetLevelComment::
++
+Add patch set level comment as event comment. Without this option, patch set
+level comment will not be included in the event comment attribute. Given that
+currently patch set level, file and robot comments are not exposed in the
+`comment-added` event type, those comments will be lost. One particular use
+case is to re-trigger CI build from the change screen by adding a comment with
+specific content, e.g.: `recheck`. Jenkins Gerrit Trigger plugin and Zuul CI
+depend on this feature to trigger change verification.
++
+By default, true.
+
+[[experiments]]
+=== Section experiments
+
+This section covers experimental new features. Gerrit's frontend uses experiments
+to research new behavior. Once the research is done, the experimental feature
+either stays and the experimentation flag gets removed, or the feature as a whole
+gets removed
+
+[[experiments.enabled]]experiments.enabled::
++
+List of experiments that are currently enabled. The release notes contain currently
+available experiments.
++
+We will not remove experiments in stable patch releases. They are likely to be
+removed in the next stable version.
+
+----
+[experiments]
+ enabled = ExperimentKey
+----
+
+[[experiments.disabled]]experiments.disabled::
++
+List of experiments that are currently disabled. The release notes contain currently
+available experiments. This list disables experiments with the given key that are
+either enabled by default or explicitly in the config.
+
+----
+[experiments]
+ disabled = ExperimentKey
+----
[[ldap]]
=== Section ldap
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index c770733..159e2fc 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1007,17 +1007,9 @@
Runtime exceptions generated by the implementors of ChangePluginDefinedInfoFactory
are encapsulated in PluginDefinedInfo objects which are part of SSH/REST query output.
-==== ChangeAttributeFactory
-
-Alternatively, there is also `ChangeAttributeFactory` which takes in one single
-`ChangeData` at a time. `ChangePluginDefinedInfoFactory` should be preferred
-over this as it handles many changes at once which also decreases the round-trip
-time for queries resulting in performance increase for bulk queries.
-
-Implementors of the `ChangePluginDefinedInfoFactory` and `ChangeAttributeFactory`
-interfaces should check whether they need to contribute to the
-link:#change-etag-computation[change ETag computation] to prevent callers using
-ETags from potentially seeing outdated plugin attributes.
+Implementors of the `ChangePluginDefinedInfoFactory` interface should check whether
+they need to contribute to the link:#change-etag-computation[change ETag computation]
+to prevent callers using ETags from potentially seeing outdated plugin attributes.
[[simple-configuration]]
== Simple Configuration in `gerrit.config`
@@ -2255,7 +2247,7 @@
@Override
public WebLinkInfo getPatchSetWebLink(String projectName, String commit,
- String subject, String branchName) {
+ String commitMessage, String branchName) {
return new WebLinkInfo(name,
imageUrl,
String.format(placeHolderUrlProjectCommit, project, commit),
@@ -2470,6 +2462,32 @@
Macros that start with `\` such as `\@KEEP@` will render as `@KEEP@`
even if there is an expansion for `KEEP` in the future.
+Documentation should typically contain the following content:
+
+[width="100%",options="header"]
+|===================================================
+|File | Content
+|`README.md` | Home page of the plugin when browsing its source code on Git
+|`LICENSE` | Open-source license
+|`resources/Documentation/about.md` | Overview of the plugin and its purpose
+|`resources/Documentation/config.md` | Plugin configuration settings and sample configs
+|`resources/Documentation/build.md` | How to build the plugin
+|`resources/Documentation/cmd-<command>.md` | SSH commands
+|`resources/Documentation/rest-api-<api>.md` | REST API
+|`resources/Documentation/servlet-<servlet>.md` | HTTP Servlets
+|===================================================
+
+The documentation under resources/Documentation may contain macro that
+will be included and expanded by Gerrit once the plugin is loaded.
+
+The files in the root directory are not included in the plugin package
+and must not have any macro for expansion. It may also collect
+additional information that would make the plugin more discoverable, such as
+a more user-friendly description of its use-cases.
+
+The documentation can also include images that can help understanding more
+visually how the plugin can interact with the other Gerrit components.
+
[[auto-index]]
=== Automatic Index
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index cdf576c..3f0c751 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -15,9 +15,9 @@
--
The change input link:#change-input[ChangeInput] entity must be provided in the
-request body. Allowed values for `branch` are refs/heads/*,
-refs/meta/dashboards/*, refs/meta/config or HEAD. The request would fail with
-`400 Bad Request` if any other `branch` is specified.
+request body. It is not allowed to create changes on refs/tags/* or Gerrit
+internal refs such as refs/changes/*, refs/meta/external-ids/*, refs/users/*,
+etc.. and the request would fail with `400 Bad Request` in this case.
To create a change the calling user must be allowed to
link:access-control.html#category_push_review[upload to code review].
@@ -152,6 +152,12 @@
The `S` or `start` query parameter can be supplied to skip a number
of changes from the list.
+Administrators can use the `skip-visibility` query parameter to skip visibility filtering.
+This can be used to ensure that no changes are missed e.g. when querying for changes which
+need to be reindexed. Without this parameter query results the user has no permission to read
+are filtered out. REST requests with the skip-visibility option are rejected when the current
+user doesn't have the ADMINISTRATE_SERVER capability.
+
Clients are allowed to specify more than one query by setting the `q`
parameter multiple times. In this case the result is an array of
arrays, one per query in the same order the queries were given in.
@@ -2046,7 +2052,7 @@
comments for each path are sorted by patch set number. Each comment has
the `patch_set` and `author` fields set.
-If the `enable_context` request parameter is set to true, the comment entries
+If the `enable-context` request parameter is set to true, the comment entries
will contain a list of link:#context-line[ContextLine] containing the lines of
the source file where the comment was written.
@@ -6693,7 +6699,7 @@
this comment applies.
|`context_lines` |optional|
A list of link:#context-line[ContextLine] containing the lines of the source
-file where the comment was written. Available only if the "enable_context"
+file where the comment was written. Available only if the "enable-context"
parameter (see link:#list-change-comments[List Change Comments]) is set.
|===========================
diff --git a/WORKSPACE b/WORKSPACE
index fd36850..b204e8d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -45,9 +45,11 @@
load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig")
# Creates a default toolchain config for RBE.
-# Use this as is if you are using the rbe_ubuntu16_04 container,
-# otherwise refer to RBE docs.
-rbe_autoconfig(name = "rbe_default")
+rbe_autoconfig(
+ name = "rbe_jdk11",
+ java_home = "/usr/lib/jvm/11.29.3-ca-jdk11.0.2/reduced",
+ use_checked_in_confs = "Force",
+)
http_archive(
name = "com_google_protobuf",
@@ -795,26 +797,30 @@
sha1 = "fd369423346b2f1525c413e33f8cf95b09c92cbd",
)
-# Note that all of the following org.apache.httpcomponents have newer versions,
-# but 4.4.1 is the only version that is available for all of them.
-HTTPCOMP_VERS = "4.4.1"
+# Base the following org.apache.httpcomponents versions on what
+# elasticsearch-rest-client explicitly depends on, except for
+# commons-codec (non-http) which is not necessary yet. Note that
+# below httpcore version(s) differs from the HTTPCOMP_VERS range,
+# upstream: that specific dependency has no HTTPCOMP_VERS version
+# equivalent currently.
+HTTPCOMP_VERS = "4.5.2"
maven_jar(
name = "fluent-hc",
artifact = "org.apache.httpcomponents:fluent-hc:" + HTTPCOMP_VERS,
- sha1 = "96fb842b68a44cc640c661186828b60590c71261",
+ sha1 = "7bfdfa49de6d720ad3c8cedb6a5238eec564dfed",
)
maven_jar(
name = "httpclient",
artifact = "org.apache.httpcomponents:httpclient:" + HTTPCOMP_VERS,
- sha1 = "016d0bc512222f1253ee6b64d389c84e22f697f0",
+ sha1 = "733db77aa8d9b2d68015189df76ab06304406e50",
)
maven_jar(
name = "httpcore",
- artifact = "org.apache.httpcomponents:httpcore:" + HTTPCOMP_VERS,
- sha1 = "f5aa318bda4c6c8d688c9d00b90681dcd82ce636",
+ artifact = "org.apache.httpcomponents:httpcore:4.4.4",
+ sha1 = "b31526a230871fbe285fbcbe2813f9c0839ae9b0",
)
# Test-only dependencies below.
diff --git a/contrib/reindex/.flake8 b/contrib/reindex/.flake8
new file mode 100644
index 0000000..151557f
--- /dev/null
+++ b/contrib/reindex/.flake8
@@ -0,0 +1,9 @@
+[flake8]
+max-line-length=100
+ignore=
+ # E203 whitespace before ':'
+ E203,
+ # W503: Line break before binary operator
+ W503,
+ # W504: Line break after binary operator
+ W504
diff --git a/contrib/reindex/.gitignore b/contrib/reindex/.gitignore
new file mode 100644
index 0000000..fd8c78f
--- /dev/null
+++ b/contrib/reindex/.gitignore
@@ -0,0 +1 @@
+changes-to-reindex.list
diff --git a/contrib/reindex/Pipfile b/contrib/reindex/Pipfile
new file mode 100644
index 0000000..21ffd90
--- /dev/null
+++ b/contrib/reindex/Pipfile
@@ -0,0 +1,19 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+pygerrit2 = "*"
+requests = "*"
+tqdm = "*"
+
+[dev-packages]
+flake8 = "*"
+black = "*"
+
+[requires]
+python_version = "3.9"
+
+[pipenv]
+allow_prereleases = true
diff --git a/contrib/reindex/Pipfile.lock b/contrib/reindex/Pipfile.lock
new file mode 100644
index 0000000..bb7cc2d
--- /dev/null
+++ b/contrib/reindex/Pipfile.lock
@@ -0,0 +1,248 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "37be5a74a22d0e084ebfe168bfdcd7bcaa87ad7b42be66b1d9fbff5e936ebe72"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.9"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "certifi": {
+ "hashes": [
+ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
+ "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
+ ],
+ "version": "==2020.12.5"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
+ "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==4.0.0"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
+ "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.10"
+ },
+ "pbr": {
+ "hashes": [
+ "sha256:5fad80b613c402d5b7df7bd84812548b2a61e9977387a80a5fc5c396492b13c9",
+ "sha256:b236cde0ac9a6aedd5e3c34517b423cd4fd97ef723849da6b0d2231142d89c00"
+ ],
+ "markers": "python_version >= '2.6'",
+ "version": "==5.5.1"
+ },
+ "pygerrit2": {
+ "hashes": [
+ "sha256:d12cff5cc514dd61281d997ea86771e7f818030c3d2ef230b25bb14dae7d3f86"
+ ],
+ "index": "pypi",
+ "version": "==2.0.14"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
+ "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
+ ],
+ "index": "pypi",
+ "version": "==2.25.1"
+ },
+ "tqdm": {
+ "hashes": [
+ "sha256:38b658a3e4ecf9b4f6f8ff75ca16221ae3378b2e175d846b6b33ea3a20852cf5",
+ "sha256:d4f413aecb61c9779888c64ddf0c62910ad56dcbe857d8922bb505d4dbff0df1"
+ ],
+ "index": "pypi",
+ "version": "==4.54.1"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08",
+ "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
+ "version": "==1.26.2"
+ }
+ },
+ "develop": {
+ "appdirs": {
+ "hashes": [
+ "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41",
+ "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"
+ ],
+ "version": "==1.4.4"
+ },
+ "black": {
+ "hashes": [
+ "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"
+ ],
+ "index": "pypi",
+ "version": "==20.8b1"
+ },
+ "click": {
+ "hashes": [
+ "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
+ "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==7.1.2"
+ },
+ "flake8": {
+ "hashes": [
+ "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839",
+ "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"
+ ],
+ "index": "pypi",
+ "version": "==3.8.4"
+ },
+ "mccabe": {
+ "hashes": [
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
+ ],
+ "version": "==0.6.1"
+ },
+ "mypy-extensions": {
+ "hashes": [
+ "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
+ "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"
+ ],
+ "version": "==0.4.3"
+ },
+ "pathspec": {
+ "hashes": [
+ "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd",
+ "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"
+ ],
+ "version": "==0.8.1"
+ },
+ "pycodestyle": {
+ "hashes": [
+ "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
+ "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.6.0"
+ },
+ "pyflakes": {
+ "hashes": [
+ "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
+ "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.2.0"
+ },
+ "regex": {
+ "hashes": [
+ "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538",
+ "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4",
+ "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc",
+ "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa",
+ "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444",
+ "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1",
+ "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af",
+ "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8",
+ "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9",
+ "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88",
+ "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba",
+ "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364",
+ "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e",
+ "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7",
+ "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0",
+ "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31",
+ "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683",
+ "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee",
+ "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b",
+ "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884",
+ "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c",
+ "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e",
+ "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562",
+ "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85",
+ "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c",
+ "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6",
+ "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d",
+ "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b",
+ "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70",
+ "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b",
+ "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b",
+ "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f",
+ "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0",
+ "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5",
+ "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5",
+ "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f",
+ "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e",
+ "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512",
+ "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d",
+ "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917",
+ "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"
+ ],
+ "version": "==2020.11.13"
+ },
+ "toml": {
+ "hashes": [
+ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+ "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
+ ],
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==0.10.2"
+ },
+ "typed-ast": {
+ "hashes": [
+ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
+ "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
+ "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
+ "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
+ "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
+ "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
+ "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
+ "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
+ "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
+ "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
+ "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
+ "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
+ "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
+ "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
+ "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
+ "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
+ "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
+ "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
+ "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
+ "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
+ "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
+ "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
+ "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
+ "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
+ "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
+ "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
+ "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
+ "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
+ "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
+ "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ ],
+ "version": "==1.4.1"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
+ "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
+ "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
+ ],
+ "version": "==3.7.4.3"
+ }
+ }
+}
diff --git a/contrib/reindex/README.md b/contrib/reindex/README.md
new file mode 100644
index 0000000..acb9588
--- /dev/null
+++ b/contrib/reindex/README.md
@@ -0,0 +1,63 @@
+# Incremental reindexing during upgrade of large gerrit site
+
+In order to shorten the downtime needed to reindex changes during a
+Gerrit upgrade the following strategy can be used:
+
+- index preparation
+ - create a full consistent backup
+ - note down the timestamp when the backup was created (backup-time)
+ - create a complete copy of the production system from the backup
+ - upgrade this copy to the new Gerrit version
+ - online reindex this copy
+- upgrade of the production system
+ - make system unavailable so that users can't reach it anymore
+ e.g. by changing port numbers (downtime starts)
+ - take a full backup
+ - run
+
+ ``` bash
+ ./reindex.py -u gerrit-url -s backup-time
+ ```
+
+ to write the list of changes which have been created or modified
+ since the backup for the index preparation was created to a file
+ "changes-to-reindex.list"
+ - upgrade the production system to the new gerrit version skipping
+ reindexing
+ - copy the bulk of the new index from the copy system to the
+ production system
+ - run
+
+ ``` bash
+ ./reindex.py -u gerrit-url
+ ```
+
+ this reindexes all changes which have been created or modified after
+ the backup was taken reading these changes from the file
+ "changes-to-reindex.list"
+ - smoketest the system
+ - make the production system available to the users again
+ (downtime ends)
+
+## Online help
+
+For help on all available options run
+
+``` bash
+./reindex -h
+```
+
+## Python environment
+
+Prerequisites:
+
+- python 3.9
+- pipenv
+
+Install virtual python environment and run the script
+
+``` bash
+pipenv sync
+pipenv shell
+./reindex <options>
+```
diff --git a/contrib/reindex/reindex.py b/contrib/reindex/reindex.py
new file mode 100755
index 0000000..266f5ec
--- /dev/null
+++ b/contrib/reindex/reindex.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+from argparse import ArgumentParser, RawTextHelpFormatter
+from itertools import islice
+import getpass
+import logging
+import os
+
+from pygerrit2 import GerritRestAPI, HTTPBasicAuth, HTTPBasicAuthFromNetrc
+from tqdm import tqdm
+
+EPILOG = """\
+To query the list of changes which have been created or modified since the
+given timestamp and write them to a file "changes-to-reindex.list" run
+$ ./reindex.py -u gerrit-url -s timestamp
+
+To reindex the list of changes in file "changes-to-reindex.list" run
+$ ./reindex.py -u gerrit-url
+"""
+
+
+def _parse_options():
+ parser = ArgumentParser(
+ formatter_class=RawTextHelpFormatter,
+ epilog=EPILOG,
+ )
+ parser.add_argument(
+ "-u",
+ "--url",
+ dest="url",
+ help="gerrit url",
+ )
+ parser.add_argument(
+ "-s",
+ "--since",
+ dest="time",
+ help=(
+ "changes modified after the given 'TIME', inclusive. Must be in the\n"
+ "format '2006-01-02[ 15:04:05[.890][ -0700]]', omitting the time defaults\n"
+ "to 00:00:00 and omitting the timezone defaults to UTC."
+ ),
+ )
+ parser.add_argument(
+ "-f",
+ "--file",
+ default="changes-to-reindex.list",
+ dest="file",
+ help=(
+ "file path to store list of changes if --since is given,\n"
+ "otherwise file path to read list of changes from"
+ ),
+ )
+ parser.add_argument(
+ "-c",
+ "--chunk",
+ default=100,
+ dest="chunksize",
+ help="chunk size defining how many changes are reindexed per request",
+ type=int,
+ )
+ parser.add_argument(
+ "--cert",
+ dest="cert",
+ type=str,
+ help="path to file containing custom ca certificates to trust",
+ )
+ parser.add_argument(
+ "-v",
+ "--verbose",
+ dest="verbose",
+ action="store_true",
+ help="verbose debugging output",
+ )
+ parser.add_argument(
+ "-n",
+ "--netrc",
+ default=True,
+ dest="netrc",
+ action="store_true",
+ help=(
+ "read credentials from .netrc, default to environment variables\n"
+ "USERNAME and PASSWORD, otherwise prompt for credentials interactively"
+ ),
+ )
+ return parser.parse_args()
+
+
+def _chunker(iterable, chunksize):
+ it = map(lambda s: s.strip(), iterable)
+ while True:
+ chunk = list(islice(it, chunksize))
+ if not chunk:
+ return
+ yield chunk
+
+
+class Reindexer:
+ """Class for reindexing Gerrit changes"""
+
+ def __init__(self):
+ self.options = _parse_options()
+ self._init_logger()
+ credentials = self._authenticate()
+ if self.options.cert:
+ certs = os.path.expanduser(self.options.cert)
+ self.api = GerritRestAPI(
+ url=self.options.url, auth=credentials, verify=certs
+ )
+ else:
+ self.api = GerritRestAPI(url=self.options.url, auth=credentials)
+
+ def _init_logger(self):
+ self.logger = logging.getLogger("Reindexer")
+ self.logger.setLevel(logging.DEBUG)
+ h = logging.StreamHandler()
+ if self.options.verbose:
+ h.setLevel(logging.DEBUG)
+ else:
+ h.setLevel(logging.INFO)
+ formatter = logging.Formatter("%(message)s")
+ h.setFormatter(formatter)
+ self.logger.addHandler(h)
+
+ def _authenticate(self):
+ username = password = None
+ if self.options.netrc:
+ auth = HTTPBasicAuthFromNetrc(url=self.options.url)
+ username = auth.username
+ password = auth.password
+ if not username:
+ username = os.environ.get("USERNAME")
+ if not password:
+ password = os.environ.get("PASSWORD")
+ while not username:
+ username = input("user: ")
+ while not password:
+ password = getpass.getpass("password: ")
+ auth = HTTPBasicAuth(username, password)
+ return auth
+
+ def _query(self):
+ start = 0
+ more_changes = True
+ while more_changes:
+ query = f"since:{self.options.time}&start={start}&skip-visibility"
+ for change in self.api.get(f"changes/?q={query}"):
+ more_changes = change.get("_more_changes") is not None
+ start += 1
+ yield change.get("_number")
+ break
+
+ def _query_to_file(self):
+ self.logger.debug(
+ f"writing changes since {self.options.time} to file {self.options.file}:"
+ )
+ with open(self.options.file, "w") as output:
+ for id in self._query():
+ self.logger.debug(id)
+ output.write(f"{id}\n")
+
+ def _reindex_chunk(self, chunk):
+ self.logger.debug(f"indexing {chunk}")
+ response = self.api.post(
+ "/config/server/index.changes",
+ chunk,
+ )
+ self.logger.debug(f"response: {response}")
+
+ def _reindex(self):
+ self.logger.debug(f"indexing changes from file {self.options.file}")
+ with open(self.options.file, "r") as f:
+ with tqdm(unit="changes", desc="Indexed") as pbar:
+ for chunk in _chunker(f, self.options.chunksize):
+ self._reindex_chunk(chunk)
+ pbar.update(len(chunk))
+
+ def execute(self):
+ if self.options.time:
+ self._query_to_file()
+ else:
+ self._reindex()
+
+
+def main():
+ reindexer = Reindexer()
+ reindexer.execute()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/java/com/google/gerrit/acceptance/AbstractPluginFieldsTest.java b/java/com/google/gerrit/acceptance/AbstractPluginFieldsTest.java
index a91bc49..29dc6a3 100644
--- a/java/com/google/gerrit/acceptance/AbstractPluginFieldsTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractPluginFieldsTest.java
@@ -30,7 +30,6 @@
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.DynamicOptions.DynamicBean;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.change.ChangePluginDefinedInfoFactory;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.restapi.change.GetChange;
@@ -40,7 +39,6 @@
import com.google.gson.reflect.TypeToken;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
-import com.google.inject.Module;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -86,21 +84,6 @@
}
}
- protected static class NullAttributeModule extends AbstractModule {
- @Override
- public void configure() {
- DynamicSet.bind(binder(), ChangeAttributeFactory.class).toInstance((cd, bp, p) -> null);
- }
- }
-
- protected static class SimpleAttributeModule extends AbstractModule {
- @Override
- public void configure() {
- DynamicSet.bind(binder(), ChangeAttributeFactory.class)
- .toInstance((cd, bp, p) -> new MyInfo("change " + cd.getId()));
- }
- }
-
protected static class PluginDefinedSimpleAttributeModule extends AbstractModule {
@Override
public void configure() {
@@ -170,21 +153,6 @@
private String opt;
}
- protected static class OptionAttributeModule extends AbstractModule {
- @Override
- public void configure() {
- DynamicSet.bind(binder(), ChangeAttributeFactory.class)
- .toInstance(
- (cd, bp, p) -> {
- MyOptions opts = (MyOptions) bp.getDynamicBean(p);
- return opts != null ? new MyInfo("opt " + opts.opt) : null;
- });
- bind(DynamicBean.class).annotatedWith(Exports.named(Query.class)).to(MyOptions.class);
- bind(DynamicBean.class).annotatedWith(Exports.named(QueryChanges.class)).to(MyOptions.class);
- bind(DynamicBean.class).annotatedWith(Exports.named(GetChange.class)).to(MyOptions.class);
- }
- }
-
public static class BulkAttributeFactoryWithOption implements ChangePluginDefinedInfoFactory {
protected MyOptions opts;
@@ -211,33 +179,6 @@
}
}
- protected void getChangeWithNullAttribute(PluginInfoGetter getter) throws Exception {
- Change.Id id = createChange().getChange().getId();
- assertThat(getter.call(id)).isNull();
-
- try (AutoCloseable ignored = installPlugin("my-plugin", NullAttributeModule.class)) {
- assertThat(getter.call(id)).isNull();
- }
-
- assertThat(getter.call(id)).isNull();
- }
-
- protected void getChangeWithSimpleAttribute(PluginInfoGetter getter) throws Exception {
- getChangeWithSimpleAttribute(getter, SimpleAttributeModule.class);
- }
-
- protected void getChangeWithSimpleAttribute(
- PluginInfoGetter getter, Class<? extends Module> moduleClass) throws Exception {
- Change.Id id = createChange().getChange().getId();
- assertThat(getter.call(id)).isNull();
-
- try (AutoCloseable ignored = installPlugin("my-plugin", moduleClass)) {
- assertThat(getter.call(id)).containsExactly(new MyInfo("my-plugin", "change " + id));
- }
-
- assertThat(getter.call(id)).isNull();
- }
-
protected void getSingleChangeWithPluginDefinedBulkAttribute(BulkPluginInfoGetterWithId getter)
throws Exception {
Change.Id id = createChange().getChange().getId();
@@ -298,30 +239,6 @@
assertThat(pluginInfos.get(changeWithInfo)).isNull();
}
- protected void getMultipleChangesWithPluginDefinedBulkAndChangeAttributes(
- BulkPluginInfoGetter getter) throws Exception {
- Change.Id id1 = createChange().getChange().getId();
- Change.Id id2 = createChange().getChange().getId();
-
- Map<Change.Id, List<PluginDefinedInfo>> pluginInfos = getter.call();
- assertThat(pluginInfos.get(id1)).isNull();
- assertThat(pluginInfos.get(id2)).isNull();
-
- try (AutoCloseable ignored =
- installPlugin("my-plugin-1", PluginDefinedSimpleAttributeModule.class);
- AutoCloseable ignored1 = installPlugin("my-plugin-2", SimpleAttributeModule.class)) {
- pluginInfos = getter.call();
- assertThat(pluginInfos.get(id1)).contains(new MyInfo("my-plugin-1", "change " + id1));
- assertThat(pluginInfos.get(id1)).contains(new MyInfo("my-plugin-2", "change " + id1));
- assertThat(pluginInfos.get(id2)).contains(new MyInfo("my-plugin-1", "change " + id2));
- assertThat(pluginInfos.get(id2)).contains(new MyInfo("my-plugin-2", "change " + id2));
- }
-
- pluginInfos = getter.call();
- assertThat(pluginInfos.get(id1)).isNull();
- assertThat(pluginInfos.get(id2)).isNull();
- }
-
protected void getMultipleChangesWithPluginDefinedBulkAttributeInSingleCall(
BulkPluginInfoGetter getter) throws Exception {
Change.Id id1 = createChange().getChange().getId();
@@ -345,22 +262,6 @@
assertThat(pluginInfos.get(id2)).isNull();
}
- protected void getChangeWithOption(
- PluginInfoGetter getterWithoutOptions, PluginInfoGetterWithOptions getterWithOptions)
- throws Exception {
- Change.Id id = createChange().getChange().getId();
- assertThat(getterWithoutOptions.call(id)).isNull();
-
- try (AutoCloseable ignored = installPlugin("my-plugin", OptionAttributeModule.class)) {
- assertThat(getterWithoutOptions.call(id))
- .containsExactly(new MyInfo("my-plugin", "opt null"));
- assertThat(getterWithOptions.call(id, ImmutableListMultimap.of("my-plugin--opt", "foo")))
- .containsExactly(new MyInfo("my-plugin", "opt foo"));
- }
-
- assertThat(getterWithoutOptions.call(id)).isNull();
- }
-
protected void getChangeWithPluginDefinedBulkAttributeOption(
BulkPluginInfoGetterWithId getterWithoutOptions,
BulkPluginInfoGetterWithIdAndOptions getterWithOptions)
@@ -455,11 +356,6 @@
}
@FunctionalInterface
- protected interface PluginInfoGetter {
- List<PluginDefinedInfo> call(Change.Id id) throws Exception;
- }
-
- @FunctionalInterface
protected interface BulkPluginInfoGetter {
Map<Change.Id, List<PluginDefinedInfo>> call() throws Exception;
}
@@ -474,10 +370,4 @@
Map<Change.Id, List<PluginDefinedInfo>> call(
Change.Id id, ImmutableListMultimap<String, String> pluginOptions) throws Exception;
}
-
- @FunctionalInterface
- protected interface PluginInfoGetterWithOptions {
- List<PluginDefinedInfo> call(Change.Id id, ImmutableListMultimap<String, String> pluginOptions)
- throws Exception;
- }
}
diff --git a/java/com/google/gerrit/acceptance/PushOneCommit.java b/java/com/google/gerrit/acceptance/PushOneCommit.java
index afd451a..4215255 100644
--- a/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -43,8 +43,12 @@
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.api.TagCommand;
+import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
+import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
@@ -277,6 +281,19 @@
return this;
}
+ public PushOneCommit addSymlink(String path, String target) throws Exception {
+ RevBlob blobId = testRepo.blob(target);
+ commitBuilder.edit(
+ new PathEdit(path) {
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ent.setFileMode(FileMode.SYMLINK);
+ ent.setObjectId(blobId);
+ }
+ });
+ return this;
+ }
+
public Result to(String ref) throws Exception {
for (Map.Entry<String, String> e : files.entrySet()) {
commitBuilder.add(e.getKey(), e.getValue());
diff --git a/java/com/google/gerrit/entities/RefNames.java b/java/com/google/gerrit/entities/RefNames.java
index f18c122..522c60a 100644
--- a/java/com/google/gerrit/entities/RefNames.java
+++ b/java/com/google/gerrit/entities/RefNames.java
@@ -14,6 +14,7 @@
package com.google.gerrit.entities;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.UsedAt;
/** Constants and utilities for Gerrit-specific ref names. */
@@ -105,6 +106,26 @@
/** A change starred by a user */
public static final String REFS_STARRED_CHANGES = "refs/starred-changes/";
+ /**
+ * List of refs managed by Gerrit. Covers all Gerrit internal refs.
+ *
+ * <p><b>Caution</b> Any ref not in this list will be served if the user was granted a READ
+ * permission on it using Gerrit's permission model.
+ */
+ public static final ImmutableList<String> GERRIT_REFS =
+ ImmutableList.of(
+ REFS_CHANGES,
+ REFS_EXTERNAL_IDS,
+ REFS_CACHE_AUTOMERGE,
+ REFS_DRAFT_COMMENTS,
+ REFS_DELETED_GROUPS,
+ REFS_SEQUENCES,
+ REFS_GROUPS,
+ REFS_GROUPNAMES,
+ REFS_USERS,
+ REFS_STARRED_CHANGES,
+ REFS_REJECT_COMMITS);
+
public static String fullName(String ref) {
return (ref.startsWith(REFS) || ref.equals(HEAD)) ? ref : REFS_HEADS + ref;
}
@@ -306,21 +327,11 @@
* <p>Any ref for which this method evaluates to true will be served to users who have the {@code
* ACCESS_DATABASE} capability.
*
- * <p><b>Caution</b>Any ref not in this list will be served if the user was granted a READ
+ * <p><b>Caution</b> Any ref not in this list will be served if the user was granted a READ
* permission on it using Gerrit's permission model.
*/
public static boolean isGerritRef(String ref) {
- return ref.startsWith(REFS_CHANGES)
- || ref.startsWith(REFS_EXTERNAL_IDS)
- || ref.startsWith(REFS_CACHE_AUTOMERGE)
- || ref.startsWith(REFS_DRAFT_COMMENTS)
- || ref.startsWith(REFS_DELETED_GROUPS)
- || ref.startsWith(REFS_SEQUENCES)
- || ref.startsWith(REFS_GROUPS)
- || ref.startsWith(REFS_GROUPNAMES)
- || ref.startsWith(REFS_USERS)
- || ref.startsWith(REFS_STARRED_CHANGES)
- || ref.startsWith(REFS_REJECT_COMMITS);
+ return GERRIT_REFS.stream().anyMatch(internalRef -> ref.startsWith(internalRef));
}
static Integer parseShardedRefPart(String name) {
diff --git a/java/com/google/gerrit/extensions/api/changes/ReviewInput.java b/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
index 7ecc0a6..fd445b6 100644
--- a/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
+++ b/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
@@ -21,9 +21,11 @@
import com.google.gerrit.extensions.common.FixSuggestionInfo;
import com.google.gerrit.extensions.restapi.DefaultInput;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/** Input passed to {@code POST /changes/[id]/revisions/[id]/review}. */
public class ReviewInput {
@@ -117,6 +119,15 @@
return this;
}
+ public ReviewInput patchSetLevelComment(String message) {
+ Objects.requireNonNull(message);
+ CommentInput comment = new CommentInput();
+ comment.message = message;
+ // TODO(davido): Because of cyclic dependency, we cannot use here Patch.PATCHSET_LEVEL constant
+ comments = Collections.singletonMap("/PATCHSET_LEVEL", Collections.singletonList(comment));
+ return this;
+ }
+
public ReviewInput label(String name, short value) {
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException();
diff --git a/java/com/google/gerrit/extensions/webui/ParentWebLink.java b/java/com/google/gerrit/extensions/webui/ParentWebLink.java
index 2176e78..9f2bc6e 100644
--- a/java/com/google/gerrit/extensions/webui/ParentWebLink.java
+++ b/java/com/google/gerrit/extensions/webui/ParentWebLink.java
@@ -32,11 +32,11 @@
*
* @param projectName name of the project
* @param commit commit sha1 of the parent revision
- * @param subject first line of the commit message
+ * @param commitMessage the commit messsage of the change
* @param branchName target branch of the change
* @return WebLinkInfo that links to parent commit in external service, null if there should be no
* link.
*/
WebLinkInfo getParentWebLink(
- String projectName, String commit, String subject, String branchName);
+ String projectName, String commit, String commitMessage, String branchName);
}
diff --git a/java/com/google/gerrit/extensions/webui/PatchSetWebLink.java b/java/com/google/gerrit/extensions/webui/PatchSetWebLink.java
index b8ba5c4..0e8e28e 100644
--- a/java/com/google/gerrit/extensions/webui/PatchSetWebLink.java
+++ b/java/com/google/gerrit/extensions/webui/PatchSetWebLink.java
@@ -32,11 +32,11 @@
*
* @param projectName name of the project
* @param commit commit of the patch set
- * @param subject first line of the commit message
+ * @param commitMessage the commit message of the change
* @param branchName target branch of the change
* @return WebLinkInfo that links to patch set in external service, null if there should be no
* link.
*/
WebLinkInfo getPatchSetWebLink(
- String projectName, String commit, String subject, String branchName);
+ String projectName, String commit, String commitMessage, String branchName);
}
diff --git a/java/com/google/gerrit/httpd/HttpLogoutServlet.java b/java/com/google/gerrit/httpd/HttpLogoutServlet.java
index 1eaaba3..b56f973 100644
--- a/java/com/google/gerrit/httpd/HttpLogoutServlet.java
+++ b/java/com/google/gerrit/httpd/HttpLogoutServlet.java
@@ -73,11 +73,10 @@
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
-
- final String sid = webSession.get().getSessionId();
- final CurrentUser currentUser = webSession.get().getUser();
- final String what = "sign out";
- final long when = TimeUtil.nowMs();
+ String sid = webSession.get().getSessionId();
+ CurrentUser currentUser = webSession.get().getUser();
+ String what = "sign out";
+ long when = TimeUtil.nowMs();
try {
doLogout(req, rsp);
diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
index 77d02c1..46dde41 100644
--- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
+++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
@@ -20,6 +20,7 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
@@ -37,15 +38,21 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
+import org.eclipse.jgit.lib.Config;
/** Helper for generating parts of {@code index.html}. */
@UsedAt(Project.GOOGLE)
public class IndexHtmlUtil {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+ static final ImmutableSet<String> DEFAULT_EXPERIMENTS =
+ ImmutableSet.of(
+ "UiFeature__patchset_comments", "UiFeature__patchset_choice_for_comment_links");
+
private static final Gson GSON = OutputFormat.JSON_COMPACT.newGson();
/**
* Returns both static and dynamic parameters of {@code index.html}. The result is to be used when
@@ -53,6 +60,7 @@
*/
public static ImmutableMap<String, Object> templateData(
GerritApi gerritApi,
+ Config gerritServerConfig,
String canonicalURL,
String cdnPath,
String faviconPath,
@@ -66,7 +74,13 @@
canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer))
.putAll(dynamicTemplateData(gerritApi, requestedURL));
- Set<String> enabledExperiments = experimentData(urlParameterMap);
+ Set<String> enabledExperiments = new HashSet<>();
+ Arrays.stream(gerritServerConfig.getStringList("experiments", null, "enabled"))
+ .forEach(enabledExperiments::add);
+ DEFAULT_EXPERIMENTS.forEach(enabledExperiments::add);
+ Arrays.stream(gerritServerConfig.getStringList("experiments", null, "disabled"))
+ .forEach(enabledExperiments::remove);
+ experimentData(urlParameterMap).forEach(enabledExperiments::add);
if (!enabledExperiments.isEmpty()) {
data.put("enabledExperiments", serializeObject(GSON, enabledExperiments).toString());
}
diff --git a/java/com/google/gerrit/httpd/raw/IndexServlet.java b/java/com/google/gerrit/httpd/raw/IndexServlet.java
index 97d2270..b2bdf7c 100644
--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
+++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
@@ -34,6 +34,7 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jgit.lib.Config;
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@@ -42,6 +43,7 @@
@Nullable private final String cdnPath;
@Nullable private final String faviconPath;
private final GerritApi gerritApi;
+ private final Config gerritServerConfig;
private final SoySauce soySauce;
private final Function<String, SanitizedContent> urlOrdainer;
@@ -49,11 +51,13 @@
@Nullable String canonicalUrl,
@Nullable String cdnPath,
@Nullable String faviconPath,
- GerritApi gerritApi) {
+ GerritApi gerritApi,
+ Config gerritServerConfig) {
this.canonicalUrl = canonicalUrl;
this.cdnPath = cdnPath;
this.faviconPath = faviconPath;
this.gerritApi = gerritApi;
+ this.gerritServerConfig = gerritServerConfig;
this.soySauce =
SoyFileSet.builder()
.add(Resources.getResource("com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy"))
@@ -74,7 +78,14 @@
// TODO(hiesel): Remove URL ordainer as parameter once Soy is consistent
ImmutableMap<String, Object> templateData =
IndexHtmlUtil.templateData(
- gerritApi, canonicalUrl, cdnPath, faviconPath, parameterMap, urlOrdainer, requestUrl);
+ gerritApi,
+ gerritServerConfig,
+ canonicalUrl,
+ cdnPath,
+ faviconPath,
+ parameterMap,
+ urlOrdainer,
+ requestUrl);
renderer = soySauce.renderTemplate("com.google.gerrit.httpd.raw.Index").setData(templateData);
} catch (URISyntaxException | RestApiException e) {
throw new IOException(e);
diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
index 4b2c8a9..66e107b 100644
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -225,7 +225,7 @@
String cdnPath =
options.useDevCdn() ? options.devCdn() : cfg.getString("gerrit", null, "cdnPath");
String faviconPath = cfg.getString("gerrit", null, "faviconPath");
- return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi);
+ return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, cfg);
}
@Provides
diff --git a/java/com/google/gerrit/httpd/restapi/ParameterParser.java b/java/com/google/gerrit/httpd/restapi/ParameterParser.java
index 326cab8..3ab409e 100644
--- a/java/com/google/gerrit/httpd/restapi/ParameterParser.java
+++ b/java/com/google/gerrit/httpd/restapi/ParameterParser.java
@@ -43,6 +43,7 @@
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashSet;
@@ -153,6 +154,12 @@
this.parserFactory = pf;
}
+ /**
+ * Parses query parameters ({@code in}) into annotated option fields of {@code param}.
+ *
+ * @return true if parsing was successful. Requesting help is considered failure and returns
+ * false.
+ */
<T> boolean parse(
T param,
DynamicOptions pluginOptions,
@@ -160,6 +167,10 @@
HttpServletRequest req,
HttpServletResponse res)
throws IOException {
+ if (param.getClass().getAnnotation(Singleton.class) != null) {
+ // Command-line parsing mutates the object, so we can't have options on @Singleton.
+ return true;
+ }
CmdLineParser clp = parserFactory.create(param);
pluginOptions.setBean(param);
pluginOptions.startLifecycleListeners();
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index e9c0136..894757b 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -39,7 +39,6 @@
import com.google.gerrit.server.account.externalids.ExternalIdModule;
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeKindCacheImpl;
import com.google.gerrit.server.change.MergeabilityCacheImpl;
@@ -116,8 +115,6 @@
bind(new TypeLiteral<List<CommentLinkInfo>>() {})
.toProvider(CommentLinkProvider.class)
.in(SINGLETON);
- bind(new TypeLiteral<DynamicSet<ChangeAttributeFactory>>() {})
- .toInstance(DynamicSet.emptySet());
bind(new TypeLiteral<DynamicMap<RestView<CommitResource>>>() {})
.toInstance(DynamicMap.emptyMap());
bind(String.class)
diff --git a/java/com/google/gerrit/server/CurrentUser.java b/java/com/google/gerrit/server/CurrentUser.java
index c85c389..afbc74e 100644
--- a/java/com/google/gerrit/server/CurrentUser.java
+++ b/java/com/google/gerrit/server/CurrentUser.java
@@ -130,6 +130,14 @@
}
/**
+ * Returns all email addresses associated with this user. For {@link AnonymousUser} and other
+ * users that don't represent a person user or service account, this set will be empty.
+ */
+ public ImmutableSet<String> getEmailAddresses() {
+ return ImmutableSet.of();
+ }
+
+ /**
* Returns all {@link ExternalId.Key}s associated with this user. For {@link AnonymousUser} and
* other users that don't represent a person user or service account, this set will be empty.
*/
diff --git a/java/com/google/gerrit/server/query/change/ExternalUser.java b/java/com/google/gerrit/server/ExternalUser.java
similarity index 79%
rename from java/com/google/gerrit/server/query/change/ExternalUser.java
rename to java/com/google/gerrit/server/ExternalUser.java
index f853a5c..9680f3e 100644
--- a/java/com/google/gerrit/server/query/change/ExternalUser.java
+++ b/java/com/google/gerrit/server/ExternalUser.java
@@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.server.query.change;
+package com.google.gerrit.server;
import static com.google.common.flogger.LazyArgs.lazy;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.externalids.ExternalId;
@@ -38,22 +37,36 @@
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
- ExternalUser create(Collection<ExternalId.Key> externalIdKeys);
+ ExternalUser create(
+ Collection<String> emailAddresses,
+ Collection<ExternalId.Key> externalIdKeys,
+ PropertyMap propertyMap);
}
private final GroupBackend groupBackend;
+ private final ImmutableSet<String> emailAddresses;
private final ImmutableSet<ExternalId.Key> externalIdKeys;
private GroupMembership effectiveGroups;
@Inject
public ExternalUser(
- GroupBackend groupBackend, @Assisted Collection<ExternalId.Key> externalIdKeys) {
+ GroupBackend groupBackend,
+ @Assisted Collection<String> emailAddresses,
+ @Assisted Collection<ExternalId.Key> externalIdKeys,
+ @Assisted PropertyMap propertyMap) {
+ super(propertyMap);
this.groupBackend = groupBackend;
+ this.emailAddresses = ImmutableSet.copyOf(emailAddresses);
this.externalIdKeys = ImmutableSet.copyOf(externalIdKeys);
}
@Override
+ public ImmutableSet<String> getEmailAddresses() {
+ return emailAddresses;
+ }
+
+ @Override
public ImmutableSet<ExternalId.Key> getExternalIdKeys() {
return externalIdKeys;
}
diff --git a/java/com/google/gerrit/server/IdentifiedUser.java b/java/com/google/gerrit/server/IdentifiedUser.java
index ca86434..34f0eb5 100644
--- a/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/java/com/google/gerrit/server/IdentifiedUser.java
@@ -382,6 +382,7 @@
return false;
}
+ @Override
public ImmutableSet<String> getEmailAddresses() {
if (!loadedAllEmails) {
validEmails.addAll(realm.getEmailAddresses(this));
diff --git a/java/com/google/gerrit/server/WebLinks.java b/java/com/google/gerrit/server/WebLinks.java
index 47ba325..e66e7f5 100644
--- a/java/com/google/gerrit/server/WebLinks.java
+++ b/java/com/google/gerrit/server/WebLinks.java
@@ -86,29 +86,29 @@
/**
* @param project Project name.
* @param commit SHA1 of commit.
- * @param subject subject of the commit.
+ * @param commitMessage the commit message of the commit.
* @param branchName branch of the commit.
* @return Links for patch sets.
*/
public ImmutableList<WebLinkInfo> getPatchSetLinks(
- Project.NameKey project, String commit, String subject, String branchName) {
+ Project.NameKey project, String commit, String commitMessage, String branchName) {
return filterLinks(
patchSetLinks,
- webLink -> webLink.getPatchSetWebLink(project.get(), commit, subject, branchName));
+ webLink -> webLink.getPatchSetWebLink(project.get(), commit, commitMessage, branchName));
}
/**
* @param project Project name.
* @param revision SHA1 of the parent revision.
- * @param subject subject of the parent revision.
+ * @param commitMessage the commit message of the parent revision.
* @param branchName branch of the revision (and parent revision).
* @return Links for patch sets.
*/
public ImmutableList<WebLinkInfo> getParentLinks(
- Project.NameKey project, String revision, String subject, String branchName) {
+ Project.NameKey project, String revision, String commitMessage, String branchName) {
return filterLinks(
parentLinks,
- webLink -> webLink.getParentWebLink(project.get(), revision, subject, branchName));
+ webLink -> webLink.getParentWebLink(project.get(), revision, commitMessage, branchName));
}
/**
diff --git a/java/com/google/gerrit/server/change/ChangeAttributeFactory.java b/java/com/google/gerrit/server/change/ChangeAttributeFactory.java
deleted file mode 100644
index 663d7aa..0000000
--- a/java/com/google/gerrit/server/change/ChangeAttributeFactory.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2019 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.server.change;
-
-import com.google.gerrit.extensions.common.PluginDefinedInfo;
-import com.google.gerrit.server.DynamicOptions.BeanProvider;
-import com.google.gerrit.server.query.change.ChangeData;
-
-/**
- * Interface for plugins to provide additional fields in {@link
- * com.google.gerrit.extensions.common.ChangeInfo ChangeInfo}.
- *
- * <p>Register a {@code ChangeAttributeFactory} in a plugin {@code Module} like this:
- *
- * <pre>
- * DynamicSet.bind(binder(), ChangeAttributeFactory.class).to(YourClass.class);
- * </pre>
- *
- * <p>See the <a
- * href="https://gerrit-review.googlesource.com/Documentation/dev-plugins.html#query_attributes">plugin
- * developer documentation for more details and examples.
- */
-@Deprecated
-public interface ChangeAttributeFactory {
-
- /**
- * Create a plugin-provided info field.
- *
- * <p>Typically, implementations will subclass {@code PluginDefinedInfo} to add additional fields.
- *
- * @param cd change.
- * @param beanProvider provider of {@code DynamicBean}s, which may be used for reading options.
- * @param plugin plugin name.
- * @return the plugin's special change info.
- */
- PluginDefinedInfo create(ChangeData cd, BeanProvider beanProvider, String plugin);
-}
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index 6ab0c61..02da518 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -158,17 +158,12 @@
}
public ChangeJson create(Iterable<ListChangesOption> options) {
- return factory.create(options, Optional.empty(), Optional.empty());
+ return factory.create(options, Optional.empty());
}
public ChangeJson create(
- Iterable<ListChangesOption> options,
- PluginDefinedAttributesFactory pluginDefinedAttributesFactory,
- PluginDefinedInfosFactory pluginDefinedInfosFactory) {
- return factory.create(
- options,
- Optional.of(pluginDefinedAttributesFactory),
- Optional.of(pluginDefinedInfosFactory));
+ Iterable<ListChangesOption> options, PluginDefinedInfosFactory pluginDefinedInfosFactory) {
+ return factory.create(options, Optional.of(pluginDefinedInfosFactory));
}
public ChangeJson create(ListChangesOption first, ListChangesOption... rest) {
@@ -179,7 +174,6 @@
public interface AssistedFactory {
ChangeJson create(
Iterable<ListChangesOption> options,
- Optional<PluginDefinedAttributesFactory> pluginDefinedAttributesFactory,
Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory);
}
@@ -226,7 +220,6 @@
private final TrackingFooters trackingFooters;
private final Metrics metrics;
private final RevisionJson revisionJson;
- private final Optional<PluginDefinedAttributesFactory> pluginDefinedAttributesFactory;
private final Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory;
private final boolean includeMergeable;
private final boolean lazyLoad;
@@ -251,7 +244,6 @@
RevisionJson.Factory revisionJsonFactory,
@GerritServerConfig Config cfg,
@Assisted Iterable<ListChangesOption> options,
- @Assisted Optional<PluginDefinedAttributesFactory> pluginDefinedAttributesFactory,
@Assisted Optional<PluginDefinedInfosFactory> pluginDefinedInfosFactory) {
this.userProvider = user;
this.changeDataFactory = cdf;
@@ -269,7 +261,6 @@
this.options = Sets.immutableEnumSet(options);
this.includeMergeable = MergeabilityComputationBehavior.fromConfig(cfg).includeInApi();
this.lazyLoad = containsAnyOf(this.options, REQUIRE_LAZY_LOAD);
- this.pluginDefinedAttributesFactory = pluginDefinedAttributesFactory;
this.pluginDefinedInfosFactory = pluginDefinedInfosFactory;
logger.atFine().log("options = %s", options);
@@ -611,17 +602,9 @@
}
setSubmitter(cd, out);
- if (pluginDefinedAttributesFactory.isPresent()) {
- out.plugins = pluginDefinedAttributesFactory.get().create(cd);
- }
if (!pluginInfos.isEmpty()) {
- if (out.plugins == null) {
- out.plugins = pluginInfos;
- } else {
- out.plugins = new ArrayList<>(out.plugins);
- out.plugins.addAll(pluginInfos);
- }
+ out.plugins = pluginInfos;
}
out.revertOf = cd.change().getRevertOf() != null ? cd.change().getRevertOf().get() : null;
out.submissionId = cd.change().getSubmissionId();
diff --git a/java/com/google/gerrit/server/change/PluginDefinedAttributesFactories.java b/java/com/google/gerrit/server/change/PluginDefinedAttributesFactories.java
index b474dab..db21f11 100644
--- a/java/com/google/gerrit/server/change/PluginDefinedAttributesFactories.java
+++ b/java/com/google/gerrit/server/change/PluginDefinedAttributesFactories.java
@@ -14,55 +14,22 @@
package com.google.gerrit.server.change;
-import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.concurrent.TimeUnit.MINUTES;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Change;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.extensions.registration.Extension;
import com.google.gerrit.server.DynamicOptions.BeanProvider;
import com.google.gerrit.server.query.change.ChangeData;
import java.util.Collection;
-import java.util.Objects;
import java.util.stream.Stream;
-/** Static helpers for use by {@link PluginDefinedAttributesFactory} implementations. */
+/** Static helpers for use by {@link PluginDefinedInfosFactory} implementations. */
public class PluginDefinedAttributesFactories {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- @Nullable
- public static ImmutableList<PluginDefinedInfo> createAll(
- ChangeData cd,
- BeanProvider beanProvider,
- Stream<Extension<ChangeAttributeFactory>> attrFactories) {
- ImmutableList<PluginDefinedInfo> result =
- attrFactories
- .map(e -> tryCreate(cd, beanProvider, e.getPluginName(), e.get()))
- .filter(Objects::nonNull)
- .collect(toImmutableList());
- return !result.isEmpty() ? result : null;
- }
-
- @Nullable
- private static PluginDefinedInfo tryCreate(
- ChangeData cd, BeanProvider beanProvider, String plugin, ChangeAttributeFactory attrFactory) {
- PluginDefinedInfo pdi = null;
- try {
- pdi = attrFactory.create(cd, beanProvider, plugin);
- } catch (RuntimeException ex) {
- logger.atWarning().atMostEvery(1, MINUTES).withCause(ex).log(
- "error populating attribute on change %s from plugin %s", cd.getId(), plugin);
- }
- if (pdi != null) {
- pdi.name = plugin;
- }
- return pdi;
- }
-
public static ImmutableListMultimap<Change.Id, PluginDefinedInfo> createAll(
Collection<ChangeData> cds,
BeanProvider beanProvider,
diff --git a/java/com/google/gerrit/server/change/PluginDefinedAttributesFactory.java b/java/com/google/gerrit/server/change/PluginDefinedAttributesFactory.java
deleted file mode 100644
index 08d6ce7..0000000
--- a/java/com/google/gerrit/server/change/PluginDefinedAttributesFactory.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2019 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.server.change;
-
-import com.google.gerrit.extensions.common.PluginDefinedInfo;
-import com.google.gerrit.server.query.change.ChangeData;
-import java.util.List;
-
-public interface PluginDefinedAttributesFactory {
- List<PluginDefinedInfo> create(ChangeData cd);
-}
diff --git a/java/com/google/gerrit/server/change/RevisionJson.java b/java/com/google/gerrit/server/change/RevisionJson.java
index 90caea0..c1c0cfc 100644
--- a/java/com/google/gerrit/server/change/RevisionJson.java
+++ b/java/com/google/gerrit/server/change/RevisionJson.java
@@ -183,7 +183,7 @@
if (addLinks) {
ImmutableList<WebLinkInfo> links =
- webLinks.getPatchSetLinks(project, commit.name(), commit.getShortMessage(), branchName);
+ webLinks.getPatchSetLinks(project, commit.name(), commit.getFullMessage(), branchName);
info.webLinks = links.isEmpty() ? null : links;
}
@@ -194,7 +194,7 @@
i.subject = parent.getShortMessage();
if (addLinks) {
ImmutableList<WebLinkInfo> parentLinks =
- webLinks.getParentLinks(project, parent.name(), parent.getShortMessage(), branchName);
+ webLinks.getParentLinks(project, parent.name(), parent.getFullMessage(), branchName);
i.webLinks = parentLinks.isEmpty() ? null : parentLinks;
}
info.parents.add(i);
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index d131cf5..9308662 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -81,6 +81,7 @@
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.ExceptionHook;
import com.google.gerrit.server.ExceptionHookImpl;
+import com.google.gerrit.server.ExternalUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.RequestListener;
import com.google.gerrit.server.TraceRequestListener;
@@ -105,7 +106,6 @@
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.change.AbandonOp;
import com.google.gerrit.server.change.AccountPatchReviewStore;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.change.ChangeETagComputation;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.change.ChangeJson;
@@ -179,7 +179,6 @@
import com.google.gerrit.server.query.change.ChangeIsVisibleToPredicate;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ConflictsCacheImpl;
-import com.google.gerrit.server.query.change.ExternalUser;
import com.google.gerrit.server.quota.QuotaEnforcer;
import com.google.gerrit.server.restapi.change.OnPostReview;
import com.google.gerrit.server.restapi.change.SuggestReviewers;
@@ -441,7 +440,6 @@
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeOperatorFactory.class);
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeHasOperandFactory.class);
DynamicMap.mapOf(binder(), ChangeQueryBuilder.ChangeIsOperandFactory.class);
- DynamicSet.setOf(binder(), ChangeAttributeFactory.class);
DynamicSet.setOf(binder(), ChangePluginDefinedInfoFactory.class);
install(new GitwebConfig.LegacyModule(cfg));
diff --git a/java/com/google/gerrit/server/config/GitwebConfig.java b/java/com/google/gerrit/server/config/GitwebConfig.java
index 3340a52..8214f03 100644
--- a/java/com/google/gerrit/server/config/GitwebConfig.java
+++ b/java/com/google/gerrit/server/config/GitwebConfig.java
@@ -328,9 +328,9 @@
@Override
public WebLinkInfo getPatchSetWebLink(
- String projectName, String commit, String subject, String branchName) {
+ String projectName, String commit, String commitMessage, String branchName) {
if (revision != null) {
- // subject and branchName are not needed, hence not used.
+ // commitMessage and branchName are not needed, hence not used.
return link(
revision
.replace("project", encode(projectName))
@@ -342,9 +342,9 @@
@Override
public WebLinkInfo getParentWebLink(
- String projectName, String commit, String subject, String branchName) {
+ String projectName, String commit, String commitMessage, String branchName) {
// For Gitweb treat parent revision links the same as patch set links
- return getPatchSetWebLink(projectName, commit, subject, branchName);
+ return getPatchSetWebLink(projectName, commit, commitMessage, branchName);
}
@Override
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index fb89240..4c90ef9 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -2692,12 +2692,10 @@
private void readChangesForReplace() {
try (TraceTimer traceTimer = newTimer("readChangesForReplace")) {
- Collection<ChangeNotes> allNotes =
- notesFactory.createUsingIndexLookup(
- replaceByChange.values().stream().map(r -> r.ontoChange).collect(toList()));
- for (ChangeNotes notes : allNotes) {
- replaceByChange.get(notes.getChangeId()).notes = notes;
- }
+ replaceByChange.values().stream()
+ .map(r -> r.ontoChange)
+ .map(id -> notesFactory.create(project.getNameKey(), id))
+ .forEach(notes -> replaceByChange.get(notes.getChangeId()).notes = notes);
}
}
diff --git a/java/com/google/gerrit/server/group/SystemGroupBackend.java b/java/com/google/gerrit/server/group/SystemGroupBackend.java
index dfb42ff..5d50d22 100644
--- a/java/com/google/gerrit/server/group/SystemGroupBackend.java
+++ b/java/com/google/gerrit/server/group/SystemGroupBackend.java
@@ -25,6 +25,7 @@
import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.ExternalUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.StartupCheck;
import com.google.gerrit.server.StartupException;
@@ -34,7 +35,6 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.query.change.ExternalUser;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index e8f1fe1..b816264 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -138,9 +138,8 @@
}
/**
- * Create change notes based on a {@link com.google.gerrit.entities.Change.Id}. This requires
- * using the Change index and should only be used when {@link
- * com.google.gerrit.entities.Project.NameKey} and the numeric change ID are not available.
+ * Create change notes based on a {@link Change.Id}. This requires using the Change index and
+ * should only be used when {@link Project.NameKey} and the numeric change ID are not available.
*/
public ChangeNotes createCheckedUsingIndexLookup(Change.Id changeId) {
InternalChangeQuery query = queryProvider.get().noFields();
@@ -156,9 +155,9 @@
}
/**
- * Create change notes based on a list of {@link com.google.gerrit.entities.Change.Id}s. This
- * requires using the Change index and should only be used when {@link
- * com.google.gerrit.entities.Project.NameKey} and the numeric change ID are not available.
+ * Create change notes based on a list of {@link Change.Id}s. This requires using the Change
+ * index and should only be used when {@link Project.NameKey} and the numeric change ID are not
+ * available.
*/
public List<ChangeNotes> createUsingIndexLookup(Collection<Change.Id> changeIds) {
List<ChangeNotes> notes = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/patch/DiffNotAvailableException.java b/java/com/google/gerrit/server/patch/DiffNotAvailableException.java
index 34e1577..e75adec 100644
--- a/java/com/google/gerrit/server/patch/DiffNotAvailableException.java
+++ b/java/com/google/gerrit/server/patch/DiffNotAvailableException.java
@@ -25,4 +25,8 @@
public DiffNotAvailableException(Throwable cause) {
super(cause);
}
+
+ public DiffNotAvailableException(String message) {
+ super(message);
+ }
}
diff --git a/java/com/google/gerrit/server/patch/DiffUtil.java b/java/com/google/gerrit/server/patch/DiffUtil.java
index 9198666..1e88f9f 100644
--- a/java/com/google/gerrit/server/patch/DiffUtil.java
+++ b/java/com/google/gerrit/server/patch/DiffUtil.java
@@ -64,6 +64,16 @@
|| haveCommonParent(commitA, commitB);
}
+ public static int stringSize(String str) {
+ if (str != null) {
+ // each character in the string occupies 2 bytes. Ignoring the fixed overhead for the string
+ // (length, offset and hash code) since they are negligible and do not affect the comparison
+ // of 2 strings.
+ return str.length() * 2;
+ }
+ return 0;
+ }
+
private static boolean isRootOrMergeCommit(RevCommit commit) {
return commit.getParentCount() != 1;
}
diff --git a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
index 5aa31ec..2ac3f5e 100644
--- a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
+++ b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.patch.diff;
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
+
import com.google.auto.value.AutoValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
@@ -103,14 +105,4 @@
.build();
}
}
-
- private static int stringSize(String str) {
- if (str != null) {
- // each character in the string occupies 2 bytes. Ignoring the fixed overhead for the string
- // (length, offset and hash code) since they are negligible and do not
- // affect the comparison of 2 strings
- return str.length() * 2;
- }
- return 0;
- }
}
diff --git a/java/com/google/gerrit/server/patch/filediff/AllDiffsEvaluator.java b/java/com/google/gerrit/server/patch/filediff/AllDiffsEvaluator.java
new file mode 100644
index 0000000..12decc3
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/AllDiffsEvaluator.java
@@ -0,0 +1,218 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import static org.eclipse.jgit.lib.Constants.EMPTY_TREE_ID;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+import com.google.gerrit.server.patch.DiffUtil;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiff;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCache;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheKey;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * A helper class that computes the four {@link GitFileDiff}s for a list of {@link
+ * FileDiffCacheKey}s:
+ *
+ * <ul>
+ * <li>old commit vs. new commit
+ * <li>old parent vs. old commit
+ * <li>new parent vs. new commit
+ * <li>old parent vs. new parent
+ * </ul>
+ *
+ * The four {@link GitFileDiff} are stored in the entity class {@link AllFileGitDiffs}. We use these
+ * diffs to identify the edits due to rebase using the {@link EditTransformer} class.
+ */
+class AllDiffsEvaluator {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private final RevWalk rw;
+ private final GitFileDiffCache gitCache;
+
+ interface Factory {
+ AllDiffsEvaluator create(RevWalk rw);
+ }
+
+ @Inject
+ private AllDiffsEvaluator(GitFileDiffCache gitCache, @Assisted RevWalk rw) {
+ this.gitCache = gitCache;
+ this.rw = rw;
+ }
+
+ Map<AugmentedFileDiffCacheKey, AllFileGitDiffs> execute(
+ List<AugmentedFileDiffCacheKey> augmentedKeys) throws DiffNotAvailableException {
+ ImmutableMap.Builder<AugmentedFileDiffCacheKey, AllFileGitDiffs> keyToAllDiffs =
+ ImmutableMap.builderWithExpectedSize(augmentedKeys.size());
+
+ List<AugmentedFileDiffCacheKey> keysWithRebaseEdits =
+ augmentedKeys.stream().filter(k -> !k.ignoreRebase()).collect(Collectors.toList());
+
+ // TODO(ghareeb): as an enhancement, you can batch these calls as follows.
+ // First batch: "old commit vs. new commit" and "new parent vs. new commit"
+ // Second batch: "old parent vs. old commit" and "old parent vs. new parent"
+
+ Map<FileDiffCacheKey, GitDiffEntity> mainDiffs =
+ computeGitFileDiffs(
+ createGitKeys(
+ augmentedKeys,
+ k -> k.key().oldCommit(),
+ k -> k.key().newCommit(),
+ k -> k.key().newFilePath()));
+
+ Map<FileDiffCacheKey, GitDiffEntity> oldVsParentDiffs =
+ computeGitFileDiffs(
+ createGitKeys(
+ keysWithRebaseEdits,
+ k -> k.oldParentId().get(), // oldParent is set for keysWithRebaseEdits
+ k -> k.key().oldCommit(),
+ k -> mainDiffs.get(k.key()).gitDiff().oldPath().orElse(null)));
+
+ Map<FileDiffCacheKey, GitDiffEntity> newVsParentDiffs =
+ computeGitFileDiffs(
+ createGitKeys(
+ keysWithRebaseEdits,
+ k -> k.newParentId().get(), // newParent is set for keysWithRebaseEdits
+ k -> k.key().newCommit(),
+ k -> k.key().newFilePath()));
+
+ Map<FileDiffCacheKey, GitDiffEntity> parentsDiffs =
+ computeGitFileDiffs(
+ createGitKeys(
+ keysWithRebaseEdits,
+ k -> k.oldParentId().get(),
+ k -> k.newParentId().get(),
+ k -> {
+ GitFileDiff newVsParDiff = newVsParentDiffs.get(k.key()).gitDiff();
+ // TODO(ghareeb): Follow up on replacing key.newFilePath as a fallback.
+ // If the file was added between newParent and newCommit, we actually wouldn't
+ // need to have to determine the oldParent vs. newParent diff as nothing in
+ // that file could be an edit due to rebase anymore. Only if the returned diff
+ // is empty, the oldParent vs. newParent diff becomes relevant again (e.g. to
+ // identify a file deletion which was due to rebase. Check if the structure
+ // can be improved to make this clearer. Can we maybe even skip the diff in
+ // the first situation described?
+ return newVsParDiff.oldPath().orElse(k.key().newFilePath());
+ }));
+
+ for (AugmentedFileDiffCacheKey augmentedKey : augmentedKeys) {
+ FileDiffCacheKey key = augmentedKey.key();
+ AllFileGitDiffs.Builder builder =
+ AllFileGitDiffs.builder().augmentedKey(augmentedKey).mainDiff(mainDiffs.get(key));
+
+ if (augmentedKey.ignoreRebase()) {
+ keyToAllDiffs.put(augmentedKey, builder.build());
+ continue;
+ }
+
+ if (oldVsParentDiffs.containsKey(key) && !oldVsParentDiffs.get(key).gitDiff().isEmpty()) {
+ builder.oldVsParentDiff(Optional.of(oldVsParentDiffs.get(key)));
+ }
+
+ if (newVsParentDiffs.containsKey(key) && !newVsParentDiffs.get(key).gitDiff().isEmpty()) {
+ builder.newVsParentDiff(Optional.of(newVsParentDiffs.get(key)));
+ }
+
+ if (parentsDiffs.containsKey(key) && !parentsDiffs.get(key).gitDiff().isEmpty()) {
+ builder.parentVsParentDiff(Optional.of(parentsDiffs.get(key)));
+ }
+
+ keyToAllDiffs.put(augmentedKey, builder.build());
+ }
+ return keyToAllDiffs.build();
+ }
+
+ /**
+ * Computes the git diff for the git keys of the input map {@code keys} parameter. The computation
+ * uses the underlying {@link GitFileDiffCache}.
+ */
+ private Map<FileDiffCacheKey, GitDiffEntity> computeGitFileDiffs(
+ Map<FileDiffCacheKey, GitFileDiffCacheKey> keys) throws DiffNotAvailableException {
+ ImmutableMap.Builder<FileDiffCacheKey, GitDiffEntity> result =
+ ImmutableMap.builderWithExpectedSize(keys.size());
+ ImmutableMap<GitFileDiffCacheKey, GitFileDiff> gitDiffs = gitCache.getAll(keys.values());
+ for (FileDiffCacheKey key : keys.keySet()) {
+ GitFileDiffCacheKey gitKey = keys.get(key);
+ GitFileDiff gitFileDiff = gitDiffs.get(gitKey);
+ result.put(key, GitDiffEntity.create(gitKey, gitFileDiff));
+ }
+ return result.build();
+ }
+
+ /**
+ * Convert a list of {@link AugmentedFileDiffCacheKey} to their corresponding {@link
+ * GitFileDiffCacheKey} which can be used to call the underlying {@link GitFileDiffCache}.
+ *
+ * @param keys a list of input {@link AugmentedFileDiffCacheKey}s.
+ * @param aCommitFn a function to compute the aCommit that will be used in the git diff.
+ * @param bCommitFn a function to compute the bCommit that will be used in the git diff.
+ * @param newPathFn a function to compute the new path of the git key.
+ * @return a map of the input {@link FileDiffCacheKey} to the {@link GitFileDiffCacheKey}.
+ */
+ private Map<FileDiffCacheKey, GitFileDiffCacheKey> createGitKeys(
+ List<AugmentedFileDiffCacheKey> keys,
+ Function<AugmentedFileDiffCacheKey, ObjectId> aCommitFn,
+ Function<AugmentedFileDiffCacheKey, ObjectId> bCommitFn,
+ Function<AugmentedFileDiffCacheKey, String> newPathFn) {
+ Map<FileDiffCacheKey, GitFileDiffCacheKey> result = new HashMap<>();
+ for (AugmentedFileDiffCacheKey key : keys) {
+ try {
+ String path = newPathFn.apply(key);
+ if (path != null) {
+ result.put(
+ key.key(),
+ createGitKey(key.key(), aCommitFn.apply(key), bCommitFn.apply(key), path, rw));
+ }
+ } catch (IOException e) {
+ // TODO(ghareeb): This implies that the output keys may not have the same size as the input.
+ // Check the caller's code path about the correctness of the computation in this case. If
+ // errors are rare, it may be better to throw an exception and fail the whole computation.
+ logger.atWarning().log("Failed to compute the git key for key %s: %s", key, e.getMessage());
+ }
+ }
+ return result;
+ }
+
+ /** Returns the {@link GitFileDiffCacheKey} for the {@code key} input parameter. */
+ private GitFileDiffCacheKey createGitKey(
+ FileDiffCacheKey key, ObjectId aCommit, ObjectId bCommit, String pathNew, RevWalk rw)
+ throws IOException {
+ ObjectId oldTreeId =
+ aCommit.equals(EMPTY_TREE_ID) ? EMPTY_TREE_ID : DiffUtil.getTreeId(rw, aCommit);
+ ObjectId newTreeId = DiffUtil.getTreeId(rw, bCommit);
+ return GitFileDiffCacheKey.builder()
+ .project(key.project())
+ .oldTree(oldTreeId)
+ .newTree(newTreeId)
+ .newFilePath(pathNew == null ? key.newFilePath() : pathNew)
+ .renameScore(key.renameScore())
+ .diffAlgorithm(key.diffAlgorithm())
+ .whitespace(key.whitespace())
+ .build();
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/AllFileGitDiffs.java b/java/com/google/gerrit/server/patch/filediff/AllFileGitDiffs.java
new file mode 100644
index 0000000..3b1886f
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/AllFileGitDiffs.java
@@ -0,0 +1,61 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.auto.value.AutoValue;
+import java.util.Optional;
+
+/**
+ * An entity containing the four git diffs for a {@link FileDiffCacheKey}:
+ *
+ * <ol>
+ * <li>The old vs. new commit
+ * <li>The old commit vs. the old parent
+ * <li>The new commit vs. the new parent
+ * <li>The old parent vs. the new parent
+ * </ol>
+ */
+@AutoValue
+abstract class AllFileGitDiffs {
+ abstract AugmentedFileDiffCacheKey augmentedKey();
+
+ abstract GitDiffEntity mainDiff();
+
+ abstract Optional<GitDiffEntity> oldVsParentDiff();
+
+ abstract Optional<GitDiffEntity> newVsParentDiff();
+
+ abstract Optional<GitDiffEntity> parentVsParentDiff();
+
+ static AllFileGitDiffs.Builder builder() {
+ return new AutoValue_AllFileGitDiffs.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder augmentedKey(AugmentedFileDiffCacheKey value);
+
+ public abstract Builder mainDiff(GitDiffEntity value);
+
+ public abstract Builder oldVsParentDiff(Optional<GitDiffEntity> value);
+
+ public abstract Builder newVsParentDiff(Optional<GitDiffEntity> value);
+
+ public abstract Builder parentVsParentDiff(Optional<GitDiffEntity> value);
+
+ public abstract AllFileGitDiffs build();
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/AugmentedFileDiffCacheKey.java b/java/com/google/gerrit/server/patch/filediff/AugmentedFileDiffCacheKey.java
new file mode 100644
index 0000000..8e40452
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/AugmentedFileDiffCacheKey.java
@@ -0,0 +1,52 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.auto.value.AutoValue;
+import java.util.Optional;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * A wrapper entity to the {@link FileDiffCacheKey} that also includes the old parent commit ID, the
+ * new parent commit ID and if we should ignore computing the rebase edits for that key.
+ */
+@AutoValue
+abstract class AugmentedFileDiffCacheKey {
+ abstract FileDiffCacheKey key();
+
+ abstract boolean ignoreRebase();
+
+ abstract Optional<ObjectId> oldParentId();
+
+ abstract Optional<ObjectId> newParentId();
+
+ static Builder builder() {
+ return new AutoValue_AugmentedFileDiffCacheKey.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder oldParentId(Optional<ObjectId> value);
+
+ public abstract Builder newParentId(Optional<ObjectId> value);
+
+ public abstract Builder ignoreRebase(boolean value);
+
+ public abstract Builder key(FileDiffCacheKey value);
+
+ public abstract AugmentedFileDiffCacheKey build();
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/Edit.java b/java/com/google/gerrit/server/patch/filediff/Edit.java
index b1b336e..4a698a4 100644
--- a/java/com/google/gerrit/server/patch/filediff/Edit.java
+++ b/java/com/google/gerrit/server/patch/filediff/Edit.java
@@ -32,6 +32,14 @@
jgitEdit.getBeginA(), jgitEdit.getEndA(), jgitEdit.getBeginB(), jgitEdit.getEndB());
}
+ public static org.eclipse.jgit.diff.Edit toJGitEdit(Edit e) {
+ return new org.eclipse.jgit.diff.Edit(e.beginA(), e.endA(), e.beginB(), e.endB());
+ }
+
+ public org.eclipse.jgit.diff.Edit asJGitEdit() {
+ return new org.eclipse.jgit.diff.Edit(beginA(), endA(), beginB(), endB());
+ }
+
/** Start of a region in sequence A. */
public abstract int beginA();
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffCache.java b/java/com/google/gerrit/server/patch/filediff/FileDiffCache.java
new file mode 100644
index 0000000..a9bcf03
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffCache.java
@@ -0,0 +1,45 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+
+/**
+ * This cache computes the git diff for a single file path and adds some extra logic, e.g. for
+ * identifying edits that are due to rebase.
+ */
+public interface FileDiffCache {
+ /**
+ * Returns the file diff for a single file path identified by its key.
+ *
+ * @param key identifies two git commits, a specific file path and other diff parameters.
+ * @return the file diff for a single file path identified by its key.
+ * @throws DiffNotAvailableException if the commit IDs of the key are invalid for this project or
+ * if file contents could not be read.
+ */
+ FileDiffOutput get(FileDiffCacheKey key) throws DiffNotAvailableException;
+
+ /**
+ * Returns the file diff for a collection of file paths identified by their keys.
+ *
+ * @param keys identifying different file paths of different projects.
+ * @return a map of the input keys to their corresponding git file diffs.
+ * @throws DiffNotAvailableException if the diff failed to be evaluated for one or more of the
+ * input keys due to invalid commit IDs or if file contents could not be read.
+ */
+ ImmutableMap<FileDiffCacheKey, FileDiffOutput> getAll(Iterable<FileDiffCacheKey> keys)
+ throws DiffNotAvailableException;
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffCacheImpl.java b/java/com/google/gerrit/server/patch/filediff/FileDiffCacheImpl.java
new file mode 100644
index 0000000..091b02c
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffCacheImpl.java
@@ -0,0 +1,509 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.eclipse.jgit.lib.Constants.EMPTY_TREE_ID;
+
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Streams;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Patch;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
+import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.patch.ComparisonType;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+import com.google.gerrit.server.patch.DiffUtil;
+import com.google.gerrit.server.patch.Text;
+import com.google.gerrit.server.patch.filediff.EditTransformer.ContextAwareEdit;
+import com.google.gerrit.server.patch.gitfilediff.FileHeaderUtil;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiff;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl.DiffAlgorithmFactory;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.name.Named;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.eclipse.jgit.diff.EditList;
+import org.eclipse.jgit.diff.RawText;
+import org.eclipse.jgit.diff.RawTextComparator;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.patch.FileHeader;
+import org.eclipse.jgit.patch.FileHeader.PatchType;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Cache for the single file diff between two commits for a single file path. This cache adds extra
+ * Gerrit logic such as identifying edits due to rebase.
+ *
+ * <p>If the {@link FileDiffCacheKey#oldCommit()} is equal to {@link
+ * org.eclipse.jgit.lib.Constants#EMPTY_TREE_ID}, the git diff will be evaluated against the empty
+ * tree.
+ */
+public class FileDiffCacheImpl implements FileDiffCache {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private static final String DIFF = "gerrit_file_diff";
+
+ private final LoadingCache<FileDiffCacheKey, FileDiffOutput> cache;
+
+ public static Module module() {
+ return new CacheModule() {
+ @Override
+ protected void configure() {
+ bind(FileDiffCache.class).to(FileDiffCacheImpl.class);
+
+ factory(AllDiffsEvaluator.Factory.class);
+
+ persist(DIFF, FileDiffCacheKey.class, FileDiffOutput.class)
+ .maximumWeight(10 << 20)
+ .weigher(FileDiffWeigher.class)
+ .keySerializer(FileDiffCacheKey.Serializer.INSTANCE)
+ .valueSerializer(FileDiffOutput.Serializer.INSTANCE)
+ .loader(FileDiffLoader.class);
+ }
+ };
+ }
+
+ private enum MagicPath {
+ COMMIT,
+ MERGE_LIST
+ }
+
+ @Inject
+ public FileDiffCacheImpl(@Named(DIFF) LoadingCache<FileDiffCacheKey, FileDiffOutput> cache) {
+ this.cache = cache;
+ }
+
+ @Override
+ public FileDiffOutput get(FileDiffCacheKey key) throws DiffNotAvailableException {
+ try {
+ return cache.get(key);
+ } catch (ExecutionException e) {
+ throw new DiffNotAvailableException(e);
+ }
+ }
+
+ @Override
+ public ImmutableMap<FileDiffCacheKey, FileDiffOutput> getAll(Iterable<FileDiffCacheKey> keys)
+ throws DiffNotAvailableException {
+ try {
+ ImmutableMap<FileDiffCacheKey, FileDiffOutput> result = cache.getAll(keys);
+ if (result.size() != Iterables.size(keys)) {
+ throw new DiffNotAvailableException(
+ String.format(
+ "Failed to load the value for all %d keys. Returned "
+ + "map contains only %d values",
+ Iterables.size(keys), result.size()));
+ }
+ return result;
+ } catch (ExecutionException e) {
+ throw new DiffNotAvailableException(e);
+ }
+ }
+
+ static class FileDiffLoader extends CacheLoader<FileDiffCacheKey, FileDiffOutput> {
+ private final GitRepositoryManager repoManager;
+ private final AllDiffsEvaluator.Factory allDiffsEvaluatorFactory;
+
+ @Inject
+ FileDiffLoader(
+ AllDiffsEvaluator.Factory allDiffsEvaluatorFactory, GitRepositoryManager manager) {
+ this.allDiffsEvaluatorFactory = allDiffsEvaluatorFactory;
+ this.repoManager = manager;
+ }
+
+ @Override
+ public FileDiffOutput load(FileDiffCacheKey key) throws IOException, DiffNotAvailableException {
+ return loadAll(ImmutableList.of(key)).get(key);
+ }
+
+ @Override
+ public Map<FileDiffCacheKey, FileDiffOutput> loadAll(Iterable<? extends FileDiffCacheKey> keys)
+ throws DiffNotAvailableException {
+ ImmutableMap.Builder<FileDiffCacheKey, FileDiffOutput> result = ImmutableMap.builder();
+
+ Map<Project.NameKey, List<FileDiffCacheKey>> keysByProject =
+ Streams.stream(keys).distinct().collect(Collectors.groupingBy(FileDiffCacheKey::project));
+
+ for (Project.NameKey project : keysByProject.keySet()) {
+ List<FileDiffCacheKey> fileKeys = new ArrayList<>();
+
+ try (Repository repo = repoManager.openRepository(project);
+ ObjectReader reader = repo.newObjectReader();
+ RevWalk rw = new RevWalk(reader)) {
+
+ for (FileDiffCacheKey key : keysByProject.get(project)) {
+ if (key.newFilePath().equals(Patch.COMMIT_MSG)) {
+ result.put(key, createMagicPathEntry(key, reader, rw, MagicPath.COMMIT));
+ } else if (key.newFilePath().equals(Patch.MERGE_LIST)) {
+ result.put(key, createMagicPathEntry(key, reader, rw, MagicPath.MERGE_LIST));
+ } else {
+ fileKeys.add(key);
+ }
+ }
+ result.putAll(createFileEntries(reader, fileKeys, rw));
+ } catch (IOException e) {
+ logger.atWarning().log("Failed to open the repository %s: %s", project, e.getMessage());
+ }
+ }
+ return result.build();
+ }
+
+ private ComparisonType getComparisonType(RevWalk rw, ObjectId oldCommitId, ObjectId newCommitId)
+ throws IOException {
+ RevCommit oldCommit = DiffUtil.getRevCommit(rw, oldCommitId);
+ RevCommit newCommit = DiffUtil.getRevCommit(rw, newCommitId);
+ for (int i = 0; i < newCommit.getParentCount(); i++) {
+ if (newCommit.getParent(i).equals(oldCommit)) {
+ return ComparisonType.againstParent(i + 1);
+ }
+ }
+ if (newCommit.getParentCount() > 0) {
+ return ComparisonType.againstAutoMerge();
+ }
+ return ComparisonType.againstOtherPatchSet();
+ }
+
+ /**
+ * Creates a {@link FileDiffOutput} entry for the "Commit message" and "Merge list" file paths.
+ */
+ private FileDiffOutput createMagicPathEntry(
+ FileDiffCacheKey key, ObjectReader reader, RevWalk rw, MagicPath magicPath) {
+ try {
+ RawTextComparator cmp = comparatorFor(key.whitespace());
+ ComparisonType comparisonType = getComparisonType(rw, key.oldCommit(), key.newCommit());
+ RevCommit aCommit =
+ comparisonType.isAgainstParentOrAutoMerge()
+ ? null
+ : DiffUtil.getRevCommit(rw, key.oldCommit());
+ RevCommit bCommit = DiffUtil.getRevCommit(rw, key.newCommit());
+ return magicPath == MagicPath.COMMIT
+ ? createCommitEntry(reader, aCommit, bCommit, cmp, key.diffAlgorithm())
+ : createMergeListEntry(
+ reader, aCommit, bCommit, comparisonType, cmp, key.diffAlgorithm());
+ } catch (IOException e) {
+ logger.atWarning().log("Failed to compute commit entry for key " + key);
+ }
+ return FileDiffOutput.empty(key.newFilePath());
+ }
+
+ private static RawTextComparator comparatorFor(Whitespace ws) {
+ switch (ws) {
+ case IGNORE_ALL:
+ return RawTextComparator.WS_IGNORE_ALL;
+
+ case IGNORE_TRAILING:
+ return RawTextComparator.WS_IGNORE_TRAILING;
+
+ case IGNORE_LEADING_AND_TRAILING:
+ return RawTextComparator.WS_IGNORE_CHANGE;
+
+ case IGNORE_NONE:
+ default:
+ return RawTextComparator.DEFAULT;
+ }
+ }
+
+ private FileDiffOutput createCommitEntry(
+ ObjectReader reader,
+ RevCommit oldCommit,
+ RevCommit newCommit,
+ RawTextComparator rawTextComparator,
+ GitFileDiffCacheImpl.DiffAlgorithm diffAlgorithm)
+ throws IOException {
+ Text aText = newCommit != null ? Text.forCommit(reader, newCommit) : Text.EMPTY;
+ Text bText = Text.forCommit(reader, newCommit);
+ return createMagicFileDiffOutput(
+ rawTextComparator, oldCommit, aText, bText, Patch.COMMIT_MSG, diffAlgorithm);
+ }
+
+ private FileDiffOutput createMergeListEntry(
+ ObjectReader reader,
+ RevCommit oldCommit,
+ RevCommit newCommit,
+ ComparisonType comparisonType,
+ RawTextComparator rawTextComparator,
+ GitFileDiffCacheImpl.DiffAlgorithm diffAlgorithm)
+ throws IOException {
+ Text aText =
+ oldCommit != null ? Text.forMergeList(comparisonType, reader, oldCommit) : Text.EMPTY;
+ Text bText = Text.forMergeList(comparisonType, reader, newCommit);
+ return createMagicFileDiffOutput(
+ rawTextComparator, oldCommit, aText, bText, Patch.MERGE_LIST, diffAlgorithm);
+ }
+
+ private static FileDiffOutput createMagicFileDiffOutput(
+ RawTextComparator rawTextComparator,
+ RevCommit aCommit,
+ Text aText,
+ Text bText,
+ String fileName,
+ GitFileDiffCacheImpl.DiffAlgorithm diffAlgorithm) {
+ byte[] rawHdr = getRawHeader(aCommit != null, fileName);
+ byte[] aContent = aText.getContent();
+ byte[] bContent = bText.getContent();
+ long size = bContent.length;
+ long sizeDelta = size - aContent.length;
+ RawText aRawText = new RawText(aContent);
+ RawText bRawText = new RawText(bContent);
+ EditList edits =
+ DiffAlgorithmFactory.create(diffAlgorithm).diff(rawTextComparator, aRawText, bRawText);
+ FileHeader fileHeader = new FileHeader(rawHdr, edits, PatchType.UNIFIED);
+ Patch.ChangeType changeType = FileHeaderUtil.getChangeType(fileHeader);
+ return FileDiffOutput.builder()
+ .oldPath(FileHeaderUtil.getOldPath(fileHeader))
+ .newPath(FileHeaderUtil.getNewPath(fileHeader))
+ .changeType(Optional.of(changeType))
+ .patchType(Optional.of(FileHeaderUtil.getPatchType(fileHeader)))
+ .headerLines(FileHeaderUtil.getHeaderLines(fileHeader))
+ .edits(
+ asTaggedEdits(
+ edits.stream().map(Edit::fromJGitEdit).collect(Collectors.toList()),
+ ImmutableList.of()))
+ .size(size)
+ .sizeDelta(sizeDelta)
+ .build();
+ }
+
+ private static byte[] getRawHeader(boolean hasA, String fileName) {
+ StringBuilder hdr = new StringBuilder();
+ hdr.append("diff --git");
+ if (hasA) {
+ hdr.append(" a/").append(fileName);
+ } else {
+ hdr.append(" ").append(FileHeader.DEV_NULL);
+ }
+ hdr.append(" b/").append(fileName);
+ hdr.append("\n");
+
+ if (hasA) {
+ hdr.append("--- a/").append(fileName).append("\n");
+ } else {
+ hdr.append("--- ").append(FileHeader.DEV_NULL).append("\n");
+ }
+ hdr.append("+++ b/").append(fileName).append("\n");
+ return hdr.toString().getBytes(UTF_8);
+ }
+
+ private Map<FileDiffCacheKey, FileDiffOutput> createFileEntries(
+ ObjectReader reader, List<FileDiffCacheKey> keys, RevWalk rw)
+ throws DiffNotAvailableException, IOException {
+ Map<AugmentedFileDiffCacheKey, AllFileGitDiffs> allFileDiffs =
+ allDiffsEvaluatorFactory.create(rw).execute(wrapKeys(keys, rw));
+
+ Map<FileDiffCacheKey, FileDiffOutput> result = new HashMap<>();
+
+ for (AugmentedFileDiffCacheKey augmentedKey : allFileDiffs.keySet()) {
+ AllFileGitDiffs allDiffs = allFileDiffs.get(augmentedKey);
+
+ FileEdits rebaseFileEdits = FileEdits.empty();
+ if (!augmentedKey.ignoreRebase()) {
+ rebaseFileEdits = computeRebaseEdits(allDiffs);
+ }
+ List<Edit> rebaseEdits = rebaseFileEdits.edits();
+
+ RevTree aTree = rw.parseTree(allDiffs.mainDiff().gitKey().oldTree());
+ RevTree bTree = rw.parseTree(allDiffs.mainDiff().gitKey().newTree());
+ GitFileDiff mainGitDiff = allDiffs.mainDiff().gitDiff();
+
+ Long oldSize =
+ mainGitDiff.oldPath().isPresent()
+ ? new FileSizeEvaluator(reader, aTree)
+ .compute(
+ mainGitDiff.oldId(),
+ mainGitDiff.oldMode().get(),
+ mainGitDiff.oldPath().get())
+ : 0;
+ Long newSize =
+ mainGitDiff.newPath().isPresent()
+ ? new FileSizeEvaluator(reader, bTree)
+ .compute(
+ mainGitDiff.newId(),
+ mainGitDiff.newMode().get(),
+ mainGitDiff.newPath().get())
+ : 0;
+
+ FileDiffOutput fileDiff =
+ FileDiffOutput.builder()
+ .changeType(mainGitDiff.changeType())
+ .patchType(mainGitDiff.patchType())
+ .oldPath(mainGitDiff.oldPath())
+ .newPath(mainGitDiff.newPath())
+ .headerLines(FileHeaderUtil.getHeaderLines(mainGitDiff.fileHeader()))
+ .edits(asTaggedEdits(mainGitDiff.edits(), rebaseEdits))
+ .size(newSize)
+ .sizeDelta(newSize - oldSize)
+ .build();
+
+ result.put(augmentedKey.key(), fileDiff);
+ }
+
+ return result;
+ }
+
+ /**
+ * Convert the list of input keys {@link FileDiffCacheKey} to a list of {@link
+ * AugmentedFileDiffCacheKey} that also include the old and new parent commit IDs, and a boolean
+ * that indicates whether we should include the rebase edits for each key.
+ *
+ * <p>The output list is expected to have the same size of the input list, i.e. we map all keys.
+ */
+ private List<AugmentedFileDiffCacheKey> wrapKeys(List<FileDiffCacheKey> keys, RevWalk rw) {
+ List<AugmentedFileDiffCacheKey> result = new ArrayList<>();
+ for (FileDiffCacheKey key : keys) {
+ if (key.oldCommit().equals(EMPTY_TREE_ID)) {
+ result.add(AugmentedFileDiffCacheKey.builder().key(key).ignoreRebase(true).build());
+ continue;
+ }
+ try {
+ RevCommit oldRevCommit = DiffUtil.getRevCommit(rw, key.oldCommit());
+ RevCommit newRevCommit = DiffUtil.getRevCommit(rw, key.newCommit());
+ if (!DiffUtil.areRelated(oldRevCommit, newRevCommit)) {
+ result.add(
+ AugmentedFileDiffCacheKey.builder()
+ .key(key)
+ .oldParentId(Optional.of(oldRevCommit.getParent(0).getId()))
+ .newParentId(Optional.of(newRevCommit.getParent(0).getId()))
+ .ignoreRebase(false)
+ .build());
+ } else {
+ result.add(AugmentedFileDiffCacheKey.builder().key(key).ignoreRebase(true).build());
+ }
+ } catch (IOException e) {
+ logger.atWarning().log(
+ "Failed to evaluate commits relation for key "
+ + key
+ + ". Skipping this key: "
+ + e.getMessage(),
+ e);
+ result.add(AugmentedFileDiffCacheKey.builder().key(key).ignoreRebase(true).build());
+ }
+ }
+ return result;
+ }
+
+ private static ImmutableList<TaggedEdit> asTaggedEdits(
+ List<Edit> normalEdits, List<Edit> rebaseEdits) {
+ Set<Edit> rebaseEditsSet = new HashSet(rebaseEdits);
+ ImmutableList.Builder<TaggedEdit> result =
+ ImmutableList.builderWithExpectedSize(normalEdits.size());
+ for (Edit e : normalEdits) {
+ result.add(TaggedEdit.create(e, rebaseEditsSet.contains(e)));
+ }
+ return result.build();
+ }
+
+ /**
+ * Computes the subset of edits that are due to rebase between 2 commits.
+ *
+ * <p>The input parameter {@link AllFileGitDiffs#mainDiff} contains all the edits in
+ * consideration. Of those, we identify the edits due to rebase as a function of:
+ *
+ * <ol>
+ * <li>The edits between the old commit and its parent {@link
+ * AllFileGitDiffs#oldVsParentDiff}.
+ * <li>The edits between the new commit and its parent {@link
+ * AllFileGitDiffs#newVsParentDiff}.
+ * <li>The edits between the parents of the old commit and new commits {@link
+ * AllFileGitDiffs#parentVsParentDiff}.
+ * </ol>
+ *
+ * @param diffs an entity containing 4 sets of edits: those between the old and new commit,
+ * between the old and new commits vs. their parents, and between the old and new parents.
+ * @return the list of edits that are due to rebase.
+ */
+ private FileEdits computeRebaseEdits(AllFileGitDiffs diffs) {
+ if (!diffs.parentVsParentDiff().isPresent()) {
+ return FileEdits.empty();
+ }
+
+ GitFileDiff parentVsParentDiff = diffs.parentVsParentDiff().get().gitDiff();
+
+ EditTransformer editTransformer =
+ new EditTransformer(
+ ImmutableList.of(
+ FileEdits.create(
+ parentVsParentDiff.edits().stream()
+ .map(Edit::toJGitEdit)
+ .collect(Collectors.toList()),
+ parentVsParentDiff.oldPath(),
+ parentVsParentDiff.newPath())));
+
+ if (diffs.oldVsParentDiff().isPresent()) {
+ GitFileDiff oldVsParDiff = diffs.oldVsParentDiff().get().gitDiff();
+ editTransformer.transformReferencesOfSideA(
+ ImmutableList.of(
+ FileEdits.create(
+ oldVsParDiff.edits().stream()
+ .map(Edit::toJGitEdit)
+ .collect(Collectors.toList()),
+ oldVsParDiff.oldPath(),
+ oldVsParDiff.newPath())));
+ }
+
+ if (diffs.newVsParentDiff().isPresent()) {
+ GitFileDiff newVsParDiff = diffs.newVsParentDiff().get().gitDiff();
+ editTransformer.transformReferencesOfSideB(
+ ImmutableList.of(
+ FileEdits.create(
+ newVsParDiff.edits().stream()
+ .map(Edit::toJGitEdit)
+ .collect(Collectors.toList()),
+ newVsParDiff.oldPath(),
+ newVsParDiff.newPath())));
+ }
+
+ Multimap<String, ContextAwareEdit> editsPerFilePath = editTransformer.getEditsPerFilePath();
+
+ if (editsPerFilePath.isEmpty()) {
+ return FileEdits.empty();
+ }
+
+ // editsPerFilePath is expected to have a single item representing the file
+ String filePath = editsPerFilePath.keys().iterator().next();
+ Collection<ContextAwareEdit> edits = editsPerFilePath.get(filePath);
+ return FileEdits.create(
+ Streams.stream(edits)
+ .map(ContextAwareEdit::toEdit)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.toList()),
+ edits.iterator().next().getOldFilePath(),
+ edits.iterator().next().getNewFilePath());
+ }
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffCacheKey.java b/java/com/google/gerrit/server/patch/filediff/FileDiffCacheKey.java
new file mode 100644
index 0000000..a478fcf
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffCacheKey.java
@@ -0,0 +1,130 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
+
+import com.google.auto.value.AutoValue;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.Project.NameKey;
+import com.google.gerrit.extensions.client.DiffPreferencesInfo;
+import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.server.cache.proto.Cache.FileDiffKeyProto;
+import com.google.gerrit.server.cache.serialize.CacheSerializer;
+import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl.DiffAlgorithm;
+import org.eclipse.jgit.lib.ObjectId;
+
+/** Cache key for the {@link FileDiffCache}. */
+@AutoValue
+public abstract class FileDiffCacheKey {
+
+ /** A specific git project / repository. */
+ public abstract Project.NameKey project();
+
+ /** The 20 bytes SHA-1 commit ID of the old commit used in the diff. */
+ public abstract ObjectId oldCommit();
+
+ /** The 20 bytes SHA-1 commit ID of the new commit used in the diff. */
+ public abstract ObjectId newCommit();
+
+ /** File path identified by its name. */
+ public abstract String newFilePath();
+
+ /**
+ * Percentage score used to identify a file as a "rename". A special value of -1 means that the
+ * computation will ignore renames and rename detection will be disabled.
+ */
+ public abstract int renameScore();
+
+ /** The diff algorithm that should be used in the computation. */
+ public abstract DiffAlgorithm diffAlgorithm();
+
+ public abstract DiffPreferencesInfo.Whitespace whitespace();
+
+ /** Number of bytes that this entity occupies. */
+ public int weight() {
+ return stringSize(project().get())
+ + 20 * 2 // old and new commits
+ + stringSize(newFilePath())
+ + 4 // renameScore
+ + 4 // diffAlgorithm
+ + 4; // whitespace
+ }
+
+ public static FileDiffCacheKey.Builder builder() {
+ return new AutoValue_FileDiffCacheKey.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract FileDiffCacheKey.Builder project(NameKey value);
+
+ public abstract FileDiffCacheKey.Builder oldCommit(ObjectId value);
+
+ public abstract FileDiffCacheKey.Builder newCommit(ObjectId value);
+
+ public abstract FileDiffCacheKey.Builder newFilePath(String value);
+
+ public abstract FileDiffCacheKey.Builder renameScore(int value);
+
+ public FileDiffCacheKey.Builder disableRenameDetection() {
+ renameScore(-1);
+ return this;
+ }
+
+ public abstract FileDiffCacheKey.Builder diffAlgorithm(DiffAlgorithm value);
+
+ public abstract FileDiffCacheKey.Builder whitespace(Whitespace value);
+
+ public abstract FileDiffCacheKey build();
+ }
+
+ public enum Serializer implements CacheSerializer<FileDiffCacheKey> {
+ INSTANCE;
+
+ @Override
+ public byte[] serialize(FileDiffCacheKey key) {
+ ObjectIdConverter idConverter = ObjectIdConverter.create();
+ return Protos.toByteArray(
+ FileDiffKeyProto.newBuilder()
+ .setProject(key.project().get())
+ .setOldCommit(idConverter.toByteString(key.oldCommit()))
+ .setNewCommit(idConverter.toByteString(key.newCommit()))
+ .setFilePath(key.newFilePath())
+ .setRenameScore(key.renameScore())
+ .setDiffAlgorithm(key.diffAlgorithm().name())
+ .setWhitespace(key.whitespace().name())
+ .build());
+ }
+
+ @Override
+ public FileDiffCacheKey deserialize(byte[] in) {
+ FileDiffKeyProto proto = Protos.parseUnchecked(FileDiffKeyProto.parser(), in);
+ ObjectIdConverter idConverter = ObjectIdConverter.create();
+ return FileDiffCacheKey.builder()
+ .project(Project.nameKey(proto.getProject()))
+ .oldCommit(idConverter.fromByteString(proto.getOldCommit()))
+ .newCommit(idConverter.fromByteString(proto.getNewCommit()))
+ .newFilePath(proto.getFilePath())
+ .renameScore(proto.getRenameScore())
+ .diffAlgorithm(DiffAlgorithm.valueOf(proto.getDiffAlgorithm()))
+ .whitespace(Whitespace.valueOf(proto.getWhitespace()))
+ .build();
+ }
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java b/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java
new file mode 100644
index 0000000..e89f148
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffOutput.java
@@ -0,0 +1,255 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.entities.Patch;
+import com.google.gerrit.entities.Patch.ChangeType;
+import com.google.gerrit.entities.Patch.PatchType;
+import com.google.gerrit.proto.Protos;
+import com.google.gerrit.server.cache.proto.Cache.FileDiffOutputProto;
+import com.google.gerrit.server.cache.serialize.CacheSerializer;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import java.io.Serializable;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/** File diff for a single file path. Produced as output of the {@link FileDiffCache}. */
+@AutoValue
+public abstract class FileDiffOutput implements Serializable {
+
+ /**
+ * The file path at the old commit. Returns an empty Optional if {@link #changeType()} is equal to
+ * {@link ChangeType#ADDED}.
+ */
+ public abstract Optional<String> oldPath();
+
+ /**
+ * The file path at the new commit. Returns an empty optional if {@link #changeType()} is equal to
+ * {@link ChangeType#DELETED}.
+ */
+ public abstract Optional<String> newPath();
+
+ /** The change type of the underlying file, e.g. added, deleted, renamed, etc... */
+ public abstract Optional<Patch.ChangeType> changeType();
+
+ /** The patch type of the underlying file, e.g. unified, binary , etc... */
+ public abstract Optional<Patch.PatchType> patchType();
+
+ /**
+ * A list of strings representation of the header lines of the {@link
+ * org.eclipse.jgit.patch.FileHeader} that is produced as output of the diff.
+ */
+ public abstract ImmutableList<String> headerLines();
+
+ /** The list of edits resulting from the diff hunks of the file. */
+ public abstract ImmutableList<TaggedEdit> edits();
+
+ /** The file size at the new commit. */
+ public abstract long size();
+
+ /** Difference in file size between the old and new commits. */
+ public abstract long sizeDelta();
+
+ /** A boolean indicating if all underlying edits of the file diff are due to rebase. */
+ public boolean allEditsDueToRebase() {
+ return !edits().isEmpty() && edits().stream().allMatch(TaggedEdit::dueToRebase);
+ }
+
+ /** Returns the number of inserted lines for the file diff. */
+ public int insertions() {
+ int ins = 0;
+ for (TaggedEdit e : edits()) {
+ if (!e.dueToRebase()) {
+ ins += e.edit().endB() - e.edit().beginB();
+ }
+ }
+ return ins;
+ }
+
+ /** Returns the number of deleted lines for the file diff. */
+ public int deletions() {
+ int del = 0;
+ for (TaggedEdit e : edits()) {
+ if (!e.dueToRebase()) {
+ del += e.edit().endA() - e.edit().beginA();
+ }
+ }
+ return del;
+ }
+
+ /** Returns an entity representing an unchanged file between two commits. */
+ static FileDiffOutput empty(String filePath) {
+ return builder()
+ .oldPath(Optional.empty())
+ .newPath(Optional.of(filePath))
+ .headerLines(ImmutableList.of())
+ .edits(ImmutableList.of())
+ .size(0)
+ .sizeDelta(0)
+ .build();
+ }
+
+ /** Returns true if this entity represents an unchanged file between two commits. */
+ public boolean isEmpty() {
+ return headerLines().isEmpty() && edits().isEmpty();
+ }
+
+ public static Builder builder() {
+ return new AutoValue_FileDiffOutput.Builder();
+ }
+
+ public int weight() {
+ int result = 0;
+ if (oldPath().isPresent()) {
+ result += stringSize(oldPath().get());
+ }
+ if (newPath().isPresent()) {
+ result += stringSize(newPath().get());
+ }
+ if (changeType().isPresent()) {
+ result += 4;
+ }
+ if (patchType().isPresent()) {
+ result += 4;
+ }
+ result += 4 + 4; // insertions and deletions
+ result += 4 + 4; // size and size delta
+ result += 20 * edits().size(); // each edit is 4 Integers + boolean = 4 * 4 + 4 = 20
+ for (String s : headerLines()) {
+ s += stringSize(s);
+ }
+ return result;
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder oldPath(Optional<String> value);
+
+ public abstract Builder newPath(Optional<String> value);
+
+ public abstract Builder changeType(Optional<ChangeType> value);
+
+ public abstract Builder patchType(Optional<PatchType> value);
+
+ public abstract Builder headerLines(ImmutableList<String> value);
+
+ public abstract Builder edits(ImmutableList<TaggedEdit> value);
+
+ public abstract Builder size(long value);
+
+ public abstract Builder sizeDelta(long value);
+
+ public abstract FileDiffOutput build();
+ }
+
+ public enum Serializer implements CacheSerializer<FileDiffOutput> {
+ INSTANCE;
+
+ private static final FieldDescriptor OLD_PATH_DESCRIPTOR =
+ FileDiffOutputProto.getDescriptor().findFieldByNumber(1);
+
+ private static final FieldDescriptor NEW_PATH_DESCRIPTOR =
+ FileDiffOutputProto.getDescriptor().findFieldByNumber(2);
+
+ private static final FieldDescriptor CHANGE_TYPE_DESCRIPTOR =
+ FileDiffOutputProto.getDescriptor().findFieldByNumber(3);
+
+ private static final FieldDescriptor PATCH_TYPE_DESCRIPTOR =
+ FileDiffOutputProto.getDescriptor().findFieldByNumber(4);
+
+ @Override
+ public byte[] serialize(FileDiffOutput fileDiff) {
+ FileDiffOutputProto.Builder builder =
+ FileDiffOutputProto.newBuilder()
+ .setSize(fileDiff.size())
+ .setSizeDelta(fileDiff.sizeDelta())
+ .addAllHeaderLines(fileDiff.headerLines())
+ .addAllEdits(
+ fileDiff.edits().stream()
+ .map(
+ e ->
+ FileDiffOutputProto.TaggedEdit.newBuilder()
+ .setEdit(
+ FileDiffOutputProto.Edit.newBuilder()
+ .setBeginA(e.edit().beginA())
+ .setEndA(e.edit().endA())
+ .setBeginB(e.edit().beginB())
+ .setEndB(e.edit().endB())
+ .build())
+ .setDueToRebase(e.dueToRebase())
+ .build())
+ .collect(Collectors.toList()));
+
+ if (fileDiff.oldPath().isPresent()) {
+ builder.setOldPath(fileDiff.oldPath().get());
+ }
+
+ if (fileDiff.newPath().isPresent()) {
+ builder.setNewPath(fileDiff.newPath().get());
+ }
+
+ if (fileDiff.changeType().isPresent()) {
+ builder.setChangeType(fileDiff.changeType().get().name());
+ }
+
+ if (fileDiff.patchType().isPresent()) {
+ builder.setPatchType(fileDiff.patchType().get().name());
+ }
+
+ return Protos.toByteArray(builder.build());
+ }
+
+ @Override
+ public FileDiffOutput deserialize(byte[] in) {
+ FileDiffOutputProto proto = Protos.parseUnchecked(FileDiffOutputProto.parser(), in);
+ FileDiffOutput.Builder builder = FileDiffOutput.builder();
+ builder
+ .size(proto.getSize())
+ .sizeDelta(proto.getSizeDelta())
+ .headerLines(proto.getHeaderLinesList().stream().collect(ImmutableList.toImmutableList()))
+ .edits(
+ proto.getEditsList().stream()
+ .map(
+ e ->
+ TaggedEdit.create(
+ Edit.create(
+ e.getEdit().getBeginA(),
+ e.getEdit().getEndA(),
+ e.getEdit().getBeginB(),
+ e.getEdit().getEndB()),
+ e.getDueToRebase()))
+ .collect(ImmutableList.toImmutableList()));
+
+ if (proto.hasField(OLD_PATH_DESCRIPTOR)) {
+ builder.oldPath(Optional.of(proto.getOldPath()));
+ }
+ if (proto.hasField(NEW_PATH_DESCRIPTOR)) {
+ builder.newPath(Optional.of(proto.getNewPath()));
+ }
+ if (proto.hasField(CHANGE_TYPE_DESCRIPTOR)) {
+ builder.changeType(Optional.of(Patch.ChangeType.valueOf(proto.getChangeType())));
+ }
+ if (proto.hasField(PATCH_TYPE_DESCRIPTOR)) {
+ builder.patchType(Optional.of(Patch.PatchType.valueOf(proto.getPatchType())));
+ }
+ return builder.build();
+ }
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileDiffWeigher.java b/java/com/google/gerrit/server/patch/filediff/FileDiffWeigher.java
new file mode 100644
index 0000000..8eda234
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileDiffWeigher.java
@@ -0,0 +1,29 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.common.cache.Weigher;
+
+/**
+ * A weigher for the {@link FileDiffCache} key and value. This is used by the cache backend to
+ * assign weights for cache entries and is used for evictions.
+ */
+public class FileDiffWeigher implements Weigher<FileDiffCacheKey, FileDiffOutput> {
+
+ @Override
+ public int weigh(FileDiffCacheKey key, FileDiffOutput fileDiffOutput) {
+ return key.weight() + fileDiffOutput.weight();
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileEdits.java b/java/com/google/gerrit/server/patch/filediff/FileEdits.java
index c51cc45..376bbc2 100644
--- a/java/com/google/gerrit/server/patch/filediff/FileEdits.java
+++ b/java/com/google/gerrit/server/patch/filediff/FileEdits.java
@@ -22,7 +22,7 @@
import java.util.Optional;
/**
- * An entity class containing the list of edits between 2 commits for a file, and the old and new
+ * An entity class containing the list of edits between two commits for a file, and the old and new
* paths.
*/
@AutoValue
@@ -41,4 +41,8 @@
public abstract Optional<String> oldPath();
public abstract Optional<String> newPath();
+
+ public static FileEdits empty() {
+ return new AutoValue_FileEdits(ImmutableList.of(), Optional.empty(), Optional.empty());
+ }
}
diff --git a/java/com/google/gerrit/server/patch/filediff/FileSizeEvaluator.java b/java/com/google/gerrit/server/patch/filediff/FileSizeEvaluator.java
new file mode 100644
index 0000000..97b55dc
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/FileSizeEvaluator.java
@@ -0,0 +1,95 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
+
+import com.google.common.collect.Iterables;
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.entities.Patch;
+import com.google.gerrit.entities.Patch.FileMode;
+import com.google.gerrit.exceptions.StorageException;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Optional;
+import org.eclipse.jgit.lib.AbbreviatedObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+/** Helper class for computing the size of a file in a given git tree. */
+class FileSizeEvaluator {
+ private final ObjectReader reader;
+ private final RevTree tree;
+
+ FileSizeEvaluator(ObjectReader reader, RevTree tree) {
+ this.reader = reader;
+ this.tree = tree;
+ }
+
+ /**
+ * Computes the file size identified by the {@code path} parameter at the given git tree
+ * identified by {@code gitTreeId}.
+ */
+ long compute(AbbreviatedObjectId gitTreeId, Patch.FileMode mode, String path) throws IOException {
+ if (!isBlob(mode)) {
+ return 0;
+ }
+ ObjectId fileId =
+ toObjectId(reader, gitTreeId).orElseGet(() -> lookupObjectId(reader, path, tree));
+ if (ObjectId.zeroId().equals(fileId)) {
+ return 0;
+ }
+ return reader.getObjectSize(fileId, OBJ_BLOB);
+ }
+
+ private static ObjectId lookupObjectId(ObjectReader reader, String path, RevTree tree) {
+ // This variant is very expensive.
+ try (TreeWalk treeWalk = TreeWalk.forPath(reader, path, tree)) {
+ return treeWalk != null ? treeWalk.getObjectId(0) : ObjectId.zeroId();
+ } catch (IOException e) {
+ throw new StorageException(e);
+ }
+ }
+
+ private static Optional<ObjectId> toObjectId(
+ ObjectReader reader, @Nullable AbbreviatedObjectId abbreviatedId) throws IOException {
+ if (abbreviatedId == null) {
+ // In theory, DiffEntry#getOldId or DiffEntry#getNewId can be null for pure renames or pure
+ // mode changes (e.g. DiffEntry#modify doesn't set the IDs). However, the method we call for
+ // diffs (DiffFormatter#scan) seems to always produce DiffEntries with set IDs, even for pure
+ // renames.
+ return Optional.empty();
+ }
+ if (abbreviatedId.isComplete()) {
+ // With the current JGit version and the method we call for diffs (DiffFormatter#scan),
+ // this
+ // is the only code path taken right now.
+ return Optional.ofNullable(abbreviatedId.toObjectId());
+ }
+ Collection<ObjectId> objectIds = reader.resolve(abbreviatedId);
+ // It seems very unlikely that an ObjectId which was just abbreviated by the diff
+ // computation
+ // now can't be resolved to exactly one ObjectId. The API allows this possibility, though.
+ return objectIds.size() == 1
+ ? Optional.of(Iterables.getOnlyElement(objectIds))
+ : Optional.empty();
+ }
+
+ private static boolean isBlob(Patch.FileMode mode) {
+ return mode.equals(FileMode.REGULAR_FILE) || mode.equals(FileMode.SYMLINK);
+ }
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/GitDiffEntity.java b/java/com/google/gerrit/server/patch/filediff/GitDiffEntity.java
new file mode 100644
index 0000000..2ca8fa6
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/GitDiffEntity.java
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.auto.value.AutoValue;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiff;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheKey;
+
+/** An entity containing a {@link GitFileDiffCacheKey} and its loaded value {@link GitFileDiff}. */
+@AutoValue
+abstract class GitDiffEntity {
+ public static GitDiffEntity create(GitFileDiffCacheKey gitKey, GitFileDiff gitDiff) {
+ return new AutoValue_GitDiffEntity(gitKey, gitDiff);
+ }
+
+ abstract GitFileDiffCacheKey gitKey();
+
+ abstract GitFileDiff gitDiff();
+}
diff --git a/java/com/google/gerrit/server/patch/filediff/TaggedEdit.java b/java/com/google/gerrit/server/patch/filediff/TaggedEdit.java
new file mode 100644
index 0000000..aef2f63
--- /dev/null
+++ b/java/com/google/gerrit/server/patch/filediff/TaggedEdit.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.patch.filediff;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * An entity class encapsulating a JGit {@link Edit} along with extra attributes (e.g. identifying a
+ * rebase edit).
+ */
+@AutoValue
+public abstract class TaggedEdit {
+
+ public static TaggedEdit create(Edit edit, boolean dueToRebase) {
+ return new AutoValue_TaggedEdit(edit, dueToRebase);
+ }
+
+ abstract Edit edit();
+
+ abstract boolean dueToRebase();
+}
diff --git a/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheKey.java b/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheKey.java
index f94f2c9..fb8fce1 100644
--- a/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheKey.java
+++ b/java/com/google/gerrit/server/patch/gitdiff/GitModifiedFilesCacheKey.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.patch.gitdiff;
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
+
import com.google.auto.value.AutoValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
@@ -124,14 +126,4 @@
.build();
}
}
-
- private static int stringSize(String str) {
- if (str != null) {
- // each character in the string occupies 2 bytes. Ignoring the fixed overhead for the string
- // (length, offset and hash code) since they are negligible and do not
- // affect the comparison of 2 strings
- return str.length() * 2;
- }
- return 0;
- }
}
diff --git a/java/com/google/gerrit/server/patch/gitdiff/ModifiedFile.java b/java/com/google/gerrit/server/patch/gitdiff/ModifiedFile.java
index 800bd41..9512094 100644
--- a/java/com/google/gerrit/server/patch/gitdiff/ModifiedFile.java
+++ b/java/com/google/gerrit/server/patch/gitdiff/ModifiedFile.java
@@ -79,10 +79,10 @@
INSTANCE;
private static final FieldDescriptor oldPathDescriptor =
- ModifiedFileProto.getDescriptor().findFieldByName("old_path");
+ ModifiedFileProto.getDescriptor().findFieldByNumber(2);
private static final FieldDescriptor newPathDescriptor =
- ModifiedFileProto.getDescriptor().findFieldByName("new_path");
+ ModifiedFileProto.getDescriptor().findFieldByNumber(3);
@Override
public byte[] serialize(ModifiedFile modifiedFile) {
diff --git a/java/com/google/gerrit/server/patch/gitfilediff/FileHeaderUtil.java b/java/com/google/gerrit/server/patch/gitfilediff/FileHeaderUtil.java
index 8f53751..7454f81 100644
--- a/java/com/google/gerrit/server/patch/gitfilediff/FileHeaderUtil.java
+++ b/java/com/google/gerrit/server/patch/gitfilediff/FileHeaderUtil.java
@@ -16,11 +16,14 @@
import static java.nio.charset.StandardCharsets.UTF_8;
+import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Patch.PatchType;
import java.util.Optional;
import org.eclipse.jgit.patch.CombinedFileHeader;
import org.eclipse.jgit.patch.FileHeader;
+import org.eclipse.jgit.util.IntList;
+import org.eclipse.jgit.util.RawParseUtils;
/** A utility class for the {@link FileHeader} JGit object */
public class FileHeaderUtil {
@@ -37,7 +40,7 @@
*/
private static final int BIN_FILE_MAX_SCAN_LIMIT = 20000;
- /** Converts the {@link FileHeader} parameter ot a String representation. */
+ /** Converts the {@link FileHeader} parameter to a String representation. */
static String toString(FileHeader header) {
return new String(FileHeaderUtil.toByteArray(header), UTF_8);
}
@@ -54,12 +57,37 @@
return buf;
}
+ /** Splits the {@code FileHeader} string to a list of strings, one string per header line. */
+ public static ImmutableList<String> getHeaderLines(FileHeader fileHeader) {
+ String fileHeaderString = toString(fileHeader);
+ return getHeaderLines(fileHeaderString);
+ }
+
+ public static ImmutableList<String> getHeaderLines(String header) {
+ return getHeaderLines(header.getBytes(UTF_8));
+ }
+
+ static ImmutableList<String> getHeaderLines(byte[] header) {
+ final IntList lineStartOffsets = RawParseUtils.lineMap(header, 0, header.length);
+ final ImmutableList.Builder<String> headerLines =
+ ImmutableList.builderWithExpectedSize(lineStartOffsets.size() - 1);
+ for (int i = 1; i < lineStartOffsets.size() - 1; i++) {
+ final int b = lineStartOffsets.get(i);
+ int e = lineStartOffsets.get(i + 1);
+ if (header[e - 1] == '\n') {
+ e--;
+ }
+ headerLines.add(RawParseUtils.decode(UTF_8, header, b, e));
+ }
+ return headerLines.build();
+ }
+
/**
* Returns the old file path associated with the {@link FileHeader}, or empty if the file is
* {@link com.google.gerrit.entities.Patch.ChangeType#ADDED} or {@link
* com.google.gerrit.entities.Patch.ChangeType#REWRITE}.
*/
- static Optional<String> getOldPath(FileHeader header) {
+ public static Optional<String> getOldPath(FileHeader header) {
Patch.ChangeType changeType = getChangeType(header);
switch (changeType) {
case DELETED:
@@ -79,7 +107,7 @@
* Returns the new file path associated with the {@link FileHeader}, or empty if the file is
* {@link com.google.gerrit.entities.Patch.ChangeType#DELETED}.
*/
- static Optional<String> getNewPath(FileHeader header) {
+ public static Optional<String> getNewPath(FileHeader header) {
Patch.ChangeType changeType = getChangeType(header);
switch (changeType) {
case DELETED:
@@ -96,7 +124,7 @@
}
/** Returns the change type associated with the file header. */
- static Patch.ChangeType getChangeType(FileHeader header) {
+ public static Patch.ChangeType getChangeType(FileHeader header) {
// In Gerrit, we define our own entities of the JGit entities, so that we have full control
// over their behaviors (e.g. making sure that these entities are immutable so that we can add
// them as fields of keys / values of persisted caches).
@@ -118,7 +146,7 @@
}
}
- static PatchType getPatchType(FileHeader header) {
+ public static PatchType getPatchType(FileHeader header) {
PatchType patchType;
switch (header.getPatchType()) {
diff --git a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
index bce3d44..6d63243 100644
--- a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
+++ b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiff.java
@@ -15,6 +15,7 @@
package com.google.gerrit.server.patch.gitfilediff;
import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
@@ -167,16 +168,6 @@
return result;
}
- private static int stringSize(String str) {
- if (str != null) {
- // each character in the string occupies two bytes. Ignoring the fixed overhead for the string
- // (length, offset and hash code) since they are negligible and do not affect the comparison
- // of two strings
- return str.length() * 2;
- }
- return 0;
- }
-
public static Builder builder() {
return new AutoValue_GitFileDiff.Builder();
}
@@ -211,22 +202,22 @@
INSTANCE;
private static final FieldDescriptor OLD_PATH_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("old_path");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(3);
private static final FieldDescriptor NEW_PATH_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("new_path");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(4);
private static final FieldDescriptor OLD_MODE_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("old_mode");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(7);
private static final FieldDescriptor NEW_MODE_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("new_mode");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(8);
private static final FieldDescriptor CHANGE_TYPE_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("change_type");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(9);
private static final FieldDescriptor PATCH_TYPE_DESCRIPTOR =
- GitFileDiffProto.getDescriptor().findFieldByName("patch_type");
+ GitFileDiffProto.getDescriptor().findFieldByNumber(10);
@Override
public byte[] serialize(GitFileDiff gitFileDiff) {
diff --git a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiffCacheKey.java b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiffCacheKey.java
index d570ada..f104388 100644
--- a/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiffCacheKey.java
+++ b/java/com/google/gerrit/server/patch/gitfilediff/GitFileDiffCacheKey.java
@@ -14,6 +14,8 @@
package com.google.gerrit.server.patch.gitfilediff;
+import static com.google.gerrit.server.patch.DiffUtil.stringSize;
+
import com.google.auto.value.AutoValue;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
@@ -60,16 +62,6 @@
+ 4; // whitespace
}
- private static int stringSize(String str) {
- if (str != null) {
- // each character in the string occupies 2 bytes. Ignoring the fixed overhead for the string
- // (length, offset and hash code) since they are negligible and do not
- // affect the comparison of 2 strings
- return str.length() * 2;
- }
- return 0;
- }
-
public static Builder builder() {
return new AutoValue_GitFileDiffCacheKey.Builder();
}
diff --git a/java/com/google/gerrit/server/permissions/RefControl.java b/java/com/google/gerrit/server/permissions/RefControl.java
index ad4188f..dd00dca 100644
--- a/java/com/google/gerrit/server/permissions/RefControl.java
+++ b/java/com/google/gerrit/server/permissions/RefControl.java
@@ -619,6 +619,10 @@
private boolean can(RefPermission perm) throws PermissionBackendException {
switch (perm) {
case READ:
+ /* Internal users such as plugin users should be able to read all refs. */
+ if (getUser().isInternalUser()) {
+ return true;
+ }
if (refName.startsWith(Constants.R_TAGS)) {
return isTagVisible();
}
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index e81428c..68a90d2 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -660,7 +660,15 @@
}
if ("submittable".equalsIgnoreCase(value)) {
- return new SubmittablePredicate(SubmitRecord.Status.OK);
+ // SubmittablePredicate will match if *any* of the submit records are OK,
+ // but we need to check that they're *all* OK, so check that none of the
+ // submit records match any of the negative cases. To avoid checking yet
+ // more negative cases for CLOSED and FORCED, instead make sure at least
+ // one submit record is OK.
+ return Predicate.and(
+ new SubmittablePredicate(SubmitRecord.Status.OK),
+ Predicate.not(new SubmittablePredicate(SubmitRecord.Status.NOT_READY)),
+ Predicate.not(new SubmittablePredicate(SubmitRecord.Status.RULE_ERROR)));
}
if ("ignored".equalsIgnoreCase(value)) {
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
index 370bc75..ed1f2f1 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryProcessor.java
@@ -17,7 +17,6 @@
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.query.change.ChangeQueryBuilder.FIELD_LIMIT;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.gerrit.entities.Change;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
@@ -33,10 +32,8 @@
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.DynamicOptions.DynamicBean;
import com.google.gerrit.server.account.AccountLimits;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.change.ChangePluginDefinedInfoFactory;
import com.google.gerrit.server.change.PluginDefinedAttributesFactories;
-import com.google.gerrit.server.change.PluginDefinedAttributesFactory;
import com.google.gerrit.server.change.PluginDefinedInfosFactory;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexRewriter;
@@ -60,7 +57,6 @@
public class ChangeQueryProcessor extends QueryProcessor<ChangeData>
implements DynamicOptions.BeanReceiver, DynamicOptions.BeanProvider, PluginDefinedInfosFactory {
private final Provider<CurrentUser> userProvider;
- private final ImmutableListMultimap<String, ChangeAttributeFactory> attributeFactoriesByPlugin;
private final ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory;
private final Map<String, DynamicBean> dynamicBeans = new HashMap<>();
private final List<Extension<ChangePluginDefinedInfoFactory>>
@@ -81,7 +77,6 @@
IndexConfig indexConfig,
ChangeIndexCollection indexes,
ChangeIndexRewriter rewriter,
- DynamicSet<ChangeAttributeFactory> attributeFactories,
ChangeIsVisibleToPredicate.Factory changeIsVisibleToPredicateFactory,
DynamicSet<ChangePluginDefinedInfoFactory> changePluginDefinedInfoFactories) {
super(
@@ -95,14 +90,6 @@
this.userProvider = userProvider;
this.changeIsVisibleToPredicateFactory = changeIsVisibleToPredicateFactory;
- ImmutableListMultimap.Builder<String, ChangeAttributeFactory> factoriesBuilder =
- ImmutableListMultimap.builder();
- ImmutableListMultimap.Builder<String, ChangePluginDefinedInfoFactory> infosFactoriesBuilder =
- ImmutableListMultimap.builder();
- // Eagerly call Extension#get() rather than storing Extensions, since that method invokes the
- // Provider on every call, which could be expensive if we invoke it once for every change.
- attributeFactories.entries().forEach(e -> factoriesBuilder.put(e.getPluginName(), e.get()));
- attributeFactoriesByPlugin = factoriesBuilder.build();
changePluginDefinedInfoFactories
.entries()
.forEach(e -> changePluginDefinedInfoFactoriesByPlugin.add(e));
@@ -130,18 +117,6 @@
return dynamicBeans.get(plugin);
}
- public PluginDefinedAttributesFactory getAttributesFactory() {
- return this::buildPluginInfo;
- }
-
- private ImmutableList<PluginDefinedInfo> buildPluginInfo(ChangeData cd) {
- return PluginDefinedAttributesFactories.createAll(
- cd,
- this,
- attributeFactoriesByPlugin.entries().stream()
- .map(e -> new Extension<>(e.getKey(), e::getValue)));
- }
-
public PluginDefinedInfosFactory getInfosFactory() {
return this::createPluginDefinedInfos;
}
diff --git a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
index b931457..4922b57 100644
--- a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
+++ b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
@@ -330,15 +330,9 @@
eventFactory.addDependencies(rw, c, d.change(), d.currentPatchSet());
}
- c.plugins = queryProcessor.getAttributesFactory().create(d);
List<PluginDefinedInfo> pluginInfos = pluginInfosByChange.get(d.getId());
if (!pluginInfos.isEmpty()) {
- if (c.plugins == null) {
- c.plugins = pluginInfos;
- } else {
- c.plugins = new ArrayList<>(c.plugins);
- c.plugins.addAll(pluginInfos);
- }
+ c.plugins = pluginInfos;
}
return c;
}
diff --git a/java/com/google/gerrit/server/restapi/change/CommentJson.java b/java/com/google/gerrit/server/restapi/change/CommentJson.java
index cc8ad47..02f39ab 100644
--- a/java/com/google/gerrit/server/restapi/change/CommentJson.java
+++ b/java/com/google/gerrit/server/restapi/change/CommentJson.java
@@ -123,7 +123,6 @@
list = new ArrayList<>();
out.put(o.path, list);
}
- o.path = null;
list.add(o);
}
@@ -133,10 +132,11 @@
loader.fill();
}
+ List<T> allComments = out.values().stream().flatMap(Collection::stream).collect(toList());
if (fillCommentContext) {
- List<T> allComments = out.values().stream().flatMap(Collection::stream).collect(toList());
addCommentContext(allComments);
}
+ allComments.forEach(c -> c.path = null); // we don't need path since it exists in the map keys
return out;
}
diff --git a/java/com/google/gerrit/server/restapi/change/CreateChange.java b/java/com/google/gerrit/server/restapi/change/CreateChange.java
index d535d39..c392bd1 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateChange.java
@@ -227,8 +227,7 @@
throw new BadRequestException(
"Cannot create a change on ref "
+ input.branch
- + ". "
- + "Allowed branches are refs/heads/*, refs/meta/dashboards/* or refs/meta/config");
+ + ". Gerrit internal refs and refs/tags/* are not allowed.");
}
String subject = Strings.nullToEmpty(input.subject);
@@ -299,11 +298,9 @@
}
}
+ /** Changes are allowed to be created on any ref that is not Gerrit internal or a tag ref. */
private boolean isBranchAllowed(String branch) {
- return branch.startsWith(RefNames.REFS_HEADS)
- || branch.startsWith(RefNames.REFS_DASHBOARDS)
- || "HEAD".equals(branch)
- || RefNames.REFS_CONFIG.equals(branch);
+ return !RefNames.isGerritRef(branch) && !branch.startsWith(RefNames.REFS_TAGS);
}
private void checkRequiredPermissions(
diff --git a/java/com/google/gerrit/server/restapi/change/GetChange.java b/java/com/google/gerrit/server/restapi/change/GetChange.java
index 1ef3c4b..f28d2b3 100644
--- a/java/com/google/gerrit/server/restapi/change/GetChange.java
+++ b/java/com/google/gerrit/server/restapi/change/GetChange.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.restapi.change;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Streams;
import com.google.gerrit.entities.Change;
@@ -27,7 +26,6 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.DynamicOptions.DynamicBean;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangePluginDefinedInfoFactory;
import com.google.gerrit.server.change.ChangeResource;
@@ -46,7 +44,6 @@
DynamicOptions.BeanReceiver,
DynamicOptions.BeanProvider {
private final ChangeJson.Factory json;
- private final DynamicSet<ChangeAttributeFactory> attrFactories;
private final DynamicSet<ChangePluginDefinedInfoFactory> pdiFactories;
private final EnumSet<ListChangesOption> options = EnumSet.noneOf(ListChangesOption.class);
private final Map<String, DynamicBean> dynamicBeans = new HashMap<>();
@@ -62,12 +59,8 @@
}
@Inject
- GetChange(
- ChangeJson.Factory json,
- DynamicSet<ChangeAttributeFactory> attrFactories,
- DynamicSet<ChangePluginDefinedInfoFactory> pdiFactories) {
+ GetChange(ChangeJson.Factory json, DynamicSet<ChangePluginDefinedInfoFactory> pdiFactories) {
this.json = json;
- this.attrFactories = attrFactories;
this.pdiFactories = pdiFactories;
}
@@ -91,12 +84,7 @@
}
private ChangeJson newChangeJson() {
- return json.create(options, this::buildPluginInfo, this::createPluginDefinedInfos);
- }
-
- private ImmutableList<PluginDefinedInfo> buildPluginInfo(ChangeData cd) {
- return PluginDefinedAttributesFactories.createAll(
- cd, this, Streams.stream(attrFactories.entries()));
+ return json.create(options, this::createPluginDefinedInfos);
}
private ImmutableListMultimap<Change.Id, PluginDefinedInfo> createPluginDefinedInfos(
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index a66abaa..bf9990c 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -181,6 +181,7 @@
private final PluginSetContext<OnPostReview> onPostReviews;
private final ReplyAttentionSetUpdates replyAttentionSetUpdates;
private final boolean strictLabels;
+ private final boolean publishPatchSetLevelComment;
@Inject
PostReview(
@@ -228,6 +229,8 @@
this.onPostReviews = onPostReviews;
this.replyAttentionSetUpdates = replyAttentionSetUpdates;
this.strictLabels = gerritConfig.getBoolean("change", "strictLabels", false);
+ this.publishPatchSetLevelComment =
+ gerritConfig.getBoolean("event", "comment-added", "publishPatchSetLevelComment", true);
}
@Override
@@ -945,14 +948,23 @@
String.format("Repository %s not found", ctx.getProject().get()), ex);
}
}
+ String comment = message.getMessage();
+ if (publishPatchSetLevelComment) {
+ // TODO(davido): Remove this workaround when patch set level comments are exposed in comment
+ // added event. For backwards compatibility, patchset level comment has a higher priority
+ // than change message and should be used as comment in comment added event.
+ if (in.comments != null && in.comments.containsKey(PATCHSET_LEVEL)) {
+ List<CommentInput> patchSetLevelComments = in.comments.get(PATCHSET_LEVEL);
+ if (patchSetLevelComments != null && !patchSetLevelComments.isEmpty()) {
+ CommentInput firstComment = patchSetLevelComments.get(0);
+ if (!Strings.isNullOrEmpty(firstComment.message)) {
+ comment = String.format("Patch Set %s:\n\n%s", psId.get(), firstComment.message);
+ }
+ }
+ }
+ }
commentAdded.fire(
- notes.getChange(),
- ps,
- user.state(),
- message.getMessage(),
- approvals,
- oldApprovals,
- ctx.getWhen());
+ notes.getChange(), ps, user.state(), comment, approvals, oldApprovals, ctx.getWhen());
}
private boolean insertComments(ChangeContext ctx, List<RobotComment> newRobotComments)
diff --git a/java/com/google/gerrit/server/restapi/change/PreviewSubmit.java b/java/com/google/gerrit/server/restapi/change/PreviewSubmit.java
index ed6c0a5..4acf809 100644
--- a/java/com/google/gerrit/server/restapi/change/PreviewSubmit.java
+++ b/java/com/google/gerrit/server/restapi/change/PreviewSubmit.java
@@ -42,7 +42,6 @@
import com.google.gerrit.server.update.UpdateException;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.google.inject.Singleton;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
@@ -56,7 +55,6 @@
import org.eclipse.jgit.transport.ReceiveCommand;
import org.kohsuke.args4j.Option;
-@Singleton
public class PreviewSubmit implements RestReadView<RevisionResource> {
private static final int MAX_DEFAULT_BUNDLE_SIZE = 100 * 1024 * 1024;
diff --git a/java/com/google/gerrit/server/restapi/change/QueryChanges.java b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
index 0fec476..cf0d4cf 100644
--- a/java/com/google/gerrit/server/restapi/change/QueryChanges.java
+++ b/java/com/google/gerrit/server/restapi/change/QueryChanges.java
@@ -27,8 +27,11 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryRequiresAuthException;
import com.google.gerrit.index.query.QueryResult;
+import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.change.ChangeJson;
+import com.google.gerrit.server.permissions.GlobalPermission;
+import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
@@ -49,10 +52,13 @@
private final ChangeQueryBuilder qb;
private final Provider<ChangeQueryProcessor> queryProcessorProvider;
private final HashMap<String, DynamicOptions.DynamicBean> dynamicBeans = new HashMap<>();
+ private final Provider<CurrentUser> userProvider;
+ private final PermissionBackend permissionBackend;
private EnumSet<ListChangesOption> options;
private Integer limit;
private Integer start;
private Boolean noLimit;
+ private Boolean skipVisibility;
@Option(
name = "--query",
@@ -94,6 +100,15 @@
this.noLimit = on;
}
+ @Option(name = "--skip-visibility", usage = "Skip visibility check, only for administrators")
+ public void skipVisibility(boolean on) throws AuthException, PermissionBackendException {
+ if (on) {
+ CurrentUser user = userProvider.get();
+ permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
+ }
+ skipVisibility = on;
+ }
+
@Override
public void setDynamicBean(String plugin, DynamicOptions.DynamicBean dynamicBean) {
dynamicBeans.put(plugin, dynamicBean);
@@ -103,10 +118,14 @@
QueryChanges(
ChangeJson.Factory json,
ChangeQueryBuilder qb,
- Provider<ChangeQueryProcessor> queryProcessorProvider) {
+ Provider<ChangeQueryProcessor> queryProcessorProvider,
+ Provider<CurrentUser> userProvider,
+ PermissionBackend permissionBackend) {
this.json = json;
this.qb = qb;
this.queryProcessorProvider = queryProcessorProvider;
+ this.userProvider = userProvider;
+ this.permissionBackend = permissionBackend;
options = EnumSet.noneOf(ListChangesOption.class);
}
@@ -152,6 +171,9 @@
if (noLimit != null) {
queryProcessor.setNoLimit(noLimit);
}
+ if (skipVisibility != null) {
+ queryProcessor.enforceVisibility(!skipVisibility);
+ }
dynamicBeans.forEach((p, b) -> queryProcessor.setDynamicBean(p, b));
if (queries == null || queries.isEmpty()) {
@@ -165,9 +187,7 @@
int cnt = queries.size();
List<QueryResult<ChangeData>> results = queryProcessor.query(qb.parse(queries));
List<List<ChangeInfo>> res =
- json.create(
- options, queryProcessor.getAttributesFactory(), queryProcessor.getInfosFactory())
- .format(results);
+ json.create(options, queryProcessor.getInfosFactory()).format(results);
for (int n = 0; n < cnt; n++) {
List<ChangeInfo> info = res.get(n);
if (results.get(n).more() && !info.isEmpty()) {
diff --git a/java/com/google/gerrit/server/restapi/project/CreateChange.java b/java/com/google/gerrit/server/restapi/project/CreateChange.java
index dbcd8c9..59efd06 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateChange.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateChange.java
@@ -59,8 +59,8 @@
throw new AuthException("Authentication required");
}
- if (!Strings.isNullOrEmpty(input.project)) {
- throw new BadRequestException("may not specify project");
+ if (!Strings.isNullOrEmpty(input.project) && !rsrc.getName().equals(input.project)) {
+ throw new BadRequestException("project must match URL");
}
input.project = rsrc.getName();
diff --git a/java/com/google/gerrit/server/restapi/project/CreateDashboard.java b/java/com/google/gerrit/server/restapi/project/CreateDashboard.java
index e9a0d7f..34d6696 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateDashboard.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateDashboard.java
@@ -26,11 +26,9 @@
import com.google.gerrit.server.project.ProjectResource;
import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.google.inject.Singleton;
import java.io.IOException;
import org.kohsuke.args4j.Option;
-@Singleton
public class CreateDashboard
implements RestCollectionCreateView<ProjectResource, DashboardResource, SetDashboardInput> {
private final Provider<SetDefaultDashboard> setDefault;
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 2db625b..409c808 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -481,7 +481,7 @@
if (!traceContext.isTracing()) {
String traceId = "retry-on-failure-" + new RequestId();
traceContext.addTag(RequestId.Type.TRACE_ID, traceId).forceLogging();
- logger.atFine().withCause(t).log(
+ logger.atWarning().withCause(t).log(
"AutoRetry: %s failed, retry with tracing enabled (cause = %s)",
actionName, cause);
opts.onAutoTrace().ifPresent(c -> c.accept(traceId));
@@ -492,7 +492,7 @@
// A non-recoverable failure occurred. We retried the operation with tracing
// enabled and it failed again. Log the failure so that admin can see if it
// differs from the failure that triggered the retry.
- logger.atFine().withCause(t).log(
+ logger.atWarning().withCause(t).log(
"AutoRetry: auto-retry of %s has failed (cause = %s)", actionName, cause);
metrics.failuresOnAutoRetryCount.increment(actionType, actionName, cause);
return false;
@@ -504,7 +504,7 @@
return executeWithTimeoutCount(actionType, action, opts, retryerBuilder.build(), listener);
} finally {
if (listener.getAttemptCount() > 1) {
- logger.atFine().log("%s was attempted %d times", actionType, listener.getAttemptCount());
+ logger.atWarning().log("%s was attempted %d times", actionType, listener.getAttemptCount());
metrics.attemptCounts.incrementBy(
actionType,
opts.actionName().orElse("N/A"),
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeSubmitRequirementIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeSubmitRequirementIT.java
index fd9af0e..eb5b9b0 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeSubmitRequirementIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeSubmitRequirementIT.java
@@ -22,6 +22,8 @@
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.SubmitRequirementInfo;
import com.google.gerrit.extensions.config.FactoryModule;
@@ -33,7 +35,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
public class ChangeSubmitRequirementIT extends AbstractDaemonTest {
@@ -93,20 +94,113 @@
assertThat(result.get(0).requirements).containsExactly(reqInfo);
}
+ @Test
+ public void submittableQueryRuleNotReady() throws Exception {
+ ChangeApi change = newChangeApi();
+
+ // Satisfy the default rule.
+ approveChange(change);
+
+ // The custom rule is NOT_READY.
+ rule.block(true);
+ change.index();
+
+ assertThat(queryIsSubmittable()).isEmpty();
+ }
+
+ @Test
+ public void submittableQueryRuleError() throws Exception {
+ ChangeApi change = newChangeApi();
+
+ // Satisfy the default rule.
+ approveChange(change);
+
+ rule.status(Optional.of(SubmitRecord.Status.RULE_ERROR));
+ change.index();
+
+ assertThat(queryIsSubmittable()).isEmpty();
+ }
+
+ @Test
+ public void submittableQueryDefaultRejected() throws Exception {
+ ChangeApi change = newChangeApi();
+
+ // CodeReview:-2 the change, causing the default rule to fail.
+ rejectChange(change);
+
+ rule.status(Optional.of(SubmitRecord.Status.OK));
+ change.index();
+
+ assertThat(queryIsSubmittable()).isEmpty();
+ }
+
+ @Test
+ public void submittableQueryRuleOk() throws Exception {
+ ChangeApi change = newChangeApi();
+
+ // Satisfy the default rule.
+ approveChange(change);
+
+ rule.status(Optional.of(SubmitRecord.Status.OK));
+ change.index();
+
+ List<ChangeInfo> result = queryIsSubmittable();
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).changeId).isEqualTo(change.info().changeId);
+ }
+
+ @Test
+ public void submittableQueryRuleNoRecord() throws Exception {
+ ChangeApi change = newChangeApi();
+
+ // Satisfy the default rule.
+ approveChange(change);
+
+ // Our custom rule isn't providing any submit records.
+ rule.status(Optional.empty());
+ change.index();
+
+ // is:submittable should return the change, since it was approved and the custom rule is not
+ // blocking it.
+ List<ChangeInfo> result = queryIsSubmittable();
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).changeId).isEqualTo(change.info().changeId);
+ }
+
+ private List<ChangeInfo> queryIsSubmittable() throws Exception {
+ return gApi.changes().query("is:submittable project:" + project.get()).get();
+ }
+
+ private ChangeApi newChangeApi() throws Exception {
+ return gApi.changes().id(createChange().getChangeId());
+ }
+
+ private void approveChange(ChangeApi changeApi) throws Exception {
+ changeApi.current().review(ReviewInput.approve());
+ }
+
+ private void rejectChange(ChangeApi changeApi) throws Exception {
+ changeApi.current().review(ReviewInput.reject());
+ }
+
@Singleton
private static class CustomSubmitRule implements SubmitRule {
- private final AtomicBoolean block = new AtomicBoolean(true);
+ private Optional<SubmitRecord.Status> recordStatus = Optional.empty();
public void block(boolean block) {
- this.block.set(block);
+ this.status(block ? Optional.of(SubmitRecord.Status.NOT_READY) : Optional.empty());
+ }
+
+ public void status(Optional<SubmitRecord.Status> status) {
+ this.recordStatus = status;
}
@Override
public Optional<SubmitRecord> evaluate(ChangeData changeData) {
- if (block.get()) {
+ if (this.recordStatus.isPresent()) {
SubmitRecord record = new SubmitRecord();
record.labels = new ArrayList<>();
- record.status = SubmitRecord.Status.NOT_READY;
+ record.status = this.recordStatus.get();
record.requirements = ImmutableList.of(req);
return Optional.of(record);
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/PluginFieldsIT.java b/javatests/com/google/gerrit/acceptance/api/change/PluginFieldsIT.java
index 31198d5..cebce0b 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/PluginFieldsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/PluginFieldsIT.java
@@ -16,9 +16,6 @@
import com.google.gerrit.acceptance.AbstractPluginFieldsTest;
import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.extensions.annotations.Exports;
-import com.google.gerrit.server.change.ChangeAttributeFactory;
-import com.google.inject.AbstractModule;
import java.util.Arrays;
import org.junit.Test;
@@ -27,30 +24,6 @@
// No tests for /detail via the extension API, since the extension API doesn't have that method.
@Test
- public void queryChangeWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(
- id -> pluginInfoFromSingletonList(gApi.changes().query(id.toString()).get()));
- }
-
- @Test
- public void getChangeWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(
- id -> pluginInfoFromChangeInfo(gApi.changes().id(id.toString()).get()));
- }
-
- @Test
- public void queryChangeWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromSingletonList(gApi.changes().query(id.toString()).get()));
- }
-
- @Test
- public void getChangeWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromChangeInfo(gApi.changes().id(id.toString()).get()));
- }
-
- @Test
public void querySingleChangeWithBulkAttribute() throws Exception {
getSingleChangeWithPluginDefinedBulkAttribute(
id -> pluginInfosFromChangeInfos(gApi.changes().query(id.toString()).get()));
@@ -63,22 +36,6 @@
}
@Test
- public void queryChangeWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromSingletonList(gApi.changes().query(id.toString()).get()),
- (id, opts) ->
- pluginInfoFromSingletonList(
- gApi.changes().query(id.toString()).withPluginOptions(opts).get()));
- }
-
- @Test
- public void getChangeWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromChangeInfo(gApi.changes().id(id.get()).get()),
- (id, opts) -> pluginInfoFromChangeInfo(gApi.changes().id(id.get()).get(opts)));
- }
-
- @Test
public void queryChangeWithOptionBulkAttribute() throws Exception {
getChangeWithPluginDefinedBulkAttributeOption(
id -> pluginInfosFromChangeInfos(gApi.changes().query(id.toString()).get()),
@@ -108,12 +65,6 @@
}
@Test
- public void getMultipleChangesWithPluginDefinedAndChangeAttributes() throws Exception {
- getMultipleChangesWithPluginDefinedBulkAndChangeAttributes(
- () -> pluginInfosFromChangeInfos(gApi.changes().query("status:open").get()));
- }
-
- @Test
public void getMultipleChangesWithPluginDefinedAttributeInSingleCall() throws Exception {
getMultipleChangesWithPluginDefinedBulkAttributeInSingleCall(
() -> pluginInfosFromChangeInfos(gApi.changes().query("status:open").get()));
@@ -124,23 +75,4 @@
getChangeWithPluginDefinedBulkAttributeWithException(
id -> pluginInfosFromChangeInfos(Arrays.asList(gApi.changes().id(id.get()).get())));
}
-
- static class SimpleAttributeWithExplicitExportModule extends AbstractModule {
- @Override
- public void configure() {
- bind(ChangeAttributeFactory.class)
- .annotatedWith(Exports.named("simple"))
- .toInstance((cd, bp, p) -> new MyInfo("change " + cd.getId()));
- }
- }
-
- @Test
- public void getChangeWithSimpleAttributeWithExplicitExport() throws Exception {
- // For backwards compatibility with old plugins, allow modules to bind into the
- // DynamicSet<ChangeAttributeFactory> as if it were a DynamicMap. We only need one variant of
- // this test to prove that the mapping works.
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromChangeInfo(gApi.changes().id(id.toString()).get()),
- SimpleAttributeWithExplicitExportModule.class);
- }
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java b/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
index 33ec556..14704ad 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/QueryChangesIT.java
@@ -25,21 +25,27 @@
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
+import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
+import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
+import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.TopLevelResource;
+import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.restapi.change.QueryChanges;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Arrays;
import java.util.List;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
@@ -50,6 +56,7 @@
@Inject private AccountOperations accountOperations;
@Inject private ProjectOperations projectOperations;
@Inject private Provider<QueryChanges> queryChangesProvider;
+ @Inject private RequestScopeOperations requestScopeOperations;
@Test
@SuppressWarnings("unchecked")
@@ -283,9 +290,91 @@
assertThat(result.get(1).get(0)._number).isEqualTo(numericId2);
}
+ @Test
+ public void skipVisibility_rejectedForNonAdmin() throws Exception {
+ requestScopeOperations.setApiUser(user.id());
+ final QueryChanges queryChanges = queryChangesProvider.get();
+ String query = "is:open repo:" + project.get();
+ queryChanges.addQuery(query);
+ AuthException thrown =
+ assertThrows(AuthException.class, () -> queryChanges.skipVisibility(true));
+ assertThat(thrown).hasMessageThat().isEqualTo("administrate server not permitted");
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void skipVisibility_noReadPermission() throws Exception {
+ createChange().getChangeId();
+ requestScopeOperations.setApiUser(admin.id());
+ QueryChanges queryChanges = queryChangesProvider.get();
+
+ queryChanges.addQuery("is:open repo:" + project.get());
+ List<List<ChangeInfo>> result =
+ (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+ assertThat(result).hasSize(1);
+
+ try (ProjectConfigUpdate u = updateProject(allProjects)) {
+ ProjectConfig cfg = u.getConfig();
+ removeAllBranchPermissions(cfg, Permission.READ);
+ u.save();
+ }
+
+ queryChanges = queryChangesProvider.get();
+ queryChanges.addQuery("is:open repo:" + project.get());
+ List<List<ChangeInfo>> result2 =
+ (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+ assertThat(result2).hasSize(0);
+
+ queryChanges = queryChangesProvider.get();
+ queryChanges.addQuery("is:open repo:" + project.get());
+ queryChanges.skipVisibility(true);
+ List<List<ChangeInfo>> result3 =
+ (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+ assertThat(result3).hasSize(1);
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void skipVisibility_privateChange() throws Exception {
+ TestRepository<InMemoryRepository> userRepo = cloneProject(project, user);
+ PushOneCommit.Result result =
+ pushFactory.create(user.newIdent(), userRepo).to("refs/for/master");
+ requestScopeOperations.setApiUser(user.id());
+ gApi.changes().id(result.getChangeId()).setPrivate(true);
+
+ requestScopeOperations.setApiUser(admin.id());
+ QueryChanges queryChanges = queryChangesProvider.get();
+
+ queryChanges.addQuery("is:open repo:" + project.get());
+ List<List<ChangeInfo>> result2 =
+ (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+ assertThat(result2).hasSize(0);
+
+ queryChanges = queryChangesProvider.get();
+ queryChanges.addQuery("is:open repo:" + project.get());
+ queryChanges.skipVisibility(true);
+ List<List<ChangeInfo>> result3 =
+ (List<List<ChangeInfo>>) queryChanges.apply(TopLevelResource.INSTANCE).value();
+ assertThat(result3).hasSize(1);
+ }
+
private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
for (ChangeInfo info : results) {
assertThat(info._moreChanges).isNull();
}
}
+
+ private static void removeAllBranchPermissions(ProjectConfig cfg, String... permissions) {
+ for (AccessSection s : ImmutableList.copyOf(cfg.getAccessSections())) {
+ if (s.getName().startsWith("refs/heads/")
+ || s.getName().startsWith("refs/for/")
+ || s.getName().equals("refs/*")) {
+ cfg.upsertAccessSection(
+ s.getName(),
+ updatedSection -> {
+ Arrays.stream(permissions).forEach(p -> updatedSection.remove(Permission.builder(p)));
+ });
+ }
+ }
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
index 39366bd..ff785a2 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
@@ -2745,6 +2745,55 @@
}
@Test
+ public void symlinkConveredToRegularFileIsIdentifiedAsDeleted() throws Exception {
+ // TODO(ghareeb): See https://bugs.chromium.org/p/gerrit/issues/detail?id=13914.
+ // This test creates a corner scenario of replacing a symlink with a regular file
+ // of the same name. When both patchsets are diffed, the List Files endpoint identifies the
+ // file as a 'REWRITE', however the diff endpoint for the symlink file identifies the file as
+ // deleted. This case is a bit risky since it hides from the user the new content that was added
+ // in the new regular file. Ideally, the diff endpoint should show two entries for the deleted
+ // symlink and the added file, or only one entry "REWRITE" with the content that was added to
+ // the new file.
+ String target = "file.txt";
+ String symlink = "link.lnk";
+
+ // Create a change adding file "FileName" and a symlink "symLink" pointing to the file
+ PushOneCommit push =
+ pushFactory
+ .create(admin.newIdent(), testRepo, "Commit Subject", target, "content")
+ .addSymlink(symlink, target);
+
+ PushOneCommit.Result result = push.to("refs/for/master");
+ String initialRev = gApi.changes().id(result.getChangeId()).get().currentRevision;
+
+ // Delete the symlink with patchset 2
+ gApi.changes().id(result.getChangeId()).edit().deleteFile(symlink);
+ gApi.changes().id(result.getChangeId()).edit().publish();
+
+ // Re-add the symlink as a regular file with patchset 3
+ gApi.changes()
+ .id(result.getChangeId())
+ .edit()
+ .modifyFile(symlink, RawInputUtil.create("Content of the new file named 'symlink'"));
+ gApi.changes().id(result.getChangeId()).edit().publish();
+
+ Map<String, FileInfo> changedFiles =
+ gApi.changes().id(result.getChangeId()).current().files(initialRev);
+
+ assertThat(changedFiles.keySet()).containsExactly("/COMMIT_MSG", symlink);
+ assertThat(changedFiles.get(symlink).status).isEqualTo('W'); // Rewrite
+
+ DiffInfo diffInfo =
+ gApi.changes().id(result.getChangeId()).current().file(symlink).diff(initialRev);
+
+ // TODO(ghareeb): This is not a desired behaviour. The diff endpoint treats the file as
+ // 'DELETED', hence hiding any new content that was added to the new regular file. It is better
+ // to show the file as 'ADDED'. See https://bugs.chromium.org/p/gerrit/issues/detail?id=13914
+ // for more details.
+ assertThat(diffInfo.changeType).isEqualTo(ChangeType.DELETED);
+ }
+
+ @Test
public void diffOfNonExistentFileIsAnEmptyDiffResult() throws Exception {
addModifiedPatchSet(changeId, FILE_NAME, content -> content.replace("Line 2\n", "Line two\n"));
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 22a7e03..8e31e904 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -1622,7 +1622,7 @@
new PatchSetWebLink() {
@Override
public WebLinkInfo getPatchSetWebLink(
- String projectName, String commit, String subject, String branchName) {
+ String projectName, String commit, String commitMessage, String branchName) {
return expectedWebLinkInfo;
}
};
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/PluginProvidedRootRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/PluginProvidedRootRestApiBindingsIT.java
index b447534..16dc294 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/PluginProvidedRootRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/PluginProvidedRootRestApiBindingsIT.java
@@ -16,6 +16,7 @@
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -48,6 +49,7 @@
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;
+import org.kohsuke.args4j.Option;
/**
* Tests for checking plugin-provided REST API bindings directly under {@code /}.
@@ -192,8 +194,15 @@
@Singleton
static class TestGet implements RestReadView<TestPluginResource> {
+
+ @Option(name = "--crash")
+ String crash;
+
@Override
public Response<String> apply(TestPluginResource resource) throws Exception {
+ if (!Strings.nullToEmpty(crash).isEmpty()) {
+ throw new IllegalStateException();
+ }
return Response.ok("test");
}
}
@@ -204,4 +213,13 @@
RestApiCallHelper.execute(adminRestSession, TEST_CALLS.asList());
}
}
+
+ @Test
+ public void testOptionOnSingletonIsIgnored() throws Exception {
+ try (AutoCloseable ignored = installPlugin(PLUGIN_NAME, null, MyPluginHttpModule.class, null)) {
+ RestApiCallHelper.execute(
+ adminRestSession,
+ RestCall.get("/plugins/" + PLUGIN_NAME + "/test-collection/1/detail?crash=xyz"));
+ }
+ }
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
index ce21477..a539bd5 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
@@ -182,13 +182,7 @@
}
@Test
- public void cannotCreateChangeOnNoteDbRefs() throws Exception {
- String[] disallowedBranches = {
- "refs/users/82/1000002",
- "refs/tags/v2.1",
- "refs/cache-automerge/ec/00000000000000000000000000000000000000"
- };
-
+ public void cannotCreateChangeOnGerritInternalRefs() throws Exception {
requestScopeOperations.setApiUser(admin.id());
projectOperations
.project(project)
@@ -196,21 +190,41 @@
.add(allow(CREATE).ref("refs/*").group(REGISTERED_USERS))
.update();
- for (String branchName : disallowedBranches) {
- requestScopeOperations.setApiUser(admin.id());
- BranchNameKey branchNameKey = BranchNameKey.create(project, branchName);
- createBranch(branchNameKey);
+ String disallowedRef = "refs/changes/00/1000"; // All Gerrit internal refs behave the same way
+ requestScopeOperations.setApiUser(admin.id());
+ BranchNameKey branchNameKey = BranchNameKey.create(project, disallowedRef);
+ createBranch(branchNameKey);
- requestScopeOperations.setApiUser(user.id());
- ChangeInput ci = newChangeInput(ChangeStatus.NEW);
- ci.subject = "Subject";
- ci.branch = branchName;
+ requestScopeOperations.setApiUser(user.id());
+ ChangeInput ci = newChangeInput(ChangeStatus.NEW);
+ ci.subject = "Subject";
+ ci.branch = disallowedRef;
- Throwable thrown = assertThrows(RestApiException.class, () -> gApi.changes().create(ci));
- assertThat(thrown)
- .hasMessageThat()
- .contains("Cannot create a change on ref " + ci.branch + ". ");
- }
+ Throwable thrown = assertThrows(RestApiException.class, () -> gApi.changes().create(ci));
+ assertThat(thrown).hasMessageThat().contains("Cannot create a change on ref " + ci.branch);
+ }
+
+ @Test
+ public void cannotCreateChangeOnTagRefs() throws Exception {
+ requestScopeOperations.setApiUser(admin.id());
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(allow(CREATE).ref("refs/*").group(REGISTERED_USERS))
+ .update();
+
+ String branchName = "refs/tags/v1.0";
+ requestScopeOperations.setApiUser(admin.id());
+ BranchNameKey branchNameKey = BranchNameKey.create(project, branchName);
+ createBranch(branchNameKey);
+
+ requestScopeOperations.setApiUser(user.id());
+ ChangeInput ci = newChangeInput(ChangeStatus.NEW);
+ ci.subject = "Subject";
+ ci.branch = branchName;
+
+ Throwable thrown = assertThrows(RestApiException.class, () -> gApi.changes().create(ci));
+ assertThat(thrown).hasMessageThat().contains("Cannot create a change on ref " + ci.branch);
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/PluginFieldsIT.java b/javatests/com/google/gerrit/acceptance/rest/change/PluginFieldsIT.java
index 17bf37e..a4ec40e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/PluginFieldsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/PluginFieldsIT.java
@@ -14,8 +14,6 @@
package com.google.gerrit.acceptance.rest.change;
-import static com.google.common.truth.Truth.assertThat;
-
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableListMultimap;
import com.google.gerrit.acceptance.AbstractPluginFieldsTest;
@@ -35,41 +33,6 @@
private static final Gson GSON = OutputFormat.JSON.newGson();
@Test
- public void queryChangeWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(
- id -> pluginInfoFromSingletonList(adminRestSession.get(changeQueryUrl(id))));
- }
-
- @Test
- public void getChangeWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(id -> pluginInfoFromChangeInfo(adminRestSession.get(changeUrl(id))));
- }
-
- @Test
- public void getChangeDetailWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(
- id -> pluginInfoFromChangeInfo(adminRestSession.get(changeDetailUrl(id))));
- }
-
- @Test
- public void queryChangeWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromSingletonList(adminRestSession.get(changeQueryUrl(id))));
- }
-
- @Test
- public void getChangeWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromChangeInfo(adminRestSession.get(changeUrl(id))));
- }
-
- @Test
- public void getChangeDetailWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromChangeInfo(adminRestSession.get(changeDetailUrl(id))));
- }
-
- @Test
public void querySingleChangeWithBulkAttribute() throws Exception {
getSingleChangeWithPluginDefinedBulkAttribute(
id -> pluginInfosFromChangeInfos(adminRestSession.get(changeQueryUrl(id))));
@@ -88,27 +51,6 @@
}
@Test
- public void queryChangeWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromSingletonList(adminRestSession.get(changeQueryUrl(id))),
- (id, opts) -> pluginInfoFromSingletonList(adminRestSession.get(changeQueryUrl(id, opts))));
- }
-
- @Test
- public void getChangeWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromChangeInfo(adminRestSession.get(changeUrl(id))),
- (id, opts) -> pluginInfoFromChangeInfo(adminRestSession.get(changeUrl(id, opts))));
- }
-
- @Test
- public void getChangeDetailWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromChangeInfo(adminRestSession.get(changeDetailUrl(id))),
- (id, opts) -> pluginInfoFromChangeInfo(adminRestSession.get(changeDetailUrl(id, opts))));
- }
-
- @Test
public void pluginDefinedQueryChangeWithOption() throws Exception {
getChangeWithPluginDefinedBulkAttributeOption(
id -> pluginInfosFromChangeInfos(adminRestSession.get(changeQueryUrl(id))),
@@ -142,12 +84,6 @@
}
@Test
- public void getMultipleChangesWithPluginDefinedAndChangeAttributes() throws Exception {
- getMultipleChangesWithPluginDefinedBulkAndChangeAttributes(
- () -> pluginInfosFromChangeInfos(adminRestSession.get("/changes/?q=status:open")));
- }
-
- @Test
public void getMultipleChangesWithPluginDefinedAttributeInSingleCall() throws Exception {
getMultipleChangesWithPluginDefinedBulkAttributeInSingleCall(
() -> pluginInfosFromChangeInfos(adminRestSession.get("/changes/?q=status:open")));
@@ -204,24 +140,6 @@
}
@Nullable
- private static List<PluginDefinedInfo> pluginInfoFromSingletonList(RestResponse res)
- throws Exception {
- res.assertOK();
- List<Map<String, Object>> changeInfos =
- GSON.fromJson(res.getReader(), new TypeToken<List<Map<String, Object>>>() {}.getType());
- assertThat(changeInfos).hasSize(1);
- return decodeRawPluginsList(GSON, changeInfos.get(0).get("plugins"));
- }
-
- @Nullable
- private List<PluginDefinedInfo> pluginInfoFromChangeInfo(RestResponse res) throws Exception {
- res.assertOK();
- Map<String, Object> changeInfo =
- GSON.fromJson(res.getReader(), new TypeToken<Map<String, Object>>() {}.getType());
- return decodeRawPluginsList(GSON, changeInfo.get("plugins"));
- }
-
- @Nullable
private Map<Change.Id, List<PluginDefinedInfo>> pluginInfoMapFromChangeInfo(RestResponse res)
throws Exception {
res.assertOK();
diff --git a/javatests/com/google/gerrit/acceptance/server/event/CommentAddedEventIT.java b/javatests/com/google/gerrit/acceptance/server/event/CommentAddedEventIT.java
index 002b860..fb3259f 100644
--- a/javatests/com/google/gerrit/acceptance/server/event/CommentAddedEventIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/event/CommentAddedEventIT.java
@@ -26,6 +26,7 @@
import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -201,6 +202,25 @@
assertThat(attr.value).isEqualTo(-1);
assertThat(listener.getLastCommentAddedEvent().getComment())
.isEqualTo(String.format("Patch Set 1:\n\n%s", label.getName()));
+
+ // review with patch set level comment
+ reviewInput = new ReviewInput().patchSetLevelComment("a patch set level comment");
+ revision(r).review(reviewInput);
+ assertThat(listener.getLastCommentAddedEvent().getComment())
+ .isEqualTo(String.format("Patch Set 1:\n\n%s", "a patch set level comment"));
+ }
+ }
+
+ @Test
+ @GerritConfig(name = "event.comment-added.publishPatchSetLevelComment", value = "false")
+ public void publishPatchSetLevelComment() throws Exception {
+ PushOneCommit.Result r = createChange();
+ TestListener listener = new TestListener();
+ try (Registration registration = extensionRegistry.newRegistration().add(listener)) {
+ ReviewInput reviewInput = new ReviewInput().patchSetLevelComment("a patch set level comment");
+ revision(r).review(reviewInput);
+ assertThat(listener.getLastCommentAddedEvent().getComment())
+ .isEqualTo(String.format("Patch Set 1:\n\n%s", "(1 comment)"));
}
}
diff --git a/javatests/com/google/gerrit/acceptance/server/permissions/ExternalUserPermissionIT.java b/javatests/com/google/gerrit/acceptance/server/permissions/ExternalUserPermissionIT.java
index fc7ab2f..9e4907c 100644
--- a/javatests/com/google/gerrit/acceptance/server/permissions/ExternalUserPermissionIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/permissions/ExternalUserPermissionIT.java
@@ -40,6 +40,8 @@
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.ExternalUser;
+import com.google.gerrit.server.PropertyMap;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.externalids.ExternalId;
@@ -47,7 +49,6 @@
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.query.change.ExternalUser;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.Collection;
@@ -293,6 +294,8 @@
ExternalUser createUserInGroup(String userId, String groupId) {
return externalUserFactory.create(
- ImmutableSet.of(ExternalId.Key.parse("company-auth:" + groupId + "-" + userId)));
+ ImmutableSet.of(),
+ ImmutableSet.of(ExternalId.Key.parse("company-auth:" + groupId + "-" + userId)),
+ PropertyMap.EMPTY);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/ssh/PluginChangeFieldsIT.java b/javatests/com/google/gerrit/acceptance/ssh/PluginChangeFieldsIT.java
index 38293f9..009e05d 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/PluginChangeFieldsIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/PluginChangeFieldsIT.java
@@ -14,7 +14,6 @@
package com.google.gerrit.acceptance.ssh;
-import static com.google.common.truth.Truth.assertThat;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.ImmutableListMultimap;
@@ -41,31 +40,12 @@
private static final Gson GSON = OutputStreamQuery.GSON;
@Test
- public void queryChangeWithNullAttribute() throws Exception {
- getChangeWithNullAttribute(
- id -> pluginInfoFromSingletonList(adminSshSession.exec(changeQueryCmd(id))));
- }
-
- @Test
- public void queryChangeWithSimpleAttribute() throws Exception {
- getChangeWithSimpleAttribute(
- id -> pluginInfoFromSingletonList(adminSshSession.exec(changeQueryCmd(id))));
- }
-
- @Test
public void querySingleChangeWithBulkAttribute() throws Exception {
getSingleChangeWithPluginDefinedBulkAttribute(
id -> pluginInfosFromList(adminSshSession.exec(changeQueryCmd(id))));
}
@Test
- public void queryChangeWithOption() throws Exception {
- getChangeWithOption(
- id -> pluginInfoFromSingletonList(adminSshSession.exec(changeQueryCmd(id))),
- (id, opts) -> pluginInfoFromSingletonList(adminSshSession.exec(changeQueryCmd(id, opts))));
- }
-
- @Test
public void queryPluginDefinedAttributeChangeWithOption() throws Exception {
getChangeWithPluginDefinedBulkAttributeOption(
id -> pluginInfosFromList(adminSshSession.exec(changeQueryCmd(id))),
@@ -85,12 +65,6 @@
}
@Test
- public void getMultipleChangesWithPluginDefinedAndChangeAttributes() throws Exception {
- getMultipleChangesWithPluginDefinedBulkAndChangeAttributes(
- () -> pluginInfosFromList(adminSshSession.exec("gerrit query --format json status:open")));
- }
-
- @Test
public void getMultipleChangesWithPluginDefinedAttributeInSingleCall() throws Exception {
getMultipleChangesWithPluginDefinedBulkAttributeInSingleCall(
() -> pluginInfosFromList(adminSshSession.exec("gerrit query --format json status:open")));
@@ -116,15 +90,6 @@
}
@Nullable
- private static List<PluginDefinedInfo> pluginInfoFromSingletonList(String sshOutput)
- throws Exception {
- List<Map<String, Object>> changeAttrs = getChangeAttrs(sshOutput);
-
- assertThat(changeAttrs).hasSize(1);
- return decodeRawPluginsList(GSON, changeAttrs.get(0).get("plugins"));
- }
-
- @Nullable
private static Map<Change.Id, List<PluginDefinedInfo>> pluginInfosFromList(String sshOutput)
throws Exception {
List<Map<String, Object>> changeAttrs = getChangeAttrs(sshOutput);
diff --git a/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java b/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
index 77ab58b..ba9475f 100644
--- a/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
+++ b/javatests/com/google/gerrit/httpd/raw/IndexServletTest.java
@@ -15,6 +15,7 @@
package com.google.gerrit.httpd.raw;
import static com.google.common.truth.Truth.assertThat;
+import static java.util.stream.Collectors.joining;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -53,8 +54,15 @@
String testCanonicalUrl = "foo-url";
String testCdnPath = "bar-cdn";
String testFaviconURL = "zaz-url";
+
+ String disabledDefault = IndexHtmlUtil.DEFAULT_EXPERIMENTS.asList().get(0);
+ org.eclipse.jgit.lib.Config serverConfig = new org.eclipse.jgit.lib.Config();
+ serverConfig.setStringList(
+ "experiments", null, "enabled", ImmutableList.of("NewFeature", "DisabledFeature"));
+ serverConfig.setStringList(
+ "experiments", null, "disabled", ImmutableList.of("DisabledFeature", disabledDefault));
IndexServlet servlet =
- new IndexServlet(testCanonicalUrl, testCdnPath, testFaviconURL, gerritApi);
+ new IndexServlet(testCanonicalUrl, testCdnPath, testFaviconURL, gerritApi, serverConfig);
FakeHttpServletResponse response = new FakeHttpServletResponse();
@@ -76,6 +84,15 @@
+ "'\\x7b\\x22\\/config\\/server\\/version\\x22: \\x22123\\x22, "
+ "\\x22\\/config\\/server\\/info\\x22: \\x7b\\x22default_theme\\x22:"
+ "\\x22my-default-theme\\x22\\x7d, \\x22\\/config\\/server\\/top-menus\\x22: "
- + "\\x5b\\x5d\\x7d');</script>");
+ + "\\x5b\\x5d\\x7d');");
+ String enabledDefaults =
+ IndexHtmlUtil.DEFAULT_EXPERIMENTS.stream()
+ .filter(e -> !e.equals(disabledDefault))
+ .collect(joining("\\x22,"));
+ assertThat(output)
+ .contains(
+ "window.ENABLED_EXPERIMENTS = JSON.parse('\\x5b\\x22NewFeature\\x22,\\x22"
+ + enabledDefaults
+ + "\\x22\\x5d');</script>");
}
}
diff --git a/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffCacheKeySerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffCacheKeySerializerTest.java
new file mode 100644
index 0000000..ecab07d
--- /dev/null
+++ b/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffCacheKeySerializerTest.java
@@ -0,0 +1,50 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.cache.serialize.entities;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
+import com.google.gerrit.server.patch.filediff.FileDiffCacheKey;
+import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheImpl.DiffAlgorithm;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+/** Tests the protobuf serializer for the {@link FileDiffCacheKey}. */
+public class FileDiffCacheKeySerializerTest {
+ private static final ObjectId COMMIT_ID_1 =
+ ObjectId.fromString("123e9fa8a286255ac7d5ba11b598892735758391");
+ private static final ObjectId COMMIT_ID_2 =
+ ObjectId.fromString("d07a03a9818c120301cb5b4a969b035479400b5f");
+
+ @Test
+ public void roundTrip() {
+ FileDiffCacheKey key =
+ FileDiffCacheKey.builder()
+ .project(Project.nameKey("project/x"))
+ .oldCommit(COMMIT_ID_1)
+ .newCommit(COMMIT_ID_2)
+ .newFilePath("some_file.txt")
+ .renameScore(65)
+ .diffAlgorithm(DiffAlgorithm.HISTOGRAM)
+ .whitespace(Whitespace.IGNORE_ALL)
+ .build();
+
+ byte[] serialized = FileDiffCacheKey.Serializer.INSTANCE.serialize(key);
+
+ assertThat(FileDiffCacheKey.Serializer.INSTANCE.deserialize(serialized)).isEqualTo(key);
+ }
+}
diff --git a/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffOutputSerializerTest.java b/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffOutputSerializerTest.java
new file mode 100644
index 0000000..4307954
--- /dev/null
+++ b/javatests/com/google/gerrit/server/cache/serialize/entities/FileDiffOutputSerializerTest.java
@@ -0,0 +1,51 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.cache.serialize.entities;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.entities.Patch.ChangeType;
+import com.google.gerrit.entities.Patch.PatchType;
+import com.google.gerrit.server.patch.filediff.Edit;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
+import com.google.gerrit.server.patch.filediff.TaggedEdit;
+import java.util.Optional;
+import org.junit.Test;
+
+public class FileDiffOutputSerializerTest {
+ @Test
+ public void roundTrip() {
+ ImmutableList<TaggedEdit> edits =
+ ImmutableList.of(
+ TaggedEdit.create(Edit.create(1, 5, 3, 4), true),
+ TaggedEdit.create(Edit.create(21, 30, 150, 158), false));
+
+ FileDiffOutput fileDiff =
+ FileDiffOutput.builder()
+ .oldPath(Optional.of("old_file_path.txt"))
+ .newPath(Optional.empty())
+ .changeType(Optional.of(ChangeType.DELETED))
+ .patchType(Optional.of(PatchType.UNIFIED))
+ .size(23)
+ .sizeDelta(10)
+ .headerLines(ImmutableList.of("header line 1", "header line 2"))
+ .edits(edits)
+ .build();
+
+ byte[] serialized = FileDiffOutput.Serializer.INSTANCE.serialize(fileDiff);
+ assertThat(FileDiffOutput.Serializer.INSTANCE.deserialize(serialized)).isEqualTo(fileDiff);
+ }
+}
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index 65196bf..87db21f 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -45,6 +45,7 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.InvalidNameException;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.InternalUser;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.config.AllProjectsName;
@@ -313,6 +314,11 @@
}
@Test
+ public void userRefIsVisibleForInternalUser() throws Exception {
+ internalUser(localKey).controlForRef("refs/users/default").asForRef().check(RefPermission.READ);
+ }
+
+ @Test
public void branchDelegation1() throws Exception {
projectOperations
.project(localKey)
@@ -1220,6 +1226,10 @@
return projectCache.get(nameKey).orElseThrow(illegalState(nameKey));
}
+ private ProjectControl internalUser(Project.NameKey localKey) throws Exception {
+ return projectControlFactory.create(new InternalUser(), getProjectState(localKey));
+ }
+
private ProjectControl user(Project.NameKey localKey, AccountGroup.UUID... memberOf)
throws Exception {
return user(localKey, null, memberOf);
diff --git a/package.json b/package.json
index 35544c2..91b8042 100644
--- a/package.json
+++ b/package.json
@@ -8,18 +8,20 @@
"@bazel/typescript": "^3.0.0-rc.1"
},
"devDependencies": {
- "eslint": "^6.6.0",
- "eslint-config-google": "^0.13.0",
- "eslint-plugin-html": "^6.0.0",
- "eslint-plugin-import": "^2.20.1",
- "eslint-plugin-jsdoc": "^19.2.0",
- "eslint-plugin-prettier": "^3.1.3",
- "gts": "^2.0.2",
+ "@typescript-eslint/eslint-plugin": "^4.11.0",
+ "eslint": "^7.16.0",
+ "eslint-config-google": "^0.14.0",
+ "eslint-plugin-html": "^6.1.1",
+ "eslint-plugin-import": "^2.22.1",
+ "eslint-plugin-jsdoc": "^30.7.9",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-prettier": "^3.3.0",
+ "gts": "^3.0.3",
"polymer-cli": "^1.9.11",
"prettier": "2.0.5",
"rollup": "^2.3.4",
"terser": "^4.8.0",
- "typescript": "3.9.5"
+ "typescript": "4.0.5"
},
"scripts": {
"clean": "git clean -fdx && bazel clean --expunge",
diff --git a/plugins/codemirror-editor b/plugins/codemirror-editor
index 7357ab4..740c35a 160000
--- a/plugins/codemirror-editor
+++ b/plugins/codemirror-editor
@@ -1 +1 @@
-Subproject commit 7357ab473599d16ae33cc982bbd65472f08c2dd6
+Subproject commit 740c35ae36f44748b3c91e60ee7dcb2fb6e99549
diff --git a/plugins/gitiles b/plugins/gitiles
index 0cd08bb..b196dd5 160000
--- a/plugins/gitiles
+++ b/plugins/gitiles
@@ -1 +1 @@
-Subproject commit 0cd08bbfac1a938079be8aaf6a6eef0e82ff9a41
+Subproject commit b196dd5b6fcfd50518a6625a64cb93424c084620
diff --git a/plugins/replication b/plugins/replication
index aa2792a..84b9304 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit aa2792a5f8a89c21e776cea29082a95d459e0697
+Subproject commit 84b93043383fe4296944598739db0a2dfb9b2ee6
diff --git a/polygerrit-ui/app/.eslintignore b/polygerrit-ui/app/.eslintignore
index 16ea228..087a049 100644
--- a/polygerrit-ui/app/.eslintignore
+++ b/polygerrit-ui/app/.eslintignore
@@ -1,3 +1,4 @@
**/node_modules
**/rollup.config.js
node_modules_licenses
+!.eslintrc-bazel.js
diff --git a/polygerrit-ui/app/.eslintrc-bazel.js b/polygerrit-ui/app/.eslintrc-bazel.js
index 977eb45..9a51242 100644
--- a/polygerrit-ui/app/.eslintrc-bazel.js
+++ b/polygerrit-ui/app/.eslintrc-bazel.js
@@ -20,7 +20,7 @@
// for node_modules.
function getBazelSettings() {
- const runFilesDir = process.env["RUNFILES_DIR"];
+ const runFilesDir = process.env['RUNFILES_DIR'];
if (!runFilesDir) {
// eslint is executed with 'bazel run ...' to fix the source code. It runs
// against real source code, no special paths for node_modules is set.
@@ -28,18 +28,18 @@
}
// eslint is executed with 'bazel test...'. Set path to required node_modules
return {
- "import/resolver": {
- "node": {
- "paths": [
+ 'import/resolver': {
+ node: {
+ paths: [
`${runFilesDir}/ui_npm/node_modules`,
- `${runFilesDir}/ui_dev_npm/node_modules`
- ]
- }
- }
+ `${runFilesDir}/ui_dev_npm/node_modules`,
+ ],
+ },
+ },
};
}
module.exports = {
- "extends": "./.eslintrc.js",
- "settings": getBazelSettings(),
+ extends: './.eslintrc.js',
+ settings: getBazelSettings(),
};
diff --git a/polygerrit-ui/app/.eslintrc.js b/polygerrit-ui/app/.eslintrc.js
index 28bea0b..ba2c40d 100644
--- a/polygerrit-ui/app/.eslintrc.js
+++ b/polygerrit-ui/app/.eslintrc.js
@@ -20,219 +20,224 @@
const path = require('path');
module.exports = {
- "extends": ["eslint:recommended", "google"],
- "parserOptions": {
- "ecmaVersion": 9,
- "sourceType": "module"
+ extends: ['eslint:recommended', 'google'],
+ parserOptions: {
+ ecmaVersion: 9,
+ sourceType: 'module',
},
- "env": {
- "browser": true,
- "es6": true
+ env: {
+ browser: true,
+ es6: true,
},
- "rules": {
+ rules: {
// https://eslint.org/docs/rules/no-confusing-arrow
- "no-confusing-arrow": "error",
+ 'no-confusing-arrow': 'error',
// https://eslint.org/docs/rules/newline-per-chained-call
- "newline-per-chained-call": ["error", {"ignoreChainWithDepth": 2}],
+ 'newline-per-chained-call': ['error', {ignoreChainWithDepth: 2}],
// https://eslint.org/docs/rules/arrow-body-style
- "arrow-body-style": ["error", "as-needed",
- {"requireReturnForObjectLiteral": true}],
+ 'arrow-body-style': ['error', 'as-needed',
+ {requireReturnForObjectLiteral: true}],
// https://eslint.org/docs/rules/arrow-parens
- "arrow-parens": ["error", "as-needed"],
+ 'arrow-parens': ['error', 'as-needed'],
// https://eslint.org/docs/rules/block-spacing
- "block-spacing": ["error", "always"],
+ 'block-spacing': ['error', 'always'],
// https://eslint.org/docs/rules/brace-style
- "brace-style": ["error", "1tbs", {"allowSingleLine": true}],
+ 'brace-style': ['error', '1tbs', {allowSingleLine: true}],
// https://eslint.org/docs/rules/camelcase
- "camelcase": "off",
+ 'camelcase': 'off',
// https://eslint.org/docs/rules/comma-dangle
- "comma-dangle": ["error", {
- "arrays": "always-multiline",
- "objects": "always-multiline",
- "imports": "always-multiline",
- "exports": "always-multiline",
- "functions": "never"
+ 'comma-dangle': ['error', {
+ arrays: 'always-multiline',
+ objects: 'always-multiline',
+ imports: 'always-multiline',
+ exports: 'always-multiline',
+ functions: 'never',
}],
// https://eslint.org/docs/rules/eol-last
- "eol-last": "off",
+ 'eol-last': 'off',
// https://eslint.org/docs/rules/indent
- "indent": ["error", 2, {
- "MemberExpression": 2,
- "FunctionDeclaration": {"body": 1, "parameters": 2},
- "FunctionExpression": {"body": 1, "parameters": 2},
- "CallExpression": {"arguments": 2},
- "ArrayExpression": 1,
- "ObjectExpression": 1,
- "SwitchCase": 1
+ 'indent': ['error', 2, {
+ MemberExpression: 2,
+ FunctionDeclaration: {body: 1, parameters: 2},
+ FunctionExpression: {body: 1, parameters: 2},
+ CallExpression: {arguments: 2},
+ ArrayExpression: 1,
+ ObjectExpression: 1,
+ SwitchCase: 1,
}],
// https://eslint.org/docs/rules/keyword-spacing
- "keyword-spacing": ["error", {"after": true, "before": true}],
+ 'keyword-spacing': ['error', {after: true, before: true}],
// https://eslint.org/docs/rules/lines-between-class-members
- "lines-between-class-members": ["error", "always"],
+ 'lines-between-class-members': ['error', 'always'],
// https://eslint.org/docs/rules/max-len
- "max-len": [
- "error",
+ 'max-len': [
+ 'error',
80,
2,
{
- "ignoreComments": true,
- "ignorePattern": "^import .*;$"
- }
+ ignoreComments: true,
+ ignorePattern: '^import .*;$',
+ },
],
// https://eslint.org/docs/rules/new-cap
- "new-cap": ["error", {
- "capIsNewExceptions": ["Polymer", "GestureEventListeners"],
- "capIsNewExceptionPattern": "^.*Mixin$"
+ 'new-cap': ['error', {
+ capIsNewExceptions: ['Polymer', 'GestureEventListeners'],
+ capIsNewExceptionPattern: '^.*Mixin$',
}],
// https://eslint.org/docs/rules/no-console
- "no-console": ["error", { allow: ["warn", "error", "info", "assert", "group", "groupEnd"] }],
+ 'no-console': [
+ 'error',
+ {allow: ['warn', 'error', 'info', 'assert', 'group', 'groupEnd']},
+ ],
// https://eslint.org/docs/rules/no-multiple-empty-lines
- "no-multiple-empty-lines": ["error", {"max": 1}],
+ 'no-multiple-empty-lines': ['error', {max: 1}],
// https://eslint.org/docs/rules/no-prototype-builtins
- "no-prototype-builtins": "off",
+ 'no-prototype-builtins': 'off',
// https://eslint.org/docs/rules/no-redeclare
- "no-redeclare": "off",
+ 'no-redeclare': 'off',
// https://eslint.org/docs/rules/no-trailing-spaces
- "no-trailing-spaces": "error",
+ 'no-trailing-spaces': 'error',
// https://eslint.org/docs/rules/no-irregular-whitespace
- "no-irregular-whitespace": "error",
+ 'no-irregular-whitespace': 'error',
// https://eslint.org/docs/rules/array-callback-return
- "array-callback-return": ['error', { allowImplicit: true }],
+ 'array-callback-return': ['error', {allowImplicit: true}],
// https://eslint.org/docs/rules/no-restricted-syntax
- "no-restricted-syntax": [
- "error",
+ 'no-restricted-syntax': [
+ 'error',
{
- "selector": "ExpressionStatement > CallExpression > MemberExpression[object.name='test'][property.name='only']",
- "message": "Remove test.only."
+ selector: 'ExpressionStatement > CallExpression > ' +
+ 'MemberExpression[object.name=\'test\'][property.name=\'only\']',
+ message: 'Remove test.only.',
},
{
- "selector": "ExpressionStatement > CallExpression > MemberExpression[object.name='suite'][property.name='only']",
- "message": "Remove suite.only."
- }
+ selector: 'ExpressionStatement > CallExpression > ' +
+ 'MemberExpression[object.name=\'suite\'][property.name=\'only\']',
+ message: 'Remove suite.only.',
+ },
],
// no-undef disables global variable.
// "globals" declares allowed global variables.
// https://eslint.org/docs/rules/no-undef
- "no-undef": ["error"],
+ 'no-undef': ['error'],
// https://eslint.org/docs/rules/no-useless-escape
- "no-useless-escape": "off",
+ 'no-useless-escape': 'off',
// https://eslint.org/docs/rules/no-var
- "no-var": "error",
+ 'no-var': 'error',
// https://eslint.org/docs/rules/operator-linebreak
- "operator-linebreak": "off",
+ 'operator-linebreak': 'off',
// https://eslint.org/docs/rules/object-shorthand
- "object-shorthand": ["error", "always"],
+ 'object-shorthand': ['error', 'always'],
// https://eslint.org/docs/rules/padding-line-between-statements
- "padding-line-between-statements": [
- "error",
+ 'padding-line-between-statements': [
+ 'error',
{
- "blankLine": "always",
- "prev": "class",
- "next": "*"
+ blankLine: 'always',
+ prev: 'class',
+ next: '*',
},
{
- "blankLine": "always",
- "prev": "*",
- "next": "class"
- }
+ blankLine: 'always',
+ prev: '*',
+ next: 'class',
+ },
],
// https://eslint.org/docs/rules/prefer-arrow-callback
- "prefer-arrow-callback": "error",
+ 'prefer-arrow-callback': 'error',
// https://eslint.org/docs/rules/prefer-const
- "prefer-const": "error",
+ 'prefer-const': 'error',
// https://eslint.org/docs/rules/prefer-promise-reject-errors
- "prefer-promise-reject-errors": "error",
+ 'prefer-promise-reject-errors': 'error',
// https://eslint.org/docs/rules/prefer-spread
- "prefer-spread": "error",
+ 'prefer-spread': 'error',
// https://eslint.org/docs/rules/prefer-object-spread
- "prefer-object-spread": "error",
+ 'prefer-object-spread': 'error',
// https://eslint.org/docs/rules/quote-props
- "quote-props": ["error", "consistent-as-needed"],
+ 'quote-props': ['error', 'consistent-as-needed'],
// https://eslint.org/docs/rules/semi
- "semi": ["error", "always"],
+ 'semi': ['error', 'always'],
// https://eslint.org/docs/rules/template-curly-spacing
- "template-curly-spacing": "error",
+ 'template-curly-spacing': 'error',
// https://eslint.org/docs/rules/require-jsdoc
- "require-jsdoc": 0,
+ 'require-jsdoc': 0,
// https://eslint.org/docs/rules/valid-jsdoc
- "valid-jsdoc": 0,
+ 'valid-jsdoc': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-alignment
- "jsdoc/check-alignment": 2,
+ 'jsdoc/check-alignment': 2,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-examples
- "jsdoc/check-examples": 0,
+ 'jsdoc/check-examples': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-indentation
- "jsdoc/check-indentation": 0,
+ 'jsdoc/check-indentation': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-param-names
- "jsdoc/check-param-names": 0,
+ 'jsdoc/check-param-names': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-syntax
- "jsdoc/check-syntax": 0,
+ 'jsdoc/check-syntax': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-tag-names
- "jsdoc/check-tag-names": 0,
+ 'jsdoc/check-tag-names': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-types
- "jsdoc/check-types": 0,
+ 'jsdoc/check-types': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-implements-on-classes
- "jsdoc/implements-on-classes": 2,
+ 'jsdoc/implements-on-classes': 2,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-match-description
- "jsdoc/match-description": 0,
+ 'jsdoc/match-description': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-newline-after-description
- "jsdoc/newline-after-description": 2,
+ 'jsdoc/newline-after-description': 2,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-types
- "jsdoc/no-types": 0,
+ 'jsdoc/no-types': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-undefined-types
- "jsdoc/no-undefined-types": 0,
+ 'jsdoc/no-undefined-types': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-description
- "jsdoc/require-description": 0,
+ 'jsdoc/require-description': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-description-complete-sentence
- "jsdoc/require-description-complete-sentence": 0,
+ 'jsdoc/require-description-complete-sentence': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-example
- "jsdoc/require-example": 0,
+ 'jsdoc/require-example': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-hyphen-before-param-description
- "jsdoc/require-hyphen-before-param-description": 0,
+ 'jsdoc/require-hyphen-before-param-description': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-jsdoc
- "jsdoc/require-jsdoc": 0,
+ 'jsdoc/require-jsdoc': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param
- "jsdoc/require-param": 0,
+ 'jsdoc/require-param': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-description
- "jsdoc/require-param-description": 0,
+ 'jsdoc/require-param-description': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-name
- "jsdoc/require-param-name": 2,
+ 'jsdoc/require-param-name': 2,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns
- "jsdoc/require-returns": 0,
+ 'jsdoc/require-returns': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-check
- "jsdoc/require-returns-check": 0,
+ 'jsdoc/require-returns-check': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-description
- "jsdoc/require-returns-description": 0,
+ 'jsdoc/require-returns-description': 0,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-valid-types
- "jsdoc/valid-types": 2,
+ 'jsdoc/valid-types': 2,
// https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-file-overview
- "jsdoc/require-file-overview": ["error", {
- "tags": {
- "license": {
- "mustExist": true,
- "preventDuplicates": true
- }
- }
+ 'jsdoc/require-file-overview': ['error', {
+ tags: {
+ license: {
+ mustExist: true,
+ preventDuplicates: true,
+ },
+ },
}],
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-self-import.md
- "import/no-self-import": 2,
+ 'import/no-self-import': 2,
// The no-cycle rule is slow, because it doesn't cache dependencies.
// Disable it.
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-cycle.md
- "import/no-cycle": 0,
+ 'import/no-cycle': 0,
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-useless-path-segments.md
- "import/no-useless-path-segments": 2,
+ 'import/no-useless-path-segments': 2,
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md
- "import/no-unused-modules": 2,
+ 'import/no-unused-modules': 2,
// https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-default-export.md
- "import/no-default-export": 2,
+ 'import/no-default-export': 2,
// Prevents certain identifiers being used.
// Prefer flush() over flushAsynchronousOperations().
- "id-blacklist": ["error", "flushAsynchronousOperations"],
+ 'id-blacklist': ['error', 'flushAsynchronousOperations'],
},
// List of allowed globals in all files
- "globals": {
+ globals: {
// Polygerrit global variables.
// You must not add anything new in this list!
// Instead export variables from modules
@@ -240,156 +245,166 @@
// Global variables from 3rd party libraries.
// You should not add anything in this list, always try to import
// If import is not possible - you can extend this list
- "ShadyCSS": "readonly",
- "linkify": "readonly",
- "security": "readonly",
+ ShadyCSS: 'readonly',
+ linkify: 'readonly',
+ security: 'readonly',
},
- "overrides": [
+ overrides: [
{
- // .js-only rules
- "files": ["**/*.js"],
- "rules": {
- // https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-type
- "jsdoc/require-param-type": 2,
- // https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-type
- "jsdoc/require-returns-type": 2,
- // The rule is required for .js files only, because typescript compiler
- // always checks import.
- "import/no-unresolved": 2,
- "import/named": 2,
+ files: ['.eslintrc.js', '.eslintrc-bazel.js'],
+ env: {
+ browser: false,
+ es6: true,
+ node: true,
},
- "globals": {
- "goog": "readonly",
- }
},
{
- "files": ["**/*.ts"],
- "extends": [require.resolve("gts/.eslintrc.json")],
- "rules": {
- "no-restricted-imports": ["error", {
- name: "@polymer/decorators/lib/decorators",
- message: "Use @polymer/decorators instead",
+ // .js-only rules
+ files: ['**/*.js'],
+ rules: {
+ // https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-type
+ 'jsdoc/require-param-type': 2,
+ // https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns-type
+ 'jsdoc/require-returns-type': 2,
+ // The rule is required for .js files only, because typescript compiler
+ // always checks import.
+ 'import/no-unresolved': 2,
+ 'import/named': 2,
+ },
+ globals: {
+ goog: 'readonly',
+ },
+ },
+ {
+ files: ['**/*.ts'],
+ extends: [require.resolve('gts/.eslintrc.json')],
+ rules: {
+ 'no-restricted-imports': ['error', {
+ name: '@polymer/decorators/lib/decorators',
+ message: 'Use @polymer/decorators instead',
}],
- "@typescript-eslint/no-explicit-any": "error",
+ '@typescript-eslint/no-explicit-any': 'error',
// The following rules is required to match internal google rules
- "@typescript-eslint/restrict-plus-operands": "error",
- "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
+ '@typescript-eslint/restrict-plus-operands': 'error',
+ '@typescript-eslint/no-unused-vars': [
+ 'error',
+ {argsIgnorePattern: '^_'},
+ ],
// https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-unsupported-features/node-builtins.md
- "node/no-unsupported-features/node-builtins": "off",
+ 'node/no-unsupported-features/node-builtins': 'off',
// Disable no-invalid-this for ts files, because it incorrectly reports
// errors in some cases (see https://github.com/typescript-eslint/typescript-eslint/issues/491)
// At the same time, we are using typescript in a strict mode and
// it catches almost all errors related to invalid usage of this.
- "no-invalid-this": "off",
+ 'no-invalid-this': 'off',
- "node/no-extraneous-import": "off",
+ 'node/no-extraneous-import': 'off',
// Typescript already checks for undef
- "no-undef": "off",
+ 'no-undef': 'off',
- "jsdoc/no-types": 2,
+ 'jsdoc/no-types': 2,
},
- "parserOptions": {
- "project": path.resolve(__dirname, "./tsconfig_eslint.json"),
- }
- },
- {
- "files": ["*_test.ts"],
- "rules": {
- "@typescript-eslint/no-explicit-any": "off"
+ parserOptions: {
+ project: path.resolve(__dirname, './tsconfig_eslint.json'),
},
},
{
- "files": ["*.html", "test.js", "test-infra.js"],
- "rules": {
- "jsdoc/require-file-overview": "off"
+ files: ['*_test.ts'],
+ rules: {
+ '@typescript-eslint/no-explicit-any': 'off',
},
},
{
- "files": [
- "*.html",
- "*_test.js",
- "a11y-test-utils.js",
+ files: ['*.html', 'test.js', 'test-infra.js'],
+ rules: {
+ 'jsdoc/require-file-overview': 'off',
+ },
+ },
+ {
+ files: [
+ '*.html',
+ '*_test.js',
+ 'a11y-test-utils.js',
],
// Additional global variables allowed in tests
- "globals": {
+ globals: {
// Global variables from 3rd party test libraries/frameworks.
// You can extend this list if you want to use other global
// variables from these libraries and import is not possible
- "MockInteractions": "readonly",
- "_": "readonly",
- "axs": "readonly",
- "a11ySuite": "readonly",
- "assert": "readonly",
- "expect": "readonly",
- "fixture": "readonly",
- "flush": "readonly",
- "flushAsynchronousOperations": "readonly",
- "setup": "readonly",
- "sinon": "readonly",
- "stub": "readonly",
- "suite": "readonly",
- "suiteSetup": "readonly",
- "suiteTeardown": "readonly",
- "teardown": "readonly",
- "test": "readonly",
- "fixtureFromElement": "readonly",
- "fixtureFromTemplate": "readonly",
- }
+ MockInteractions: 'readonly',
+ _: 'readonly',
+ axs: 'readonly',
+ a11ySuite: 'readonly',
+ assert: 'readonly',
+ expect: 'readonly',
+ fixture: 'readonly',
+ flush: 'readonly',
+ setup: 'readonly',
+ sinon: 'readonly',
+ stub: 'readonly',
+ suite: 'readonly',
+ suiteSetup: 'readonly',
+ suiteTeardown: 'readonly',
+ teardown: 'readonly',
+ test: 'readonly',
+ fixtureFromElement: 'readonly',
+ fixtureFromTemplate: 'readonly',
+ },
},
{
- "files": "import-href.js",
- "globals": {
- "HTMLImports": "readonly",
- }
+ files: 'import-href.js',
+ globals: {
+ HTMLImports: 'readonly',
+ },
},
{
- "files": ["samples/**/*.js"],
- "globals": {
+ files: ['samples/**/*.js'],
+ globals: {
// Settings for samples. You can add globals here if you want to use it
- "Gerrit": "readonly",
- "Polymer": "readonly",
- }
+ Gerrit: 'readonly',
+ Polymer: 'readonly',
+ },
},
{
- "files": ["test/functional/**/*.js"],
+ files: ['test/functional/**/*.js'],
// Settings for functional tests. These scripts are node scripts.
// Turn off "no-undef" to allow any global variable
- "env": {
- "browser": false,
- "node": true,
- "es6": false
+ env: {
+ browser: false,
+ node: true,
+ es6: false,
},
- "rules": {
- "no-undef": "off",
- }
+ rules: {
+ 'no-undef': 'off',
+ },
},
{
- "files": ["*_html.js", "gr-icons.js", "*-theme.js", "*-styles.js"],
- "rules": {
- "max-len": "off"
- }
+ files: ['*_html.js', 'gr-icons.js', '*-theme.js', '*-styles.js'],
+ rules: {
+ 'max-len': 'off',
+ },
},
{
- "files": ["*_html.js"],
- "rules": {
- "prettier/prettier": ["error", {
- "bracketSpacing": false,
- "singleQuote": true,
- }]
- }
- }
+ files: ['*_html.js'],
+ rules: {
+ 'prettier/prettier': ['error', {
+ bracketSpacing: false,
+ singleQuote: true,
+ }],
+ },
+ },
],
- "plugins": [
- "html",
- "jsdoc",
- "import",
- "prettier"
+ plugins: [
+ 'html',
+ 'jsdoc',
+ 'import',
+ 'prettier',
],
- "settings": {
- "html/report-bad-indent": "error",
- "import/resolver": {
- "node": {},
+ settings: {
+ 'html/report-bad-indent': 'error',
+ 'import/resolver': {
+ node: {},
[path.resolve(__dirname, './.eslint-ts-resolver.js')]: {},
},
},
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
index 9afc5f4..c45e801 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
@@ -227,7 +227,9 @@
preferences && preferences.legacycid_in_change_table
);
if (preferences.change_table && preferences.change_table.length > 0) {
- const prefColumns = this.getVisibleColumns(preferences.change_table);
+ const prefColumns = this.renameProjectToRepoColumn(
+ preferences.change_table
+ );
this.visibleChangeTableColumns = this.getEnabledColumns(
prefColumns,
config,
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index febf18a..fdf2811 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -38,11 +38,7 @@
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {appContext} from '../../../services/app-context';
-import {
- fetchChangeUpdates,
- patchNumEquals,
- CURRENT,
-} from '../../../utils/patch-set-util';
+import {fetchChangeUpdates, CURRENT} from '../../../utils/patch-set-util';
import {
changeIsOpen,
isOwner,
@@ -1153,7 +1149,7 @@
_getRevision(change: ChangeViewChangeInfo, patchNum?: PatchSetNum) {
for (const rev of Object.values(change.revisions)) {
- if (patchNumEquals(rev._number, patchNum)) {
+ if (rev._number === patchNum) {
return rev;
}
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
index da214d9..f7bca82 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.js
@@ -258,7 +258,7 @@
rev2: revObj,
},
};
- assert.deepEqual(element._getRevision(change, '2'), revObj);
+ assert.deepEqual(element._getRevision(change, 2), revObj);
});
test('_actionComparator sort order', () => {
@@ -742,11 +742,11 @@
const changes = [
{
change_id: '12345678901234', topic: 'T', subject: 'random',
- project: 'A',
+ project: 'A', status: 'MERGED',
},
{
change_id: '23456', topic: 'T', subject: 'a'.repeat(100),
- project: 'B',
+ project: 'B', status: 'NEW',
},
];
setup(done => {
@@ -769,8 +769,8 @@
flush(() => {
const changesTable = dialog.shadowRoot.querySelector('table');
const headers = Array.from(changesTable.querySelectorAll('th'));
- const expectedHeadings = ['Change', 'Subject', 'Project',
- 'Status', ''];
+ const expectedHeadings = ['', 'Change', 'Status', 'Subject',
+ 'Project', 'Progress', ''];
const headings = headers.map(header => header.innerText);
assert.equal(headings.length, expectedHeadings.length);
for (let i = 0; i < headings.length; i++) {
@@ -779,7 +779,7 @@
const changeRows = changesTable.querySelectorAll('tbody > tr');
const change = Array.from(changeRows[0].querySelectorAll('td'))
.map(e => e.innerText);
- const expectedChange = ['1234567890', 'random', 'A',
+ const expectedChange = ['', '1234567890', 'MERGED', 'random', 'A',
'NOT STARTED', ''];
for (let i = 0; i < change.length; i++) {
assert.equal(change[i].trim(), expectedChange[i]);
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
index 3ee3470..ab7d09b 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
@@ -360,13 +360,6 @@
);
});
- test('_getNonOwnerRole null for uploader with no current rev', () => {
- delete change!.current_revision;
- assert.isNotOk(
- element._getNonOwnerRole(change, element._CHANGE_ROLE.UPLOADER)
- );
- });
-
test('_computeShowRoleClass show uploader', () => {
assert.equal(
element._computeShowRoleClass(change, element._CHANGE_ROLE.UPLOADER),
@@ -407,26 +400,12 @@
);
});
- test('_getNonOwnerRole null for committer with no current rev', () => {
- delete change!.current_revision;
- assert.isNotOk(
- element._getNonOwnerRole(change, element._CHANGE_ROLE.COMMITTER)
- );
- });
-
test('_getNonOwnerRole null for committer with no commit', () => {
delete change!.revisions.rev1.commit;
assert.isNotOk(
element._getNonOwnerRole(change, element._CHANGE_ROLE.COMMITTER)
);
});
-
- test('_getNonOwnerRole null for committer with no committer', () => {
- delete change!.revisions.rev1.commit!.committer;
- assert.isNotOk(
- element._getNonOwnerRole(change, element._CHANGE_ROLE.COMMITTER)
- );
- });
});
suite('role=author', () => {
@@ -445,26 +424,12 @@
);
});
- test('_getNonOwnerRole null for author with no current rev', () => {
- delete change!.current_revision;
- assert.isNotOk(
- element._getNonOwnerRole(change, element._CHANGE_ROLE.AUTHOR)
- );
- });
-
test('_getNonOwnerRole null for author with no commit', () => {
delete change!.revisions.rev1.commit;
assert.isNotOk(
element._getNonOwnerRole(change, element._CHANGE_ROLE.AUTHOR)
);
});
-
- test('_getNonOwnerRole null for author with no author', () => {
- delete change!.revisions.rev1.commit!.author;
- assert.isNotOk(
- element._getNonOwnerRole(change, element._CHANGE_ROLE.AUTHOR)
- );
- });
});
});
@@ -609,7 +574,6 @@
element.revision = undefined;
assert.equal(element._currentParents[0].commit, '111');
element.change = createParsedChange();
- delete element.change.current_revision;
assert.deepEqual(element._currentParents, []);
});
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 950fbf3..126d017 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -69,7 +69,6 @@
fetchChangeUpdates,
hasEditBasedOnCurrentPatchSet,
hasEditPatchsetLoaded,
- patchNumEquals,
PatchSet,
} from '../../../utils/patch-set-util';
import {changeStatuses, changeStatusString} from '../../../utils/change-util';
@@ -145,6 +144,7 @@
EditableContentSaveEvent,
OpenFixPreviewEvent,
SwitchTabEvent,
+ ThreadListModifiedEvent,
} from '../../../types/events';
import {GrButton} from '../../shared/gr-button/gr-button';
import {GrMessagesList} from '../gr-messages-list/gr-messages-list';
@@ -600,6 +600,11 @@
this._handleReloadCommentThreads()
);
+ this.addEventListener(
+ 'thread-list-modified',
+ (e: ThreadListModifiedEvent) => this._handleReloadDiffComments(e)
+ );
+
this.addEventListener('open-reply-dialog', () => this._openReplyDialog());
}
@@ -1650,7 +1655,7 @@
if (!this._change) throw new Error('missing required change property');
if (!this._patchRange)
throw new Error('missing required _patchRange property');
- if (patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)) {
+ if (this._patchRange.basePatchNum === ParentPatchSetNum) {
fireAlert(this, 'Base is already selected.');
return;
}
@@ -1664,7 +1669,7 @@
if (!this._change) throw new Error('missing required change property');
if (!this._patchRange)
throw new Error('missing required _patchRange property');
- if (patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)) {
+ if (this._patchRange.basePatchNum === ParentPatchSetNum) {
fireAlert(this, 'Left is already base.');
return;
}
@@ -1679,7 +1684,7 @@
if (!this._patchRange)
throw new Error('missing required _patchRange property');
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
- if (patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ if (this._patchRange.patchNum === latestPatchNum) {
fireAlert(this, 'Latest is already selected.');
return;
}
@@ -1698,7 +1703,7 @@
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
if (!this._patchRange)
throw new Error('missing required _patchRange property');
- if (patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ if (this._patchRange.patchNum === latestPatchNum) {
fireAlert(this, 'Right is already latest.');
return;
}
@@ -1718,8 +1723,8 @@
throw new Error('missing required _patchRange property');
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
if (
- patchNumEquals(this._patchRange.patchNum, latestPatchNum) &&
- patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)
+ this._patchRange.patchNum === latestPatchNum &&
+ this._patchRange.basePatchNum === ParentPatchSetNum
) {
fireAlert(this, 'Already diffing base against latest.');
return;
@@ -1961,7 +1966,7 @@
if (
!this._patchRange ||
!this._patchRange.patchNum ||
- patchNumEquals(this._patchRange.patchNum, currentRevision._number)
+ this._patchRange.patchNum === currentRevision._number
) {
// CommitInfo.commit is optional, and may need patching.
if (currentRevision.commit && !currentRevision.commit.commit) {
@@ -2561,7 +2566,7 @@
}
const patchRange = patchRangeRecord.base || {};
- return patchNumEquals(patchRange.patchNum, EditPatchSetNum);
+ return patchRange.patchNum === EditPatchSetNum;
}
_handleFileActionTap(e: CustomEvent<{path: string; action: string}>) {
@@ -2645,10 +2650,7 @@
throw new Error('missing required _patchRange property');
let patchNum;
if (
- !patchNumEquals(
- this._patchRange.patchNum,
- computeLatestPatchNum(this._allPatchSets)
- )
+ !(this._patchRange.patchNum === computeLatestPatchNum(this._allPatchSets))
) {
patchNum = this._patchRange.patchNum;
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index cb8ed6a..4fcc9fe 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -646,7 +646,6 @@
change-num="[[_changeNum]]"
logged-in="[[_loggedIn]]"
only-show-robot-comments-with-human-reply=""
- on-thread-list-modified="_handleReloadDiffComments"
unresolved-only
></gr-thread-list>
</template>
@@ -674,7 +673,6 @@
logged-in="[[_loggedIn]]"
hide-toggle-buttons
empty-thread-msg="[[_messages.NO_ROBOT_COMMENTS_THREADS_MSG]]"
- on-thread-list-modified="_handleReloadDiffComments"
>
</gr-thread-list>
<template is="dom-if" if="[[_showRobotCommentsButton]]">
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index 2d90c0b..c4526bb 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -31,6 +31,7 @@
RepoName,
BranchName,
CommitId,
+ ChangeInfoId,
} from '../../../types/common';
import {ReportingService} from '../../../services/gr-reporting/gr-reporting';
import {customElement, property, observe} from '@polymer/decorators';
@@ -40,6 +41,7 @@
} from '../../shared/gr-autocomplete/gr-autocomplete';
import {HttpMethod, ChangeStatus} from '../../../constants/constants';
import {hasOwnProperty} from '../../../utils/common-util';
+import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
const SUGGESTIONS_LIMIT = 15;
const CHANGE_SUBJECT_LIMIT = 50;
@@ -48,11 +50,18 @@
TOPIC,
}
+// These values are directly displayed in the dialog to show progress of change
+enum ProgressStatus {
+ RUNNING = 'RUNNING',
+ FAILED = 'FAILED',
+ NOT_STARTED = 'NOT STARTED',
+ SUCCESSFUL = 'SUCCESSFUL',
+}
+
type Statuses = {[changeId: string]: Status};
-// TODO(TS): maybe convert status to an enum
interface Status {
- status: string;
+ status: ProgressStatus;
msg?: string;
}
@@ -139,6 +148,8 @@
@property({type: Object})
reporting: ReportingService;
+ private selectedChangeIds = new Set<ChangeInfoId>();
+
private restApiService = appContext.restApiService;
constructor() {
@@ -154,6 +165,7 @@
const projects: {[projectName: string]: boolean} = {};
this._duplicateProjectChanges = false;
changes.forEach(change => {
+ this.selectedChangeIds.add(change.id);
if (projects[change.project]) {
this._duplicateProjectChanges = true;
}
@@ -171,6 +183,19 @@
);
}
+ _isChangeSelected(changeId: ChangeInfoId) {
+ return this.selectedChangeIds.has(changeId);
+ }
+
+ _toggleChangeSelected(e: Event) {
+ const changeId = ((dom(e) as EventApi).localTarget as HTMLElement).dataset[
+ 'item'
+ ]! as ChangeInfoId;
+ if (this.selectedChangeIds.has(changeId))
+ this.selectedChangeIds.delete(changeId);
+ else this.selectedChangeIds.add(changeId);
+ }
+
_computeTopicErrorMessage(duplicateProjectChanges: boolean) {
if (duplicateProjectChanges) {
return 'Two changes cannot be of the same project';
@@ -183,18 +208,19 @@
}
_computeStatus(change: ChangeInfo, statuses: Statuses) {
- if (!change || !statuses || !statuses[change.id]) return 'NOT STARTED';
+ if (!change || !statuses || !statuses[change.id])
+ return ProgressStatus.NOT_STARTED;
return statuses[change.id].status;
}
_computeStatusClass(change: ChangeInfo, statuses: Statuses) {
if (!change || !statuses || !statuses[change.id]) return '';
- return statuses[change.id].status === 'FAILED' ? 'error' : '';
+ return statuses[change.id].status === ProgressStatus.FAILED ? 'error' : '';
}
_computeError(change: ChangeInfo, statuses: Statuses) {
if (!change || !statuses || !statuses[change.id]) return '';
- if (statuses[change.id].status === 'FAILED') {
+ if (statuses[change.id].status === ProgressStatus.FAILED) {
return statuses[change.id].msg;
}
return '';
@@ -212,7 +238,7 @@
_computeCancelLabel(statuses: Statuses) {
const isRunningChange = Object.values(statuses).some(
- v => v.status === 'RUNNING'
+ v => v.status === ProgressStatus.RUNNING
);
return isRunningChange ? 'Close' : 'Cancel';
}
@@ -220,14 +246,16 @@
_computeDisableCherryPick(
cherryPickType: CherryPickType,
duplicateProjectChanges: boolean,
- statuses: Statuses
+ statuses: Statuses,
+ branch?: BranchName
) {
+ if (!branch) return true;
const duplicateProject =
cherryPickType === CherryPickType.TOPIC && duplicateProjectChanges;
if (duplicateProject) return true;
if (!statuses) return false;
const isRunningChange = Object.values(statuses).some(
- v => v.status === 'RUNNING'
+ v => v.status === ProgressStatus.RUNNING
);
return isRunningChange;
}
@@ -280,14 +308,22 @@
_handleCherryPickFailed(change: ChangeInfo, response?: Response | null) {
if (!response) return;
response.text().then((errText: string) => {
- this.updateStatus(change, {status: 'FAILED', msg: errText});
+ this.updateStatus(change, {status: ProgressStatus.FAILED, msg: errText});
});
}
_handleCherryPickTopic() {
- const topic = this._generateRandomCherryPickTopic(this.changes[0]);
- this.changes.forEach(change => {
- this.updateStatus(change, {status: 'RUNNING'});
+ const changes = this.changes.filter(change =>
+ this.selectedChangeIds.has(change.id)
+ );
+ if (!changes.length) {
+ const errorSpan = this.shadowRoot?.querySelector('.error-message');
+ errorSpan!.innerHTML = 'No change selected';
+ return;
+ }
+ const topic = this._generateRandomCherryPickTopic(changes[0]);
+ changes.forEach(change => {
+ this.updateStatus(change, {status: ProgressStatus.RUNNING});
const payload = {
destination: this.branch,
base: null,
@@ -310,9 +346,9 @@
handleError
)
.then(() => {
- this.updateStatus(change, {status: 'SUCCESSFUL'});
+ this.updateStatus(change, {status: ProgressStatus.SUCCESSFUL});
const failedOrPending = Object.values(this._statuses).find(
- v => v.status !== 'SUCCESSFUL'
+ v => v.status !== ProgressStatus.SUCCESSFUL
);
if (!failedOrPending) {
/* This needs some more work, as the new topic may not always be
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts
index f784425..4de395c 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_html.ts
@@ -85,7 +85,7 @@
<gr-dialog
confirm-label="Cherry Pick"
cancel-label="[[_computeCancelLabel(_statuses)]]"
- disabled$="[[_computeDisableCherryPick(_cherryPickType, _duplicateProjectChanges, _statuses)]]"
+ disabled$="[[_computeDisableCherryPick(_cherryPickType, _duplicateProjectChanges, _statuses, branch)]]"
on-confirm="_handleConfirmTap"
on-cancel="_handleCancelTap"
>
@@ -179,10 +179,12 @@
<table>
<thead>
<tr>
+ <th></th>
<th>Change</th>
+ <th>Status</th>
<th>Subject</th>
<th>Project</th>
- <th>Status</th>
+ <th>Progress</th>
<!-- Error Message -->
<th></th>
</tr>
@@ -190,7 +192,16 @@
<tbody>
<template is="dom-repeat" items="[[changes]]">
<tr>
+ <td>
+ <input
+ type="checkbox"
+ data-item$="[[item.id]]"
+ on-change="_toggleChangeSelected"
+ checked="[[_isChangeSelected(item.id)]]"
+ />
+ </td>
<td><span> [[_getChangeId(item)]] </span></td>
+ <td><span> [[item.status]] </span></td>
<td>
<span> [[_getTrimmedChangeSubject(item.subject)]] </span>
</td>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
index cc4bb8f..5564fcf 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
@@ -88,6 +88,7 @@
suite('cherry pick topic', () => {
const changes = [
{
+ id: '1234',
change_id: '12345678901234', topic: 'T', subject: 'random',
project: 'A',
_number: 1,
@@ -97,6 +98,7 @@
current_revision: 'a',
},
{
+ id: '5678',
change_id: '23456', topic: 'T', subject: 'a'.repeat(100),
project: 'B',
_number: 2,
@@ -109,6 +111,7 @@
setup(() => {
element.updateChanges(changes);
element._cherryPickType = CHERRY_PICK_TYPES.TOPIC;
+ flush();
});
test('cherry pick topic submit', done => {
@@ -129,6 +132,38 @@
});
});
+ test('deselecting a change removes it from being cherry picked', () => {
+ element.branch = 'master';
+ const executeChangeActionStub = sinon.stub(element.restApiService,
+ 'executeChangeAction').returns(Promise.resolve([]));
+ const checkboxes = element.shadowRoot.querySelectorAll(
+ 'input[type="checkbox"]');
+ assert.equal(checkboxes.length, 2);
+ assert.isTrue(checkboxes[0].checked);
+ MockInteractions.tap(checkboxes[0]);
+ MockInteractions.tap(element.shadowRoot.
+ querySelector('gr-dialog').$.confirm);
+ flush();
+ assert.equal(executeChangeActionStub.callCount, 1);
+ });
+
+ test('deselecting all change shows error message', () => {
+ element.branch = 'master';
+ const executeChangeActionStub = sinon.stub(element.restApiService,
+ 'executeChangeAction').returns(Promise.resolve([]));
+ const checkboxes = element.shadowRoot.querySelectorAll(
+ 'input[type="checkbox"]');
+ assert.equal(checkboxes.length, 2);
+ MockInteractions.tap(checkboxes[0]);
+ MockInteractions.tap(checkboxes[1]);
+ MockInteractions.tap(element.shadowRoot.
+ querySelector('gr-dialog').$.confirm);
+ flush();
+ assert.equal(executeChangeActionStub.callCount, 0);
+ assert.equal(element.shadowRoot.querySelector('.error-message').innerText
+ , 'No change selected');
+ });
+
test('_computeStatusClass', () => {
assert.equal(element._computeStatusClass({id: 1}, {1: {status: 'RUNNING'},
}), '');
@@ -139,6 +174,9 @@
test('submit button is blocked while cherry picks is running', done => {
const confirmButton = element.shadowRoot.querySelector('gr-dialog').$
.confirm;
+ assert.isTrue(confirmButton.hasAttribute('disabled'));
+ element.branch = 'b';
+ flush();
assert.isFalse(confirmButton.hasAttribute('disabled'));
element.updateStatus(changes[0], {status: 'RUNNING'});
flush(() => {
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
index 27d9756..5949513 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
@@ -20,7 +20,6 @@
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-download-dialog_html';
-import {patchNumEquals} from '../../../utils/patch-set-util';
import {changeBaseURL} from '../../../utils/change-util';
import {customElement, property, computed, observe} from '@polymer/decorators';
import {ChangeInfo, ServerInfo, PatchSetNum} from '../../../types/common';
@@ -72,7 +71,7 @@
}
for (const rev of Object.values(this.change.revisions || {})) {
- if (patchNumEquals(rev._number, this.patchNum)) {
+ if (rev._number === this.patchNum) {
const fetch = rev.fetch;
if (fetch) {
return Object.keys(fetch).sort();
@@ -113,7 +112,7 @@
if (!change || !selectedScheme) return [];
for (const rev of Object.values(change.revisions || {})) {
if (
- patchNumEquals(rev._number, patchNum) &&
+ rev._number === patchNum &&
rev &&
rev.fetch &&
hasOwnProperty(rev.fetch, selectedScheme)
@@ -171,7 +170,7 @@
let shortRev = '';
for (const rev in change.revisions) {
- if (patchNumEquals(change.revisions[rev]._number, patchNum)) {
+ if (change.revisions[rev]._number === patchNum) {
shortRev = rev.substr(0, 7);
break;
}
@@ -185,7 +184,7 @@
return false;
}
for (const rev of Object.values(change.revisions || {})) {
- if (patchNumEquals(rev._number, patchNum)) {
+ if (rev._number === patchNum) {
const parentLength =
rev.commit && rev.commit.parents ? rev.commit.parents.length : 0;
return parentLength === 0 || parentLength > 1;
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.ts
index e436325..52ec8af 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.ts
@@ -121,7 +121,7 @@
});
test('anchors use download attribute', () => {
- const anchors = Array.from(element.root?.querySelectorAll('a')!);
+ const anchors = Array.from(element.root!.querySelectorAll('a'));
assert.isTrue(!anchors.some(a => !a.hasAttribute('download')));
});
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
index 3c99648..146b3e2 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
@@ -35,7 +35,6 @@
import {
computeLatestPatchNum,
getRevisionByPatchNum,
- patchNumEquals,
PatchSet,
} from '../../../utils/patch-set-util';
import {property, computed, observe, customElement} from '@polymer/decorators';
@@ -321,8 +320,7 @@
_handlePatchChange(e: CustomEvent) {
const {basePatchNum, patchNum} = e.detail;
if (
- (patchNumEquals(basePatchNum, this.basePatchNum) &&
- patchNumEquals(patchNum, this.patchNum)) ||
+ (basePatchNum === this.basePatchNum && patchNum === this.patchNum) ||
!this.change
) {
return;
@@ -354,7 +352,7 @@
_computePatchInfoClass(patchNum?: PatchSetNum, allPatchSets?: PatchSet[]) {
const latestNum = computeLatestPatchNum(allPatchSets);
- if (patchNumEquals(patchNum, latestNum)) {
+ if (patchNum === latestNum) {
return '';
}
return 'patchInfoOldPatchSet';
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
index cee0262..b8670c0 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header_test.js
@@ -249,11 +249,11 @@
test('class is applied to file list on old patch set', () => {
const allPatchSets = [{num: 4}, {num: 2}, {num: 1}];
- assert.equal(element._computePatchInfoClass('1', allPatchSets),
+ assert.equal(element._computePatchInfoClass(1, allPatchSets),
'patchInfoOldPatchSet');
- assert.equal(element._computePatchInfoClass('2', allPatchSets),
+ assert.equal(element._computePatchInfoClass(2, allPatchSets),
'patchInfoOldPatchSet');
- assert.equal(element._computePatchInfoClass('4', allPatchSets), '');
+ assert.equal(element._computePatchInfoClass(4, allPatchSets), '');
});
suite('editMode behavior', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
index a25ff20..bc61dad 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
@@ -45,8 +45,12 @@
import {hasOwnProperty} from '../../../utils/common-util';
import {appContext} from '../../../services/app-context';
import {pluralize} from '../../../utils/string-util';
-import {fireEvent} from '../../../utils/event-util';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
+import {
+ computeAllPatchSets,
+ computeLatestPatchNum,
+ computePredecessor,
+} from '../../../utils/patch-set-util';
const PATCH_SET_PREFIX_PATTERN = /^(?:Uploaded\s*)?(?:P|p)atch (?:S|s)et \d+:\s*(.*)/;
const LABEL_TITLE_SCORE_PATTERN = /^(-?)([A-Za-z0-9-]+?)([+-]\d+)?[.]?$/;
@@ -226,15 +230,6 @@
return pluralize(threadsLength, 'comment');
}
- _onThreadListModified() {
- // TODO(taoalpha): this won't propagate the changes to the files
- // should consider replacing this with either top level events
- // or gerrit level events
-
- // emit the event so change-view can also get updated with latest changes
- fireEvent(this, 'comment-refresh');
- }
-
_computeMessageContentExpanded(content?: string, tag?: ReviewInputTag) {
return this._computeMessageContent(true, content, tag);
}
@@ -280,13 +275,20 @@
_handleViewPatchsetDiff(e: Event) {
if (!this.message || !this.change) return;
const match = this.message.message.match(/Uploaded patch set (\d+)./);
- if (!match || match.length < 1) return;
- const patchNum = Number(match[1]);
- if (isNaN(patchNum)) throw new Error('invalid patchnum in message');
+ let patchNum: PatchSetNum;
+ // Message is of the form "Commit Message was updated" or "Patchset X
+ // was rebased"
+ if (!match || match.length < 1) {
+ patchNum = computeLatestPatchNum(computeAllPatchSets(this.change))!;
+ } else {
+ if (isNaN(Number(match[1])))
+ throw new Error('invalid patchnum in message');
+ patchNum = Number(match[1]) as PatchSetNum;
+ }
GerritNav.navigateToChange(
this.change,
- patchNum as PatchSetNum,
- (patchNum === 1 ? 'PARENT' : patchNum - 1) as PatchSetNum
+ patchNum,
+ computePredecessor(patchNum)
);
// stop propagation to stop message expansion
e.stopPropagation();
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
index 815d8bb..57beacf 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_html.ts
@@ -256,7 +256,6 @@
change-num="[[changeNum]]"
logged-in="[[_loggedIn]]"
hide-toggle-buttons
- on-thread-list-modified="_onThreadListModified"
>
</gr-thread-list>
</template>
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
index 94507e6..facde01 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message_test.js
@@ -18,6 +18,7 @@
import '../../../test/common-test-setup-karma.js';
import './gr-message.js';
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {createChange, createRevisions} from '../../../test/test-data-generators.js';
const basicFixture = fixtureFromElement('gr-message');
@@ -232,7 +233,7 @@
suite('uploaded patchset X message navigates to X - 1 vs X', () => {
let navStub;
setup(() => {
- element.change = {changeNum: 12345};
+ element.change = {...createChange(), revisions: createRevisions(4)};
navStub = sinon.stub(GerritNav, 'navigateToChange');
});
@@ -241,7 +242,7 @@
message: 'Uploaded patch set 1.',
};
element._handleViewPatchsetDiff(new MouseEvent('click'));
- assert.isTrue(navStub.calledWithExactly({changeNum: 12345}, 1,
+ assert.isTrue(navStub.calledWithExactly(element.change, 1,
'PARENT'));
});
@@ -250,21 +251,21 @@
message: 'Uploaded patch set 2.',
};
element._handleViewPatchsetDiff(new MouseEvent('click'));
- assert.isTrue(navStub.calledWithExactly({changeNum: 12345}, 2, 1));
+ assert.isTrue(navStub.calledWithExactly(element.change, 2, 1));
element.message = {
message: 'Uploaded patch set 200.',
};
element._handleViewPatchsetDiff(new MouseEvent('click'));
- assert.isTrue(navStub.calledWithExactly({changeNum: 12345}, 200, 199));
+ assert.isTrue(navStub.calledWithExactly(element.change, 200, 199));
});
- test('invalid patchset does not cause navigation', () => {
+ test('Commit message updated', () => {
element.message = {
- message: 'Uploaded patch set XYZ.',
+ message: 'Commit message updated.',
};
element._handleViewPatchsetDiff(new MouseEvent('click'));
- assert.isFalse(navStub.called);
+ assert.isTrue(navStub.calledWithExactly(element.change, 4, 3));
});
});
diff --git a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
index fc6b5ba..e6c9f42 100644
--- a/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-related-changes-list/gr-related-changes-list.ts
@@ -25,7 +25,7 @@
import {htmlTemplate} from './gr-related-changes-list_html';
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {ChangeStatus} from '../../../constants/constants';
-import {patchNumEquals} from '../../../utils/patch-set-util';
+
import {changeIsOpen} from '../../../utils/change-util';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {customElement, observe, property} from '@polymer/decorators';
@@ -410,7 +410,7 @@
return [];
}
for (const rev in change.revisions) {
- if (patchNumEquals(change.revisions[rev]._number, patchNum)) {
+ if (change.revisions[rev]._number === patchNum) {
changeRevision = rev;
}
}
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index f4d698ea..b92f179 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -42,7 +42,6 @@
ReviewerState,
SpecialFilePath,
} from '../../../constants/constants';
-import {KnownExperimentId} from '../../../services/flags/flags';
import {fetchChangeUpdates} from '../../../utils/patch-set-util';
import {KeyboardShortcutMixin} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {accountKey, removeServiceUsers} from '../../../utils/account-util';
@@ -380,8 +379,6 @@
};
}
- _isPatchsetCommentsExperimentEnabled = false;
-
constructor() {
super();
this.filterReviewerSuggestion = this._filterReviewerSuggestionGenerator(
@@ -421,9 +418,6 @@
/** @override */
ready() {
super.ready();
- this._isPatchsetCommentsExperimentEnabled = this.flagsService.isEnabled(
- KnownExperimentId.PATCHSET_COMMENTS
- );
this.$.jsAPI.addElement(TargetElement.REPLY_DIALOG, this);
}
@@ -675,17 +669,13 @@
}
if (this.draft) {
- if (this._isPatchsetCommentsExperimentEnabled) {
- const comment: CommentInput = {
- message: this.draft,
- unresolved: !this._isResolvedPatchsetLevelComment,
- };
- reviewInput.comments = {
- [SpecialFilePath.PATCHSET_LEVEL_COMMENTS]: [comment],
- };
- } else {
- reviewInput.message = this.draft;
- }
+ const comment: CommentInput = {
+ message: this.draft,
+ unresolved: !this._isResolvedPatchsetLevelComment,
+ };
+ reviewInput.comments = {
+ [SpecialFilePath.PATCHSET_LEVEL_COMMENTS]: [comment],
+ };
}
const accountAdditions = new Map<AccountId | EmailAddress, boolean>();
@@ -1463,15 +1453,6 @@
return provider;
}
- _onThreadListModified() {
- // TODO(taoalpha): this won't propogate the changes to the files
- // should consider replacing this with either top level events
- // or gerrit level events
-
- // emit the event so change-view can also get updated with latest changes
- fireEvent(this, 'comment-refresh');
- }
-
reportAttentionSetChanges(
modified: boolean,
addedSet?: AttentionSetInput[],
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
index 0948c1e..15e461a 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_html.ts
@@ -303,16 +303,14 @@
</gr-endpoint-decorator>
</section>
<section class="previewContainer">
- <template is="dom-if" if="[[_isPatchsetCommentsExperimentEnabled]]">
- <label>
- <input
- id="resolvedPatchsetLevelCommentCheckbox"
- type="checkbox"
- checked="{{_isResolvedPatchsetLevelComment::change}}"
- />
- Resolved
- </label>
- </template>
+ <label>
+ <input
+ id="resolvedPatchsetLevelCommentCheckbox"
+ type="checkbox"
+ checked="{{_isResolvedPatchsetLevelComment::change}}"
+ />
+ Resolved
+ </label>
<label class="preview-formatting">
<input type="checkbox" checked="{{_previewFormatting::change}}" />
Preview formatting
@@ -357,7 +355,6 @@
change-num="[[change._number]]"
logged-in="true"
hide-toggle-buttons=""
- on-thread-list-modified="_onThreadListModified"
>
</gr-thread-list>
<span
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts
index ff30452..4976503 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.ts
@@ -33,6 +33,7 @@
import {ChangeInfo} from '../../../types/common';
import {CommentThread, isDraft, UIRobot} from '../../../utils/comment-util';
import {pluralize} from '../../../utils/string-util';
+import {fireThreadListModifiedEvent} from '../../../utils/event-util';
interface CommentThreadWithInfo {
thread: CommentThread;
@@ -421,11 +422,7 @@
}
_handleCommentsChanged(e: CustomEvent) {
- this.dispatchEvent(
- new CustomEvent('thread-list-modified', {
- detail: {rootId: e.detail.rootId, path: e.detail.path},
- })
- );
+ fireThreadListModifiedEvent(this, e.detail.rootId, e.detail.path);
}
_isOnParent(side?: CommentSide) {
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 07045cd..2f3d03c 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -46,10 +46,7 @@
WeblinkType,
} from '../gr-navigation/gr-navigation';
import {appContext} from '../../../services/app-context';
-import {
- convertToPatchSetNum,
- patchNumEquals,
-} from '../../../utils/patch-set-util';
+import {convertToPatchSetNum} from '../../../utils/patch-set-util';
import {customElement, property} from '@polymer/decorators';
import {assertNever} from '../../../utils/common-util';
import {
@@ -693,10 +690,7 @@
// Diffing a patch against itself is invalid, so if the base and revision
// patches are equal clear the base.
- if (
- params.patchNum &&
- patchNumEquals(params.basePatchNum, params.patchNum)
- ) {
+ if (params.patchNum && params.basePatchNum === params.patchNum) {
needsRedirect = true;
params.basePatchNum = null;
} else if (!hasPatchNum) {
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
index 9988116..5210616 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api.ts
@@ -18,7 +18,7 @@
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-comment-api_html';
-import {patchNumEquals, CURRENT} from '../../../utils/patch-set-util';
+import {CURRENT} from '../../../utils/patch-set-util';
import {customElement, property} from '@polymer/decorators';
import {
CommentBasics,
@@ -30,6 +30,7 @@
NumericChangeId,
PathToCommentsInfoMap,
FileInfo,
+ ParentPatchSetNum,
} from '../../../types/common';
import {hasOwnProperty} from '../../../utils/common-util';
import {
@@ -235,9 +236,7 @@
allComments = allComments.concat(drafts);
}
if (patchNum) {
- allComments = allComments.filter(c =>
- patchNumEquals(c.patch_set, patchNum)
- );
+ allComments = allComments.filter(c => c.patch_set === patchNum);
}
return allComments.map(c => {
return {...c};
@@ -284,7 +283,7 @@
getAllDraftsForPath(path: string, patchNum?: PatchSetNum): Comment[] {
let comments = this._drafts[path] || [];
if (patchNum) {
- comments = comments.filter(c => patchNumEquals(c.patch_set, patchNum));
+ comments = comments.filter(c => c.patch_set === patchNum);
}
return comments.map(c => {
return {...c, __draft: true};
@@ -369,6 +368,10 @@
* does not return the range of the ported thread and it becomes a file level
* thread.
*
+ * If a comment was created with Side=PARENT, then we only show this ported
+ * comment if Base is part of the patch range, always on the left side of
+ * the diff.
+ *
* @return only the ported threads for the specified file and patch range
*/
_getPortedCommentThreads(
@@ -407,15 +410,22 @@
return false;
}
- // TODO(dhruvsri): Add handling for thread.commentSide = PARENT
- if (thread.commentSide === CommentSide.PARENT) return false;
+ thread.diffSide = Side.RIGHT;
+ if (thread.commentSide === CommentSide.PARENT) {
+ // TODO(dhruvsri): Add handling for merge parents
+ if (
+ patchRange.basePatchNum !== ParentPatchSetNum ||
+ !!thread.mergeParentNum
+ )
+ return false;
+ thread.diffSide = Side.LEFT;
+ }
if (!isUnresolved(thread) && !isDraftThread(thread)) return false;
thread.range = portedComment.range;
thread.line = portedComment.line;
thread.ported = true;
- thread.diffSide = Side.RIGHT;
return true;
});
}
diff --git a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
index dd36613..e107c16 100644
--- a/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-comment-api/gr-comment-api_test.js
@@ -20,6 +20,7 @@
import {ChangeComments} from './gr-comment-api.js';
import {isInRevisionOfPatchRange, isInBaseOfPatchRange, isDraftThread, isUnresolved, createCommentThreads} from '../../../utils/comment-util.js';
import {createDraft, createComment, createChangeComments, createCommentThread} from '../../../test/test-data-generators.js';
+import {CommentSide, Side} from '../../../constants/constants.js';
const basicFixture = fixtureFromElement('gr-comment-api');
@@ -153,7 +154,7 @@
const comment1 = {
...createComment(),
unresolved: true,
- id: 'db977012_e1f13818',
+ id: '1',
line: 136,
patch_set: 2,
range: {
@@ -167,10 +168,22 @@
const comment2 = {
...createComment(),
patch_set: 2,
- id: 'ecf0b9fa_fe1a5f62',
+ id: '2',
line: 5,
};
+ const comment3 = {
+ ...createComment(),
+ side: CommentSide.PARENT,
+ line: 10,
+ unresolved: true,
+ };
+
+ const comment4 = {
+ ...comment3,
+ parent: -2,
+ };
+
const draft1 = {
...createDraft(),
id: 'db977012_e1f13828',
@@ -277,6 +290,74 @@
).length, 0);
});
+ test('comments with side=PARENT are ported over', () => {
+ changeComments = new ChangeComments(
+ {/* comments */
+ // comment left on Base
+ 'karma.conf.js': [comment3],
+ },
+ {}/* robot comments */,
+ {/* drafts */
+ 'karma.conf.js': [draft2],
+ },
+ {/* ported comments */
+ 'karma.conf.js': [{
+ ...comment3,
+ line: 31,
+ patch_set: 4,
+ }],
+ },
+ {}/* ported drafts */
+ );
+
+ const portedThreads = changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: 'PARENT'});
+ assert.equal(portedThreads.length, 1);
+ assert.equal(portedThreads[0].line, 31);
+ assert.equal(portedThreads[0].diffSide, Side.LEFT);
+
+ assert.equal(changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: -2}
+ ).length, 0);
+
+ assert.equal(changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: 2}
+ ).length, 0);
+ });
+
+ test('comments left on merge parent is not ported over', () => {
+ changeComments = new ChangeComments(
+ {/* comments */
+ // comment left on Base
+ 'karma.conf.js': [comment4],
+ },
+ {}/* robot comments */,
+ {/* drafts */
+ 'karma.conf.js': [draft2],
+ },
+ {/* ported comments */
+ 'karma.conf.js': [{
+ ...comment4,
+ line: 31,
+ patch_set: 4,
+ }],
+ },
+ {}/* ported drafts */
+ );
+
+ const portedThreads = changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: 'PARENT'});
+ assert.equal(portedThreads.length, 0);
+
+ assert.equal(changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: -2}
+ ).length, 0);
+
+ assert.equal(changeComments._getPortedCommentThreads(
+ {path: 'karma.conf.js'}, {patchNum: 4, basePatchNum: 2}
+ ).length, 0);
+ });
+
test('ported comments contribute to comment count', () => {
assert.equal(changeComments.computeCommentsString(
{basePatchNum: 'PARENT', patchNum: 2}, 'karma.conf.js',
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
index 601ea80..9574c1d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.ts
@@ -716,10 +716,19 @@
}
if (lineNumberEl) {
- for (const layer of this.layers) {
- if (typeof layer.annotate === 'function') {
- layer.annotate(contentText, lineNumberEl, line);
+ const ANNOTATE_MAX_LINE_LENGTH = 1000;
+ // For performance reason, we skip annotating long lines.
+ if (line.text.length < ANNOTATE_MAX_LINE_LENGTH) {
+ for (const layer of this.layers) {
+ if (typeof layer.annotate === 'function') {
+ layer.annotate(contentText, lineNumberEl, line);
+ }
}
+ } else {
+ const msg =
+ `A line is longer than ${ANNOTATE_MAX_LINE_LENGTH}.` +
+ ' Line annotation was skipped.';
+ console.warn(msg);
}
} else {
console.error('The lineNumberEl is null, skipping layer annotations.');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index ccfab4f..da50135 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -588,7 +588,7 @@
this._getIgnoreWhitespace(),
reject
)
- .then(resolve);
+ .then(diff => resolve(diff!)); // reject is called in case of error, so we can't get undefined here
});
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
index 2c050f9..d09c811 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.js
@@ -1040,6 +1040,7 @@
commentSide: CommentSide.REVISION,
path: '/p',
rootId: 'betsys_confession',
+ mergeParentNum: undefined,
comments: [{
id: 'betsys_confession',
path: '/p',
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index 828c53d..84b227b 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -44,7 +44,6 @@
import {
computeAllPatchSets,
computeLatestPatchNum,
- patchNumEquals,
PatchSet,
} from '../../../utils/patch-set-util';
import {
@@ -880,12 +879,10 @@
_displayDiffAgainstLatestToast(latestPatchNum?: PatchSetNum) {
if (!this._patchRange) return;
- const leftPatchset = patchNumEquals(
- this._patchRange.basePatchNum,
- ParentPatchSetNum
- )
- ? 'Base'
- : `Patchset ${this._patchRange.basePatchNum}`;
+ const leftPatchset =
+ this._patchRange.basePatchNum === ParentPatchSetNum
+ ? 'Base'
+ : `Patchset ${this._patchRange.basePatchNum}`;
fireAlert(
this,
`${leftPatchset} vs
@@ -896,12 +893,12 @@
_displayToasts() {
if (!this._patchRange) return;
- if (!patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)) {
+ if (this._patchRange.basePatchNum !== ParentPatchSetNum) {
this._displayDiffBaseAgainstLeftToast();
return;
}
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
- if (!patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ if (this._patchRange.patchNum !== latestPatchNum) {
this._displayDiffAgainstLatestToast(latestPatchNum);
return;
}
@@ -916,17 +913,17 @@
if (!hasOwnProperty(this._change.revisions, commitSha)) continue;
const revision = this._change.revisions[commitSha];
const patchNum = revision._number;
- if (patchNumEquals(patchNum, this._patchRange.patchNum)) {
+ if (patchNum === this._patchRange.patchNum) {
commit = commitSha as CommitId;
const commitObj = revision.commit;
const parents = commitObj?.parents || [];
if (
- patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum) &&
+ this._patchRange.basePatchNum === ParentPatchSetNum &&
parents.length
) {
baseCommit = parents[parents.length - 1].commit;
}
- } else if (patchNumEquals(patchNum, this._patchRange.basePatchNum)) {
+ } else if (patchNum === this._patchRange.basePatchNum) {
baseCommit = commitSha as CommitId;
}
}
@@ -1250,7 +1247,7 @@
if (!patchRange) return {patchNum, basePatchNum};
if (
patchRange.basePatchNum !== ParentPatchSetNum ||
- !patchNumEquals(patchRange.patchNum, latestPatchNum as PatchSetNum)
+ patchRange.patchNum !== latestPatchNum
) {
patchNum = patchRange.patchNum;
basePatchNum = patchRange.basePatchNum;
@@ -1352,8 +1349,8 @@
const {basePatchNum, patchNum} = e.detail;
if (
- patchNumEquals(basePatchNum, this._patchRange.basePatchNum) &&
- patchNumEquals(patchNum, this._patchRange.patchNum)
+ basePatchNum === this._patchRange.basePatchNum &&
+ patchNum === this._patchRange.patchNum
) {
return;
}
@@ -1582,7 +1579,7 @@
patchRangeRecord: PolymerDeepPropertyChange<PatchRange, PatchRange>
) {
const patchRange = patchRangeRecord.base || {};
- return patchNumEquals(patchRange.patchNum, EditPatchSetNum);
+ return patchRange.patchNum === EditPatchSetNum;
}
_computeBlameToggleLabel(loaded?: boolean, loading?: boolean) {
@@ -1641,7 +1638,7 @@
if (!this._path) return;
if (!this._patchRange) return;
- if (patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)) {
+ if (this._patchRange.basePatchNum === ParentPatchSetNum) {
fireAlert(this, 'Base is already selected.');
return;
}
@@ -1658,7 +1655,7 @@
if (!this._path) return;
if (!this._patchRange) return;
- if (patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)) {
+ if (this._patchRange.basePatchNum === ParentPatchSetNum) {
fireAlert(this, 'Left is already base.');
return;
}
@@ -1680,7 +1677,7 @@
if (!this._patchRange) return;
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
- if (patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ if (this._patchRange.patchNum === latestPatchNum) {
fireAlert(this, 'Latest is already selected.');
return;
}
@@ -1700,7 +1697,7 @@
if (!this._patchRange) return;
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
- if (patchNumEquals(this._patchRange.patchNum, latestPatchNum)) {
+ if (this._patchRange.patchNum === latestPatchNum) {
fireAlert(this, 'Right is already latest.');
return;
}
@@ -1720,8 +1717,8 @@
const latestPatchNum = computeLatestPatchNum(this._allPatchSets);
if (
- patchNumEquals(this._patchRange.patchNum, latestPatchNum) &&
- patchNumEquals(this._patchRange.basePatchNum, ParentPatchSetNum)
+ this._patchRange.patchNum === latestPatchNum &&
+ this._patchRange.basePatchNum === ParentPatchSetNum
) {
fireAlert(this, 'Already diffing base against latest.');
return;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
index 04714bb..39d645e 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
@@ -38,7 +38,7 @@
rangesEqual,
} from './gr-diff-utils';
import {getHiddenScroll} from '../../../scripts/hiddenscroll';
-import {isMergeParent, patchNumEquals} from '../../../utils/patch-set-util';
+import {isMergeParent} from '../../../utils/patch-set-util';
import {customElement, observe, property} from '@polymer/decorators';
import {
BlameInfo,
@@ -605,10 +605,10 @@
? this.patchRange.basePatchNum
: this.patchRange.patchNum;
- const isEdit = patchNumEquals(patchNum, EditPatchSetNum);
+ const isEdit = patchNum === EditPatchSetNum;
const isEditBase =
- patchNumEquals(patchNum, ParentPatchSetNum) &&
- patchNumEquals(this.patchRange.patchNum, EditPatchSetNum);
+ patchNum === ParentPatchSetNum &&
+ this.patchRange.patchNum === EditPatchSetNum;
if (isEdit) {
fireAlert(this, 'You cannot comment on an edit.');
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
index ec39da2..671bd41 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select.ts
@@ -30,7 +30,6 @@
getParentIndex,
getRevisionByPatchNum,
isMergeParent,
- patchNumEquals,
sortRevisions,
PatchSet,
} from '../../../utils/patch-set-util';
@@ -346,7 +345,7 @@
patchNum: PatchSetNum,
sortedRevisions: RevisionInfo[]
): boolean {
- if (patchNumEquals(basePatchNum, ParentPatchSetNum)) {
+ if (basePatchNum === ParentPatchSetNum) {
return false;
}
@@ -441,7 +440,7 @@
});
detail.patchNum = patchSetValue;
} else {
- if (patchNumEquals(detail.basePatchNum, patchSetValue)) return;
+ if (detail.basePatchNum === patchSetValue) return;
this.reporting.reportInteraction('left-patchset-changed', {
previous: detail.basePatchNum,
current: e.detail.value,
diff --git a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
index f5e5e04..197a0c4 100644
--- a/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
+++ b/polygerrit-ui/app/elements/diff/gr-syntax-layer/gr-syntax-layer.ts
@@ -304,7 +304,7 @@
this._processPromise = util.makeCancelable(
this._loadHLJS().then(
() =>
- new Promise(resolve => {
+ new Promise<void>(resolve => {
const nextStep = () => {
this._processHandle = null;
this._processNextLine(state, rangesCache);
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
index b380ce4..df927d6 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor.ts
@@ -24,7 +24,9 @@
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-table-editor_html';
import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin';
-import {customElement, property} from '@polymer/decorators';
+import {customElement, property, observe} from '@polymer/decorators';
+import {ServerInfo} from '../../../types/common';
+import {appContext} from '../../../services/app-context';
@customElement('gr-change-table-editor')
class GrChangeTableEditor extends ChangeTableMixin(
@@ -40,6 +42,27 @@
@property({type: Boolean, notify: true})
showNumber?: boolean;
+ @property({type: Object})
+ serverConfig?: ServerInfo;
+
+ @property({type: Array})
+ defaultColumns?: string[];
+
+ flagsService = appContext.flagsService;
+
+ @observe('serverConfig')
+ _configChanged(config: ServerInfo) {
+ this.defaultColumns = this.getEnabledColumns(
+ this.columnNames,
+ config,
+ this.flagsService.enabledExperiments
+ );
+ if (!this.displayedColumns) return;
+ this.displayedColumns = this.displayedColumns.filter(column =>
+ this.isColumnEnabled(column, config, this.flagsService.enabledExperiments)
+ );
+ }
+
/**
* Get the list of enabled column names from whichever checkboxes are
* checked (excluding the number checkbox).
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
index 1233cf1..4c87d83 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_html.ts
@@ -61,7 +61,7 @@
/>
</td>
</tr>
- <template is="dom-repeat" items="[[columnNames]]">
+ <template is="dom-repeat" items="[[defaultColumns]]">
<tr>
<td>[[item]]</td>
<td
diff --git a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
index 42085ff..db5c035 100644
--- a/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
+++ b/polygerrit-ui/app/elements/settings/gr-change-table-editor/gr-change-table-editor_test.js
@@ -41,6 +41,9 @@
element.set('displayedColumns', columns);
element.showNumber = false;
+ element.serverConfig = {
+ change: {},
+ };
flush();
});
@@ -51,13 +54,25 @@
// The `+ 1` is for the number column, which isn't included in the change
// table behavior's list.
- assert.equal(rows.length, element.columnNames.length + 1);
- for (let i = 0; i < columns.length; i++) {
+ assert.equal(rows.length, element.defaultColumns.length + 1);
+ for (let i = 0; i < element.defaultColumns.length; i++) {
tds = rows[i + 1].querySelectorAll('td');
- assert.equal(tds[0].textContent, columns[i]);
+ assert.equal(tds[0].textContent, element.defaultColumns[i]);
}
});
+ test('disabled experiments are hidden', () => {
+ assert.isFalse(element.displayedColumns.includes('Assignee'));
+ element.set('displayedColumns', columns);
+ element.serverConfig = {
+ change: {
+ enable_assignee: true,
+ },
+ };
+ flush();
+ assert.isTrue(element.displayedColumns.includes('Assignee'));
+ });
+
test('hide item', () => {
const checkbox = element.shadowRoot
.querySelector('table tr:nth-child(2) input');
@@ -80,6 +95,10 @@
'Branch',
'Updated',
]);
+ // trigger computation of enabled displayed columns
+ element.serverConfig = {
+ change: {},
+ };
flush();
const checkbox = element.shadowRoot
.querySelector('table tr:nth-child(2) input');
@@ -97,12 +116,15 @@
});
test('_getDisplayedColumns', () => {
- assert.deepEqual(element._getDisplayedColumns(), columns);
+ const enabledColumns = columns.filter(column => element.isColumnEnabled(
+ column, element.serverConfig, []
+ ));
+ assert.deepEqual(element._getDisplayedColumns(), enabledColumns);
MockInteractions.tap(
element.shadowRoot
- .querySelector('.checkboxContainer input[name=Assignee]'));
+ .querySelector('.checkboxContainer input[name=Subject]'));
assert.deepEqual(element._getDisplayedColumns(),
- columns.filter(c => c !== 'Assignee'));
+ enabledColumns.filter(c => c !== 'Subject'));
});
test('_handleCheckboxContainerClick relays taps to checkboxes', () => {
@@ -140,12 +162,12 @@
test('_handleTargetClick', () => {
sinon.spy(element, '_handleTargetClick');
- assert.include(element.displayedColumns, 'Assignee');
+ assert.include(element.displayedColumns, 'Subject');
MockInteractions
.tap(element.shadowRoot
- .querySelector('.checkboxContainer input[name=Assignee]'));
+ .querySelector('.checkboxContainer input[name=Subject]'));
assert.isTrue(element._handleTargetClick.calledOnce);
- assert.notInclude(element.displayedColumns, 'Assignee');
+ assert.notInclude(element.displayedColumns, 'Subject');
});
});
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index e5e8537..809139d 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -147,9 +147,6 @@
@property({type: Boolean})
_accountInfoChanged?: boolean;
- @property({type: Array})
- _changeTableColumnsNotDisplayed?: string[];
-
@property({type: Object})
_localPrefs: PreferencesInput = {};
@@ -241,8 +238,11 @@
this.prefs = prefs;
this._showNumber = !!prefs.legacycid_in_change_table;
this._copyPrefs(CopyPrefsDirection.PrefsToLocalPrefs);
- this._cloneMenu(prefs.my);
- this._cloneChangeTableColumns(prefs.change_table);
+ this._localMenu = this._cloneMenu(prefs.my);
+ this._localChangeTableColumns =
+ prefs.change_table.length === 0
+ ? this.columnNames
+ : this.renameProjectToRepoColumn(prefs.change_table);
})
);
@@ -341,29 +341,10 @@
}
_cloneMenu(prefs: TopMenuItemInfo[]) {
- const menu = [];
- for (const item of prefs) {
- menu.push({
- name: item.name,
- url: item.url,
- target: item.target,
- });
- }
- this._localMenu = menu;
- }
-
- _cloneChangeTableColumns(changeTable: string[]) {
- let columns = this.getVisibleColumns(changeTable);
-
- if (columns.length === 0) {
- columns = this.columnNames;
- this._changeTableColumnsNotDisplayed = [];
- } else {
- this._changeTableColumnsNotDisplayed = this.getComplementColumns(
- changeTable
- );
- }
- this._localChangeTableColumns = columns;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ return prefs.map(({id, ...item}) => {
+ return item;
+ });
}
@observe('_localChangeTableColumns', '_showNumber')
@@ -437,7 +418,6 @@
_handleSaveChangeTable() {
this.set('prefs.change_table', this._localChangeTableColumns);
this.set('prefs.legacycid_in_change_table', this._showNumber);
- this._cloneChangeTableColumns(this._localChangeTableColumns);
return this.restApiService.savePreferences(this.prefs).then(() => {
this._changeTableChanged = false;
});
@@ -453,7 +433,6 @@
_handleSaveMenu() {
this.set('prefs.my', this._localMenu);
- this._cloneMenu(this._localMenu);
return this.restApiService.savePreferences(this.prefs).then(() => {
this._menuChanged = false;
});
@@ -462,7 +441,7 @@
_handleResetMenuButton() {
return this.restApiService.getDefaultPreferences().then(data => {
if (data?.my) {
- this._cloneMenu(data.my);
+ this._localMenu = this._cloneMenu(data.my);
}
});
}
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
index d1d412f..ec8f6e7 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
@@ -340,6 +340,7 @@
<fieldset id="changeTableColumns">
<gr-change-table-editor
show-number="{{_showNumber}}"
+ server-config="[[_serverConfig]]"
displayed-columns="{{_localChangeTableColumns}}"
>
</gr-change-table-editor>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
index 62e2a9e..4c5a2a2 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
@@ -351,9 +351,7 @@
let newColumns = ['Owner', 'Project', 'Branch'];
element._localChangeTableColumns = newColumns.slice(0);
element._showNumber = false;
- const cloneStub = sinon.stub(element, '_cloneChangeTableColumns');
element._handleSaveChangeTable();
- assert.isTrue(cloneStub.calledOnce);
assert.deepEqual(element.prefs.change_table, newColumns);
assert.isNotOk(element.prefs.legacycid_in_change_table);
@@ -361,7 +359,6 @@
element._localChangeTableColumns = newColumns;
element._showNumber = true;
element._handleSaveChangeTable();
- assert.isTrue(cloneStub.calledTwice);
assert.deepEqual(element.prefs.change_table, newColumns);
assert.isTrue(element.prefs.legacycid_in_change_table);
});
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_html.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_html.ts
index d9a3187..fbf7f47 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_html.ts
@@ -264,10 +264,16 @@
</gr-account-label>
</template>
<template is="dom-if" if="[[showPortedComment]]">
- <a href="[[_getUrlForComment(comment)]]">
- <span class="portedMessage">
- Ported from patchset [[comment.patch_set]]
- </span>
+ <a href="[[_getUrlForComment(comment)]]"
+ ><span class="portedMessage"
+ >Ported from patchset [[comment.patch_set]]</span
+ ></a
+ >
+ <a
+ href="https://bugs.chromium.org/p/gerrit/issues/entry?template=Porting+Comments"
+ target="_blank"
+ >
+ <iron-icon icon="gr-icons:bug" title="report a problem"></iron-icon>
</a>
</template>
<gr-tooltip-content
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
index 1c85523..cc89a7e 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment_test.js
@@ -731,7 +731,7 @@
path: SpecialFilePath.PATCHSET_LEVEL_COMMENTS, line: undefined,
range: undefined};
element.comment = comment;
- flushAsynchronousOperations();
+ flush();
MockInteractions.tap(element.shadowRoot
.querySelector('.edit'));
assert.isTrue(element.editing);
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
index 37b5348..3fce16e 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list.ts
@@ -32,12 +32,6 @@
import {NormalizedFileInfo} from '../../change/gr-file-list/gr-file-list';
/**
- * fired when the selected value of the dropdown changes
- *
- * @event {change}
- */
-
-/**
* Requred values are text and value. mobileText and triggerText will
* fall back to text if not provided.
*
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
index f313174..c163924 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
@@ -145,7 +145,6 @@
slot="dropdown-content"
attr-for-selected="data-value"
selected="{{value}}"
- on-tap="_handleDropdownTap"
>
<template
is="dom-repeat"
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
index 3b839cb..6f0e84a 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-label/gr-editable-label.ts
@@ -136,7 +136,7 @@
this._inputText = this.value;
this.editing = true;
- return new Promise(resolve => {
+ return new Promise<void>(resolve => {
this._awaitOpen(resolve);
});
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
index ae6e155..00f9a40 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface-element.ts
@@ -18,7 +18,7 @@
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {getPluginLoader} from './gr-plugin-loader';
-import {patchNumEquals} from '../../../utils/patch-set-util';
+
import {customElement} from '@polymer/decorators';
import {
ChangeInfo,
@@ -154,7 +154,7 @@
let revision;
for (const rev of Object.values(change.revisions || {})) {
- if (patchNumEquals(rev._number, patchNum)) {
+ if (rev._number === patchNum) {
revision = rev;
break;
}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
index 645e166..b725d3b 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader.ts
@@ -430,7 +430,7 @@
// and the return type is NodeJS.Timeout object
let timerId: number;
this._loadingPromise = Promise.race([
- new Promise(resolve => (this._loadingResolver = resolve)),
+ new Promise<void>(resolve => (this._loadingResolver = resolve)),
new Promise(
(_, reject) =>
(timerId = window.setTimeout(() => {
diff --git a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
index 68a73933..d29cba7 100644
--- a/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
+++ b/polygerrit-ui/app/elements/shared/gr-overlay/gr-overlay.ts
@@ -95,7 +95,7 @@
open() {
this.returnFocusTo = findActiveElement(document, true) ?? undefined;
window.addEventListener('popstate', this._boundHandleClose);
- return new Promise((resolve, reject) => {
+ return new Promise<void>((resolve, reject) => {
super.open.apply(this);
if (this._isMobile()) {
fireEvent(this, 'fullscreen-overlay-opened');
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
index 078e07f..9e77784 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
@@ -36,11 +36,7 @@
import {parseDate} from '../../../utils/date-util';
import {getBaseUrl} from '../../../utils/url-util';
import {appContext} from '../../../services/app-context';
-import {
- getParentIndex,
- isMergeParent,
- patchNumEquals,
-} from '../../../utils/patch-set-util';
+import {getParentIndex, isMergeParent} from '../../../utils/patch-set-util';
import {
ListChangesOption,
listChangesOptionsToHex,
@@ -1354,7 +1350,7 @@
let params = undefined;
if (isMergeParent(patchRange.basePatchNum)) {
params = {parent: getParentIndex(patchRange.basePatchNum)};
- } else if (!patchNumEquals(patchRange.basePatchNum, ParentPatchSetNum)) {
+ } else if (patchRange.basePatchNum !== ParentPatchSetNum) {
params = {base: patchRange.basePatchNum};
}
return this._getChangeURLAndFetch({
@@ -1401,7 +1397,7 @@
changeNum: NumericChangeId,
patchRange: PatchRange
): Promise<FileNameToFileInfoMap | undefined> {
- if (patchNumEquals(patchRange.patchNum, EditPatchSetNum)) {
+ if (patchRange.patchNum === EditPatchSetNum) {
return this.getChangeEditFiles(changeNum, patchRange).then(
res => res && res.files
);
@@ -1983,9 +1979,10 @@
}
return res;
};
- const promise = patchNumEquals(patchNum, EditPatchSetNum)
- ? this._getFileInChangeEdit(changeNum, path)
- : this._getFileInRevision(changeNum, path, patchNum, suppress404s);
+ const promise =
+ patchNum === EditPatchSetNum
+ ? this._getFileInChangeEdit(changeNum, path)
+ : this._getFileInRevision(changeNum, path, patchNum, suppress404s);
return promise.then(res => {
if (!res || !res.ok) {
@@ -2277,8 +2274,7 @@
};
if (isMergeParent(basePatchNum)) {
params.parent = getParentIndex(basePatchNum);
- } else if (!patchNumEquals(basePatchNum, ParentPatchSetNum)) {
- // TODO (TS): fix as PatchSetNum in the condition above
+ } else if (basePatchNum !== ParentPatchSetNum) {
params.base = basePatchNum;
}
const endpoint = `/files/${encodeURIComponent(path)}/diff`;
diff --git a/polygerrit-ui/app/elements/shared/revision-info/revision-info.ts b/polygerrit-ui/app/elements/shared/revision-info/revision-info.ts
index fadbfa7..d4bbe16 100644
--- a/polygerrit-ui/app/elements/shared/revision-info/revision-info.ts
+++ b/polygerrit-ui/app/elements/shared/revision-info/revision-info.ts
@@ -15,7 +15,6 @@
* limitations under the License.
*/
-import {patchNumEquals} from '../../../utils/patch-set-util';
import {ChangeInfo, PatchSetNum} from '../../../types/common';
import {ParsedChangeInfo} from '../gr-rest-api-interface/gr-reviewer-updates-parser';
@@ -71,8 +70,8 @@
getParentId(patchNum: PatchSetNum, parentIndex: number) {
if (!this.change.revisions) return;
- const rev = Object.values(this.change.revisions).find(rev =>
- patchNumEquals(rev._number, patchNum)
+ const rev = Object.values(this.change.revisions).find(
+ rev => rev._number === patchNum
);
if (!rev || !rev.commit) return;
return rev.commit.parents[parentIndex].commit;
diff --git a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts
index abbcbc8..28b7a50 100644
--- a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts
+++ b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin.ts
@@ -48,14 +48,6 @@
'Size',
];
- /**
- * Returns the complement to the given column array
- *
- */
- getComplementColumns(columns: string[]) {
- return this.columnNames.filter(column => !columns.includes(column));
- }
-
isColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]) {
if (!columnsToDisplay || !columnToCheck) {
return false;
@@ -103,7 +95,7 @@
* @return If the column was renamed, returns a new array
* with the corrected name. Otherwise, it returns the original param.
*/
- getVisibleColumns(columns: string[]) {
+ renameProjectToRepoColumn(columns: string[]) {
const projectIndex = columns.indexOf('Project');
if (projectIndex === -1) {
return columns;
@@ -120,7 +112,6 @@
export interface ChangeTableMixinInterface {
readonly columnNames: string[];
- getComplementColumns(columns: string[]): string[];
isColumnHidden(columnToCheck?: string, columnsToDisplay?: string[]): boolean;
isColumnEnabled(
column: string,
@@ -132,5 +123,5 @@
config: ServerInfo,
experiments: string[]
): string[];
- getVisibleColumns(columns: string[]): string[];
+ renameProjectToRepoColumn(columns: string[]): string[];
}
diff --git a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js
index daf10ce..0d6b4ad 100644
--- a/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js
+++ b/polygerrit-ui/app/mixins/gr-change-table-mixin/gr-change-table-mixin_test.js
@@ -37,35 +37,6 @@
element = basicFixture.instantiate();
});
- test('getComplementColumns', () => {
- let columns = [
- 'Subject',
- 'Status',
- 'Owner',
- 'Assignee',
- 'Reviewers',
- 'Comments',
- 'Repo',
- 'Branch',
- 'Updated',
- 'Size',
- ];
- assert.deepEqual(element.getComplementColumns(columns), []);
-
- columns = [
- 'Subject',
- 'Status',
- 'Assignee',
- 'Reviewers',
- 'Comments',
- 'Repo',
- 'Branch',
- 'Size',
- ];
- assert.deepEqual(element.getComplementColumns(columns),
- ['Owner', 'Updated']);
- });
-
test('isColumnHidden', () => {
const columnToCheck = 'Repo';
let columnsToDisplay = [
@@ -92,15 +63,16 @@
assert.isTrue(element.isColumnHidden(columnToCheck, columnsToDisplay));
});
- test('getVisibleColumns maps Project to Repo', () => {
+ test('renameProjectToRepoColumn maps Project to Repo', () => {
const columns = [
'Subject',
'Status',
'Owner',
];
- assert.deepEqual(element.getVisibleColumns(columns), columns.slice(0));
+ assert.deepEqual(element.renameProjectToRepoColumn(columns),
+ columns.slice(0));
assert.deepEqual(
- element.getVisibleColumns(columns.concat(['Project'])),
+ element.renameProjectToRepoColumn(columns.concat(['Project'])),
columns.slice(0).concat(['Repo']));
});
});
diff --git a/polygerrit-ui/app/rollup.config.js b/polygerrit-ui/app/rollup.config.js
index c8e9baa..d93b5ea 100644
--- a/polygerrit-ui/app/rollup.config.js
+++ b/polygerrit-ui/app/rollup.config.js
@@ -69,7 +69,13 @@
output: {
format: 'iife',
compact: true,
- plugins: [terser()]
+ plugins: [
+ terser({
+ output: {
+ comments: false
+ }
+ })
+ ]
},
//Context must be set to window to correctly processing global variables
context: 'window',
diff --git a/polygerrit-ui/app/services/flags/flags.ts b/polygerrit-ui/app/services/flags/flags.ts
index 36fe858..d2b7166 100644
--- a/polygerrit-ui/app/services/flags/flags.ts
+++ b/polygerrit-ui/app/services/flags/flags.ts
@@ -24,7 +24,6 @@
* @desc Experiment ids used in Gerrit.
*/
export enum KnownExperimentId {
- PATCHSET_COMMENTS = 'UiFeature__patchset_comments',
NEW_CONTEXT_CONTROLS = 'UiFeature__new_context_controls',
CI_REBOOT_CHECKS = 'UiFeature__ci_reboot_checks',
NEW_CHANGE_SUMMARY_UI = 'UiFeature__new_change_summary_ui',
diff --git a/polygerrit-ui/app/test/test-utils.ts b/polygerrit-ui/app/test/test-utils.ts
index 08642af..97c220d 100644
--- a/polygerrit-ui/app/test/test-utils.ts
+++ b/polygerrit-ui/app/test/test-utils.ts
@@ -161,7 +161,7 @@
* ...
*/
export function listenOnce(el: EventTarget, eventType: string) {
- return new Promise(resolve => {
+ return new Promise<void>(resolve => {
const listener = () => {
removeEventListener();
resolve();
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index 1553187..2398a66 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import {EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
-import {PatchSetNum} from './common';
+import {PatchSetNum, UrlEncodedCommentId} from './common';
import {UIComment} from '../utils/comment-util';
import {Side} from '../constants/constants';
import {LineNumber} from '../elements/diff/gr-diff/gr-diff-line';
@@ -214,3 +214,16 @@
readonly keyCode: number;
readonly repeat: boolean;
}
+
+export interface ThreadListModifiedDetail {
+ rootId: UrlEncodedCommentId;
+ path: string;
+}
+
+export type ThreadListModifiedEvent = CustomEvent<ThreadListModifiedDetail>;
+
+declare global {
+ interface HTMLElementEventMap {
+ 'thread-list-modified': ThreadListModifiedEvent;
+ }
+}
diff --git a/polygerrit-ui/app/utils/attention-set-util.ts b/polygerrit-ui/app/utils/attention-set-util.ts
index b0aefcb..5b2762c 100644
--- a/polygerrit-ui/app/utils/attention-set-util.ts
+++ b/polygerrit-ui/app/utils/attention-set-util.ts
@@ -17,6 +17,7 @@
import {AccountInfo, ChangeInfo} from '../types/common';
import {isServiceUser} from './account-util';
+import {hasOwnProperty} from './common-util';
// You would typically use a ServerInfo here, but this utility does not care
// about all the other parameters in that object.
@@ -46,7 +47,8 @@
return (
isAttentionSetEnabled(config) &&
canHaveAttention(account) &&
- !!change?.attention_set?.hasOwnProperty(account!._account_id!)
+ !!change?.attention_set &&
+ hasOwnProperty(change?.attention_set, account!._account_id!)
);
}
diff --git a/polygerrit-ui/app/utils/comment-util.ts b/polygerrit-ui/app/utils/comment-util.ts
index 5d8ea37..f4c0692 100644
--- a/polygerrit-ui/app/utils/comment-util.ts
+++ b/polygerrit-ui/app/utils/comment-util.ts
@@ -29,7 +29,7 @@
import {parseDate} from './date-util';
import {LineNumber} from '../elements/diff/gr-diff/gr-diff-line';
import {CommentIdToCommentThreadMap} from '../elements/diff/gr-comment-api/gr-comment-api';
-import {isMergeParent, getParentIndex, patchNumEquals} from './patch-set-util';
+import {isMergeParent, getParentIndex} from './patch-set-util';
export interface DraftCommentProps {
__draft?: boolean;
@@ -126,6 +126,7 @@
comments: [comment],
patchNum: comment.patch_set,
commentSide: comment.side ?? CommentSide.REVISION,
+ mergeParentNum: comment.parent,
path: comment.path,
line: comment.line,
range: comment.range,
@@ -151,6 +152,11 @@
comments: UIComment[];
path: string;
commentSide: CommentSide;
+ /* mergeParentNum is the merge parent number only valid for merge commits
+ when commentSide is PARENT.
+ mergeParentNum is undefined for auto merge commits
+ */
+ mergeParentNum?: number;
patchNum?: PatchSetNum;
line?: LineNumber;
/* rootId is optional since we create a empty comment thread element for
@@ -196,7 +202,7 @@
if (
range.basePatchNum === ParentPatchSetNum &&
comment.side === CommentSide.PARENT &&
- patchNumEquals(comment.patch_set, range.patchNum)
+ comment.patch_set === range.patchNum
) {
return true;
}
@@ -204,7 +210,7 @@
return (
range.basePatchNum !== ParentPatchSetNum &&
comment.side !== CommentSide.PARENT &&
- patchNumEquals(comment.patch_set, range.basePatchNum)
+ comment.patch_set === range.basePatchNum
);
}
@@ -217,8 +223,7 @@
range: PatchRange
) {
return (
- comment.side !== CommentSide.PARENT &&
- patchNumEquals(comment.patch_set, range.patchNum)
+ comment.side !== CommentSide.PARENT && comment.patch_set === range.patchNum
);
}
@@ -247,7 +252,7 @@
patchNum: comment.patch_set,
basePatchNum: ParentPatchSetNum,
};
- } else if (patchNumEquals(latestPatchNum, comment.patch_set)) {
+ } else if (latestPatchNum === comment.patch_set) {
return {
patchNum: latestPatchNum,
basePatchNum: ParentPatchSetNum,
diff --git a/polygerrit-ui/app/utils/event-util.ts b/polygerrit-ui/app/utils/event-util.ts
index 3dd1b9e..5e1ff44 100644
--- a/polygerrit-ui/app/utils/event-util.ts
+++ b/polygerrit-ui/app/utils/event-util.ts
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+import {UrlEncodedCommentId} from '../types/common';
import {FetchRequest} from '../types/types';
export enum EventType {
@@ -23,6 +24,7 @@
SERVER_ERROR = 'server-error',
NETWORK_ERROR = 'network-error',
TITLE_CHANGE = 'title-change',
+ THREAD_LIST_MODIFIED = 'thread-list-modified',
}
export function fireEvent(target: EventTarget, type: string) {
@@ -83,3 +85,17 @@
})
);
}
+
+export function fireThreadListModifiedEvent(
+ target: EventTarget,
+ rootId: UrlEncodedCommentId,
+ path: string
+) {
+ target.dispatchEvent(
+ new CustomEvent(EventType.THREAD_LIST_MODIFIED, {
+ detail: {rootId, path},
+ composed: true,
+ bubbles: true,
+ })
+ );
+}
diff --git a/polygerrit-ui/app/utils/patch-set-util.ts b/polygerrit-ui/app/utils/patch-set-util.ts
index fda302b..cb0bdec 100644
--- a/polygerrit-ui/app/utils/patch-set-util.ts
+++ b/polygerrit-ui/app/utils/patch-set-util.ts
@@ -60,19 +60,6 @@
}
/**
- * As patchNum can be either a string (e.g. 'edit', 'PARENT') OR a number,
- * this function checks for patchNum equality.
- *
- */
-export function patchNumEquals(a?: PatchSetNum, b?: PatchSetNum) {
- if (a === undefined) {
- return a === b;
- }
- // TODO(TS): replace with a===b when the whole code is converted to ts
- return `${a}` === `${b}`;
-}
-
-/**
* Whether the given patch is a numbered parent of a merge (i.e. a negative
* number).
*/
@@ -114,7 +101,7 @@
patchNum: PatchSetNum
) {
for (const rev of revisions) {
- if (patchNumEquals(rev._number, patchNum)) {
+ if (rev._number === patchNum) {
return rev;
}
}
@@ -275,6 +262,20 @@
return allPatchSets[0].num;
}
+export function computePredecessor(
+ patchset?: PatchSetNum
+): PatchSetNum | undefined {
+ if (
+ !patchset ||
+ patchset === ParentPatchSetNum ||
+ patchset === EditPatchSetNum
+ ) {
+ return undefined;
+ }
+ if (patchset === 1) return ParentPatchSetNum;
+ return (Number(patchset) - 1) as PatchSetNum;
+}
+
export function hasEditBasedOnCurrentPatchSet(allPatchSets: PatchSet[]) {
if (!allPatchSets || allPatchSets.length < 2) {
return false;
diff --git a/polygerrit-ui/app/utils/patch-set-util_test.js b/polygerrit-ui/app/utils/patch-set-util_test.js
index 29cc370..12f5ed4 100644
--- a/polygerrit-ui/app/utils/patch-set-util_test.js
+++ b/polygerrit-ui/app/utils/patch-set-util_test.js
@@ -21,7 +21,7 @@
fetchChangeUpdates, findEditParentPatchNum, findEditParentRevision,
getParentIndex, getRevisionByPatchNum,
isMergeParent,
- patchNumEquals, sortRevisions,
+ sortRevisions,
} from './patch-set-util.js';
suite('gr-patch-set-util tests', () => {
@@ -31,9 +31,9 @@
{_number: 1},
{_number: 2},
];
- assert.deepEqual(getRevisionByPatchNum(revisions, '1'), revisions[1]);
+ assert.deepEqual(getRevisionByPatchNum(revisions, 1), revisions[1]);
assert.deepEqual(getRevisionByPatchNum(revisions, 2), revisions[2]);
- assert.equal(getRevisionByPatchNum(revisions, '3'), undefined);
+ assert.equal(getRevisionByPatchNum(revisions, 3), undefined);
});
test('fetchChangeUpdates on latest', done => {
@@ -231,17 +231,6 @@
.assertWip(6, true); // PS6 was uploaded with WIP option
});
- test('patchNumEquals', () => {
- assert.isFalse(patchNumEquals('edit', 'PARENT'));
- assert.isFalse(patchNumEquals('edit', NaN));
- assert.isFalse(patchNumEquals(1, '2'));
-
- assert.isTrue(patchNumEquals(1, '1'));
- assert.isTrue(patchNumEquals(1, 1));
- assert.isTrue(patchNumEquals('edit', 'edit'));
- assert.isTrue(patchNumEquals('PARENT', 'PARENT'));
- });
-
test('isMergeParent', () => {
assert.isFalse(isMergeParent(1));
assert.isFalse(isMergeParent(4321));
diff --git a/proto/cache.proto b/proto/cache.proto
index 0676f1b..8d575b7 100644
--- a/proto/cache.proto
+++ b/proto/cache.proto
@@ -599,3 +599,43 @@
string change_type = 9; // ENUM as string
string patch_type = 10; // ENUM as string
}
+
+// Serialized form of
+// com.google.gerrit.server.patch.fileDiff.FileDiffCacheKey
+// Next ID: 8
+message FileDiffKeyProto {
+ string project = 1;
+ bytes old_commit = 2;
+ bytes new_commit = 3;
+ string file_path = 4;
+ int32 rename_score = 5;
+ string diff_algorithm = 6;
+ string whitespace = 7;
+}
+
+// Serialized form of
+// com.google.gerrit.server.patch.filediff.FileDiffOutput
+// Next ID: 9
+message FileDiffOutputProto {
+ // Next ID: 5
+ message Edit {
+ int32 begin_a = 1;
+ int32 end_a = 2;
+ int32 begin_b = 3;
+ int32 end_b = 4;
+ }
+ // Serialized form of com.google.gerrit.server.patch.filediff.TaggedEdit
+ // Next ID: 3
+ message TaggedEdit {
+ Edit edit = 1;
+ bool due_to_rebase = 2;
+ }
+ string old_path = 1;
+ string new_path = 2;
+ string change_type = 3;
+ string patch_type = 4;
+ repeated string header_lines = 5;
+ int64 size = 6;
+ int64 size_delta = 7;
+ repeated TaggedEdit edits = 8;
+}
diff --git a/tools/coverage.sh b/tools/coverage.sh
index c92d5cf..3582d22 100755
--- a/tools/coverage.sh
+++ b/tools/coverage.sh
@@ -33,15 +33,24 @@
cp -r {java,javatests}/* ${destdir}/java
mkdir -p ${destdir}/plugins
-for plugin in `find plugins/ -maxdepth 1 -type d`
+for plugin in `find plugins/ -mindepth 1 -maxdepth 1 -type d`
do
mkdir -p ${destdir}/${plugin}/java
- cp -r plugins/*/{java,javatests}/* ${destdir}/${plugin}/java
+ if [ -e ${plugin}/java/ ]
+ then cp -r ${plugin}/java/* ${destdir}/${plugin}/java
+ fi
+ if [ -e ${plugin}/javatests/ ]
+ then cp -r ${plugin}/javatests/* ${destdir}/${plugin}/java
+ fi
# for backwards compatibility support plugins with old file structure
mkdir -p ${destdir}/${plugin}/src/{main,test}/java
- cp -r plugins/*/src/main/java/* ${destdir}/${plugin}/src/main/java
- cp -r plugins/*/src/test/java/* ${destdir}/${plugin}/src/test/java
+ if [ -e ${plugin}/src/main/java/ ]
+ then cp -r ${plugin}/src/main/java/* ${destdir}/${plugin}/src/main/java/
+ fi
+ if [ -e ${plugin}/src/test/java/ ]
+ then cp -r ${plugin}/src/test/java/* ${destdir}/${plugin}/src/test/java/
+ fi
done
base=$(bazel info bazel-testlogs)
diff --git a/tools/js/BUILD b/tools/js/BUILD
index fedaf7f..1a272e2 100644
--- a/tools/js/BUILD
+++ b/tools/js/BUILD
@@ -1 +1 @@
-exports_files(["run_npm_binary.py"])
+exports_files(["run_npm_binary.py", "eslint-chdir.js"])
diff --git a/tools/js/eslint-chdir.js b/tools/js/eslint-chdir.js
new file mode 100644
index 0000000..5aea704
--- /dev/null
+++ b/tools/js/eslint-chdir.js
@@ -0,0 +1,30 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Eslint 7 introduced a breaking change - it uses the current workdir instead
+// of the configuration file directory for resolving relative paths:
+// https://eslint.org/docs/user-guide/migrating-to-7.0.0#base-path-change
+// This file is loaded before the eslint and sets the current directory
+// back to the location of configuration file.
+
+const path = require('path');
+const configParamIndex =
+ process.argv.findIndex(arg => arg === '-c' || arg === '---config');
+if (configParamIndex >= 0 && configParamIndex + 1 < process.argv.length) {
+ const dirName = path.dirname(process.argv[configParamIndex + 1]);
+ process.chdir(dirName);
+}
diff --git a/tools/js/eslint.bzl b/tools/js/eslint.bzl
index 586b1c5..b32e2bc 100644
--- a/tools/js/eslint.bzl
+++ b/tools/js/eslint.bzl
@@ -57,9 +57,11 @@
config,
ignore,
"//tools/js/eslint-rules:eslint-rules-srcs",
+ "//tools/js:eslint-chdir.js",
eslint_rules_toplevel_file,
] + plugins + data
common_templated_args = [
+ "--node_options=--require=$$(rlocation $(rootpath //tools/js:eslint-chdir.js))",
"--ext",
",".join(extensions),
"-c",
@@ -85,7 +87,7 @@
"*_test_require_patch.js",
"--ignore-pattern",
"*_test_loader.js",
- native.package_name(),
+ "./", # Relative to the config file location
],
# Should not run sandboxed.
tags = [
diff --git a/tools/maven/gerrit-acceptance-framework_pom.xml b/tools/maven/gerrit-acceptance-framework_pom.xml
index 970a4a9..f6d1e3b 100644
--- a/tools/maven/gerrit-acceptance-framework_pom.xml
+++ b/tools/maven/gerrit-acceptance-framework_pom.xml
@@ -47,6 +47,9 @@
<name>Joerg Zieren</name>
</developer>
<developer>
+ <name>Jacek Centkowski</name>
+ </developer>
+ <developer>
<name>Luca Milanesio</name>
</developer>
<developer>
diff --git a/tools/maven/gerrit-extension-api_pom.xml b/tools/maven/gerrit-extension-api_pom.xml
index 74c4769..daf8089 100644
--- a/tools/maven/gerrit-extension-api_pom.xml
+++ b/tools/maven/gerrit-extension-api_pom.xml
@@ -47,6 +47,9 @@
<name>Joerg Zieren</name>
</developer>
<developer>
+ <name>Jacek Centkowski</name>
+ </developer>
+ <developer>
<name>Luca Milanesio</name>
</developer>
<developer>
diff --git a/tools/maven/gerrit-plugin-api_pom.xml b/tools/maven/gerrit-plugin-api_pom.xml
index e8fae82..07895a4 100644
--- a/tools/maven/gerrit-plugin-api_pom.xml
+++ b/tools/maven/gerrit-plugin-api_pom.xml
@@ -47,6 +47,9 @@
<name>Joerg Zieren</name>
</developer>
<developer>
+ <name>Jacek Centkowski</name>
+ </developer>
+ <developer>
<name>Luca Milanesio</name>
</developer>
<developer>
diff --git a/tools/maven/gerrit-war_pom.xml b/tools/maven/gerrit-war_pom.xml
index be6688a..a28adea 100644
--- a/tools/maven/gerrit-war_pom.xml
+++ b/tools/maven/gerrit-war_pom.xml
@@ -47,6 +47,9 @@
<name>Joerg Zieren</name>
</developer>
<developer>
+ <name>Jacek Centkowski</name>
+ </developer>
+ <developer>
<name>Luca Milanesio</name>
</developer>
<developer>
diff --git a/tools/node_tools/package.json b/tools/node_tools/package.json
index 81448e9..fdada50 100644
--- a/tools/node_tools/package.json
+++ b/tools/node_tools/package.json
@@ -16,7 +16,7 @@
"rollup": "^2.3.4",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^5.1.3",
- "typescript": "3.9.5"
+ "typescript": "4.0.5"
},
"devDependencies": {},
"license": "Apache-2.0",
diff --git a/tools/node_tools/yarn.lock b/tools/node_tools/yarn.lock
index b1412c4..338e490 100644
--- a/tools/node_tools/yarn.lock
+++ b/tools/node_tools/yarn.lock
@@ -7893,10 +7893,10 @@
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typescript@3.9.5:
- version "3.9.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36"
- integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==
+typescript@4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
+ integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
typical@^2.6.0, typical@^2.6.1:
version "2.6.1"
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index af5a900..4279183 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -1,5 +1,5 @@
load("//tools/bzl:maven_jar.bzl", "maven_jar")
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
GUAVA_VERSION = "29.0-jre"
GUAVA_BIN_SHA1 = "801142b4c3d0f0770dd29abea50906cacfddd447"
@@ -98,7 +98,8 @@
)
# When upgrading elasticsearch-rest-client, also upgrade httpcore-nio
- # and httpasyncclient as necessary.
+ # and httpasyncclient as necessary. Consider also the other
+ # org.apache.httpcomponents dependencies in ../WORKSPACE.
maven_jar(
name = "elasticsearch-rest-client",
artifact = "org.elasticsearch.client:elasticsearch-rest-client:7.8.1",
diff --git a/tools/remote-bazelrc b/tools/remote-bazelrc
index 13c498e..0aeb8d5 100644
--- a/tools/remote-bazelrc
+++ b/tools/remote-bazelrc
@@ -30,36 +30,20 @@
# Set several flags related to specifying the platform, toolchain and java
# properties.
-# These flags are duplicated rather than imported from (for example)
-# %workspace%/configs/ubuntu16_04_clang/1.2/toolchain.bazelrc to make this
-# bazelrc a standalone file that can be copied more easily.
-# These flags should only be used as is for the rbe-ubuntu16-04 container
-# and need to be adapted to work with other toolchain containers.
-build:remote --host_javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:jdk8
-build:remote --javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:jdk8
-build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
-build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
-build:remote --crosstool_top=@bazel_toolchains//configs/ubuntu16_04_clang/1.2/bazel_0.25.0/default:toolchain
+build:remote --host_javabase=@rbe_jdk11//java:jdk
+build:remote --javabase=@rbe_jdk11//java:jdk
+build:remote --crosstool_top=@rbe_jdk11//cc:toolchain
+build:remote --extra_toolchains=@rbe_jdk11//config:cc-toolchain
+build:remote --extra_execution_platforms=@rbe_jdk11//config:platform
+build:remote --host_platform=@rbe_jdk11//config:platform
+build:remote --platforms=@rbe_jdk11//config:platform
build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
-# Platform flags:
-# The toolchain container used for execution is defined in the target indicated
-# by "extra_execution_platforms", "host_platform" and "platforms".
-# If you are using your own toolchain container, you need to create a platform
-# target with "constraint_values" that allow for the toolchain specified with
-# "extra_toolchains" to be selected (given constraints defined in
-# "exec_compatible_with").
-# More about platforms: https://docs.bazel.build/versions/master/platforms.html
-build:remote --extra_toolchains=@bazel_toolchains//configs/ubuntu16_04_clang/1.2/bazel_0.25.0/cpp:cc-toolchain-clang-x86_64-default
-build:remote --extra_execution_platforms=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:rbe_ubuntu1604
-build:remote --host_platform=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:rbe_ubuntu1604
-build:remote --platforms=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:rbe_ubuntu1604
# Set various strategies so that all actions execute remotely. Mixing remote
# and local execution will lead to errors unless the toolchain and remote
# machine exactly match the host machine.
build:remote --spawn_strategy=remote,sandboxed
build:remote --strategy=Javac=remote
-build:remote --strategy=Closure=remote
build:remote --strategy=Genrule=remote
build:remote --define=EXECUTOR=remote
@@ -78,20 +62,6 @@
# account credential instead.
build:remote --auth_enabled=true
-# The following flags are only necessary for local docker sandboxing
-# with the rbe-ubuntu16-04 container. Use of these flags is still experimental.
-build:docker-sandbox --host_javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:jdk8
-build:docker-sandbox --javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.2:jdk8
-build:docker-sandbox --crosstool_top=@bazel_toolchains//configs/ubuntu16_04_clang/1.2/bazel_0.25.0/default:toolchain
-build:docker-sandbox --experimental_docker_image=gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:da0f21c71abce3bbb92c3a0c44c3737f007a82b60f8bd2930abc55fe64fc2729
-build:docker-sandbox --spawn_strategy=docker
-build:docker-sandbox --strategy=Javac=docker
-build:docker-sandbox --strategy=Closure=docker
-build:docker-sandbox --strategy=Genrule=docker
-build:docker-sandbox --define=EXECUTOR=remote
-build:docker-sandbox --experimental_docker_verbose
-build:docker-sandbox --experimental_enable_docker_sandbox
-
# The following flags enable the remote cache so action results can be shared
# across machines, developers, and workspaces.
build:remote-cache --remote_cache=remotebuildexecution.googleapis.com
@@ -100,5 +70,4 @@
build:remote-cache --auth_enabled=true
build:remote-cache --spawn_strategy=standalone
build:remote-cache --strategy=Javac=standalone
-build:remote-cache --strategy=Closure=standalone
build:remote-cache --strategy=Genrule=standalone
diff --git a/yarn.lock b/yarn.lock
index 119edf5..3653ee5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -505,6 +505,22 @@
source-map-support "0.5.9"
tsutils "2.27.2"
+"@eslint/eslintrc@^0.2.2":
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76"
+ integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.1.1"
+ espree "^7.3.0"
+ globals "^12.1.0"
+ ignore "^4.0.6"
+ import-fresh "^3.2.1"
+ js-yaml "^3.13.1"
+ lodash "^4.17.19"
+ minimatch "^3.0.4"
+ strip-json-comments "^3.1.1"
+
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -513,11 +529,32 @@
call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0"
+"@nodelib/fs.scandir@2.1.3":
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
+ integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.3"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3"
+ integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==
+
"@nodelib/fs.stat@^1.1.2":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976"
+ integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.3"
+ fastq "^1.6.0"
+
"@octokit/endpoint@^5.1.0":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.2.1.tgz#e5ef98bc4a41fad62b17e71af1a1710f6076b8df"
@@ -769,11 +806,6 @@
resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-0.0.20.tgz#cae698714dd61ebee5ab3f2aeb9a34ba1011735a"
integrity sha512-6dhZJLbA7aOwkYB2GDGdIqJ20wmHnkDzaxV9PJXe7O02I2dSFTERzRB6JrX6cWKaS+VqhhY7cQUMCbO5kloFUw==
-"@types/eslint-visitor-keys@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
- integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
-
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@@ -884,6 +916,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
+
"@types/launchpad@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@types/launchpad/-/launchpad-0.6.0.tgz#37296109b7f277f6e6c5fd7e0c0706bc918fbb51"
@@ -912,9 +949,9 @@
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/minimist@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
- integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
+ integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
"@types/mz@0.0.29":
version "0.0.29"
@@ -1225,49 +1262,76 @@
"@types/events" "*"
"@types/inquirer" "*"
-"@typescript-eslint/eslint-plugin@2.31.0":
- version "2.31.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.31.0.tgz#942c921fec5e200b79593c71fafb1e3f57aa2e36"
- integrity sha512-iIC0Pb8qDaoit+m80Ln/aaeu9zKQdOLF4SHcGLarSeY1gurW6aU4JsOPMjKQwXlw70MvWKZQc6S2NamA8SJ/gg==
+"@typescript-eslint/eslint-plugin@^4.11.0", "@typescript-eslint/eslint-plugin@^4.2.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.0.tgz#bc6c1e4175c0cf42083da4314f7931ad12f731cc"
+ integrity sha512-x4arJMXBxyD6aBXLm3W7mSDZRiABzy+2PCLJbL7OPqlp53VXhaA1HKK7R2rTee5OlRhnUgnp8lZyVIqjnyPT6g==
dependencies:
- "@typescript-eslint/experimental-utils" "2.31.0"
+ "@typescript-eslint/experimental-utils" "4.11.0"
+ "@typescript-eslint/scope-manager" "4.11.0"
+ debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
+ semver "^7.3.2"
tsutils "^3.17.1"
-"@typescript-eslint/experimental-utils@2.31.0":
- version "2.31.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.31.0.tgz#a9ec514bf7fd5e5e82bc10dcb6a86d58baae9508"
- integrity sha512-MI6IWkutLYQYTQgZ48IVnRXmLR/0Q6oAyJgiOror74arUMh7EWjJkADfirZhRsUMHeLJ85U2iySDwHTSnNi9vA==
+"@typescript-eslint/experimental-utils@4.11.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.0.tgz#d1a47cc6cfe1c080ce4ead79267574b9881a1565"
+ integrity sha512-1VC6mSbYwl1FguKt8OgPs8xxaJgtqFpjY/UzUYDBKq4pfQ5lBvN2WVeqYkzf7evW42axUHYl2jm9tNyFsb8oLg==
dependencies:
"@types/json-schema" "^7.0.3"
- "@typescript-eslint/typescript-estree" "2.31.0"
+ "@typescript-eslint/scope-manager" "4.11.0"
+ "@typescript-eslint/types" "4.11.0"
+ "@typescript-eslint/typescript-estree" "4.11.0"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
-"@typescript-eslint/parser@2.31.0":
- version "2.31.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.31.0.tgz#beddd4e8efe64995108b229b2862cd5752d40d6f"
- integrity sha512-uph+w6xUOlyV2DLSC6o+fBDzZ5i7+3/TxAsH4h3eC64tlga57oMb96vVlXoMwjR/nN+xyWlsnxtbDkB46M2EPQ==
+"@typescript-eslint/parser@^4.2.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.11.0.tgz#1dd3d7e42708c10ce9f3aa64c63c0ab99868b4e2"
+ integrity sha512-NBTtKCC7ZtuxEV5CrHUO4Pg2s784pvavc3cnz6V+oJvVbK4tH9135f/RBP6eUA2KHiFKAollSrgSctQGmHbqJQ==
dependencies:
- "@types/eslint-visitor-keys" "^1.0.0"
- "@typescript-eslint/experimental-utils" "2.31.0"
- "@typescript-eslint/typescript-estree" "2.31.0"
- eslint-visitor-keys "^1.1.0"
-
-"@typescript-eslint/typescript-estree@2.31.0":
- version "2.31.0"
- resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.31.0.tgz#ac536c2d46672aa1f27ba0ec2140d53670635cfd"
- integrity sha512-vxW149bXFXXuBrAak0eKHOzbcu9cvi6iNcJDzEtOkRwGHxJG15chiAQAwhLOsk+86p9GTr/TziYvw+H9kMaIgA==
- dependencies:
+ "@typescript-eslint/scope-manager" "4.11.0"
+ "@typescript-eslint/types" "4.11.0"
+ "@typescript-eslint/typescript-estree" "4.11.0"
debug "^4.1.1"
- eslint-visitor-keys "^1.1.0"
- glob "^7.1.6"
+
+"@typescript-eslint/scope-manager@4.11.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.11.0.tgz#2d906537db8a3a946721699e4fc0833810490254"
+ integrity sha512-6VSTm/4vC2dHM3ySDW9Kl48en+yLNfVV6LECU8jodBHQOhO8adAVizaZ1fV0QGZnLQjQ/y0aBj5/KXPp2hBTjA==
+ dependencies:
+ "@typescript-eslint/types" "4.11.0"
+ "@typescript-eslint/visitor-keys" "4.11.0"
+
+"@typescript-eslint/types@4.11.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.11.0.tgz#86cf95e7eac4ccfd183f9fcf1480cece7caf4ca4"
+ integrity sha512-XXOdt/NPX++txOQHM1kUMgJUS43KSlXGdR/aDyEwuAEETwuPt02Nc7v+s57PzuSqMbNLclblQdv3YcWOdXhQ7g==
+
+"@typescript-eslint/typescript-estree@4.11.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.0.tgz#1144d145841e5987d61c4c845442a24b24165a4b"
+ integrity sha512-eA6sT5dE5RHAFhtcC+b5WDlUIGwnO9b0yrfGa1mIOIAjqwSQCpXbLiFmKTdRbQN/xH2EZkGqqLDrKUuYOZ0+Hg==
+ dependencies:
+ "@typescript-eslint/types" "4.11.0"
+ "@typescript-eslint/visitor-keys" "4.11.0"
+ debug "^4.1.1"
+ globby "^11.0.1"
is-glob "^4.0.1"
lodash "^4.17.15"
- semver "^6.3.0"
+ semver "^7.3.2"
tsutils "^3.17.1"
+"@typescript-eslint/visitor-keys@4.11.0":
+ version "4.11.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.0.tgz#906669a50f06aa744378bb84c7d5c4fdbc5b7d51"
+ integrity sha512-tRYKyY0i7cMk6v4UIOCjl1LhuepC/pc6adQqJk4Is3YcC6k46HvsV9Wl7vQoLbm9qADgeujiT7KdLrylvFIQ+A==
+ dependencies:
+ "@typescript-eslint/types" "4.11.0"
+ eslint-visitor-keys "^2.0.0"
+
"@webcomponents/webcomponentsjs@^1.0.7":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-1.3.3.tgz#5bb82a0d3210c836bd4623e13a4a93145cb9dc27"
@@ -1298,10 +1362,10 @@
dependencies:
acorn "^3.0.4"
-acorn-jsx@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384"
- integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==
+acorn-jsx@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
+ integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
acorn@^3.0.4:
version "3.3.0"
@@ -1318,10 +1382,10 @@
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3"
integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==
-acorn@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c"
- integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==
+acorn@^7.4.0:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
adm-zip@~0.4.3:
version "0.4.13"
@@ -1340,7 +1404,7 @@
dependencies:
es6-promisify "^5.0.0"
-ajv@^6.10.0, ajv@^6.10.2:
+ajv@^6.10.0:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
@@ -1350,6 +1414,16 @@
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
+ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
ajv@^6.5.5:
version "6.10.1"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593"
@@ -1381,6 +1455,11 @@
dependencies:
string-width "^3.0.0"
+ansi-colors@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
+ integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
+
ansi-escapes@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
@@ -1392,11 +1471,11 @@
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
ansi-escapes@^4.2.1:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d"
- integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
+ integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
dependencies:
- type-fest "^0.8.1"
+ type-fest "^0.11.0"
ansi-regex@^2.0.0:
version "2.1.1"
@@ -1423,13 +1502,20 @@
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
+ansi-styles@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
ansi-styles@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
@@ -1559,13 +1645,15 @@
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
-array-includes@^3.0.3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348"
- integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==
+array-includes@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8"
+ integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.17.0"
+ es-abstract "^1.18.0-next.1"
+ get-intrinsic "^1.0.1"
is-string "^1.0.5"
array-union@^1.0.1:
@@ -1575,6 +1663,11 @@
dependencies:
array-uniq "^1.0.1"
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
array-uniq@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
@@ -1590,13 +1683,14 @@
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
-array.prototype.flat@^1.2.1:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b"
- integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==
+array.prototype.flat@^1.2.3:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123"
+ integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
+ es-abstract "^1.18.0-next.1"
arraybuffer.slice@~0.0.7:
version "0.0.7"
@@ -1608,11 +1702,6 @@
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
-arrify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
- integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
-
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
@@ -1630,10 +1719,10 @@
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-astral-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
- integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+astral-regex@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+ integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
async-each@^1.0.0:
version "1.0.3"
@@ -2183,6 +2272,13 @@
split-string "^3.0.2"
to-regex "^3.0.1"
+braces@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
browser-capabilities@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/browser-capabilities/-/browser-capabilities-1.1.4.tgz#a6bd657a07a134532ad66c722b8949904478b973"
@@ -2292,6 +2388,14 @@
normalize-url "^4.1.0"
responselike "^1.0.2"
+call-bind@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce"
+ integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.0"
+
call-me-maybe@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
@@ -2342,16 +2446,11 @@
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-camelcase@^5.0.0, camelcase@^5.3.1:
+camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-camelcase@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
- integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
-
cancel-token@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/cancel-token/-/cancel-token-0.1.1.tgz#c18197674bb1c84c1d6933ebf15d8d5a5ce79b4f"
@@ -2369,7 +2468,7 @@
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-chalk@*, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
+chalk@*, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2397,7 +2496,7 @@
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-chalk@^4.0.0:
+chalk@^4.0.0, chalk@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
@@ -2488,9 +2587,9 @@
integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
cli-boxes@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
- integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
+ integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
cli-cursor@^1.0.1:
version "1.0.2"
@@ -2525,6 +2624,11 @@
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
+cli-width@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
+ integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+
clone-buffer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
@@ -2691,10 +2795,10 @@
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
-comment-parser@^0.7.2:
- version "0.7.2"
- resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.2.tgz#baf6d99b42038678b81096f15b630d18142f4b8a"
- integrity sha512-4Rjb1FnxtOcv9qsfuaNuVsmmVn4ooVoBHzYfyKteiXwIU84PClyGA5jASoFMwPV93+FPh9spwueXauxFJZkGAg==
+comment-parser@^0.7.6:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-0.7.6.tgz#0e743a53c8e646c899a1323db31f6cd337b10f12"
+ integrity sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==
commondir@^1.0.1:
version "1.0.1"
@@ -2914,7 +3018,7 @@
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^7.0.0:
+cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -3004,6 +3108,13 @@
dependencies:
ms "^2.1.1"
+debug@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
+ integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
+ dependencies:
+ ms "2.1.2"
+
debug@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
@@ -3019,7 +3130,7 @@
decamelize "^1.1.0"
map-obj "^1.0.0"
-decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0:
+decamelize@^1.1.0, decamelize@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -3046,7 +3157,7 @@
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-deep-is@~0.1.3:
+deep-is@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
@@ -3196,6 +3307,13 @@
arrify "^1.0.1"
path-type "^3.0.0"
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@@ -3218,12 +3336,13 @@
dependencies:
esutils "^2.0.2"
-dom-serializer@0:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
- integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
+dom-serializer@^1.0.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.2.0.tgz#3433d9136aeb3c627981daa385fc7f32d27c48f1"
+ integrity sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==
dependencies:
domelementtype "^2.0.1"
+ domhandler "^4.0.0"
entities "^2.0.0"
dom-urls@^1.1.0:
@@ -3242,30 +3361,33 @@
clone "^2.1.0"
parse5 "^4.0.0"
-domelementtype@1, domelementtype@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
- integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
+domelementtype@^2.0.1, domelementtype@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e"
+ integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==
-domelementtype@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
- integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
-
-domhandler@^2.3.0:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
- integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
+domhandler@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a"
+ integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==
dependencies:
- domelementtype "1"
+ domelementtype "^2.0.1"
-domutils@^1.5.1:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
- integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
+domhandler@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e"
+ integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==
dependencies:
- dom-serializer "0"
- domelementtype "1"
+ domelementtype "^2.1.0"
+
+domutils@^2.4.2:
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3"
+ integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA==
+ dependencies:
+ dom-serializer "^1.0.1"
+ domelementtype "^2.0.1"
+ domhandler "^4.0.0"
dot-prop@^3.0.0:
version "3.0.0"
@@ -3282,9 +3404,9 @@
is-obj "^1.0.0"
dot-prop@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
- integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
+ integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
dependencies:
is-obj "^2.0.0"
@@ -3422,15 +3544,17 @@
engine.io-parser "~2.2.0"
ws "^7.1.2"
-entities@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
- integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
+enquirer@^2.3.5:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+ integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+ dependencies:
+ ansi-colors "^4.1.1"
entities@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
- integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
+ integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
env-variable@0.0.x:
version "0.0.5"
@@ -3459,22 +3583,23 @@
string-template "~0.2.1"
xtend "~4.0.0"
-es-abstract@^1.17.0, es-abstract@^1.17.0-next.1:
- version "1.17.5"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9"
- integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==
+es-abstract@^1.18.0-next.1:
+ version "1.18.0-next.1"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68"
+ integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==
dependencies:
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.1"
- is-callable "^1.1.5"
- is-regex "^1.0.5"
- object-inspect "^1.7.0"
+ is-callable "^1.2.2"
+ is-negative-zero "^2.0.0"
+ is-regex "^1.1.1"
+ object-inspect "^1.8.0"
object-keys "^1.1.1"
- object.assign "^4.1.0"
- string.prototype.trimleft "^2.1.1"
- string.prototype.trimright "^2.1.1"
+ object.assign "^4.1.1"
+ string.prototype.trimend "^1.0.1"
+ string.prototype.trimstart "^1.0.1"
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -3517,30 +3642,30 @@
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-eslint-config-google@^0.13.0:
- version "0.13.0"
- resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.13.0.tgz#e277d16d2cb25c1ffd3fd13fb0035ad7421382fe"
- integrity sha512-ELgMdOIpn0CFdsQS+FuxO+Ttu4p+aLaXHv9wA9yVnzqlUGV7oN/eRRnJekk7TCur6Cu2FXX0fqfIXRBaM14lpQ==
+eslint-config-google@^0.14.0:
+ version "0.14.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.14.0.tgz#4f5f8759ba6e11b424294a219dbfa18c508bcc1a"
+ integrity sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==
-eslint-config-prettier@^6.10.1:
- version "6.11.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1"
- integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==
+eslint-config-prettier@^6.12.0:
+ version "6.15.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9"
+ integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==
dependencies:
get-stdin "^6.0.0"
-eslint-import-resolver-node@^0.3.2:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404"
- integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==
+eslint-import-resolver-node@^0.3.4:
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
+ integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==
dependencies:
debug "^2.6.9"
resolve "^1.13.1"
-eslint-module-utils@^2.4.1:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz#7878f7504824e1b857dd2505b59a8e5eda26a708"
- integrity sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==
+eslint-module-utils@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6"
+ integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==
dependencies:
debug "^2.6.9"
pkg-dir "^2.0.0"
@@ -3553,44 +3678,44 @@
eslint-utils "^2.0.0"
regexpp "^3.0.0"
-eslint-plugin-html@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-6.0.0.tgz#28e5c3e71e6f612e07e73d7c215e469766628c13"
- integrity sha512-PQcGippOHS+HTbQCStmH5MY1BF2MaU8qW/+Mvo/8xTa/ioeMXdSP+IiaBw2+nh0KEMfYQKuTz1Zo+vHynjwhbg==
+eslint-plugin-html@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-6.1.1.tgz#95aee151900b9bb2da5fa017b45cc64456a0a74e"
+ integrity sha512-JSe3ZDb7feKMnQM27XWGeoIjvP4oWQMJD9GZ6wW67J7/plVL87NK72RBwlvfc3tTZiYUchHhxAwtgEd1GdofDA==
dependencies:
- htmlparser2 "^3.10.1"
+ htmlparser2 "^5.0.1"
-eslint-plugin-import@^2.20.1:
- version "2.20.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3"
- integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==
+eslint-plugin-import@^2.22.1:
+ version "2.22.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
+ integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==
dependencies:
- array-includes "^3.0.3"
- array.prototype.flat "^1.2.1"
+ array-includes "^3.1.1"
+ array.prototype.flat "^1.2.3"
contains-path "^0.1.0"
debug "^2.6.9"
doctrine "1.5.0"
- eslint-import-resolver-node "^0.3.2"
- eslint-module-utils "^2.4.1"
+ eslint-import-resolver-node "^0.3.4"
+ eslint-module-utils "^2.6.0"
has "^1.0.3"
minimatch "^3.0.4"
- object.values "^1.1.0"
+ object.values "^1.1.1"
read-pkg-up "^2.0.0"
- resolve "^1.12.0"
+ resolve "^1.17.0"
+ tsconfig-paths "^3.9.0"
-eslint-plugin-jsdoc@^19.2.0:
- version "19.2.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-19.2.0.tgz#f522b970878ae402b28ce62187305b33dfe2c834"
- integrity sha512-QdNifBFLXCDGdy+26RXxcrqzEZarFWNybCZQVqJQYEYPlxd6lm+LPkrs6mCOhaGc2wqC6zqpedBQFX8nQJuKSw==
+eslint-plugin-jsdoc@^30.7.9:
+ version "30.7.9"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-30.7.9.tgz#b0a9881990edc1bc8a635467bad9edfae9ecbaaf"
+ integrity sha512-qMM0fNx7/6OCnIh3jRpIrEBAhTG1THNXXbr3yfJ8yqLrDbzJR98xsstX25xt9GCPlrjNc/bBpTHfJQOvn7nVMA==
dependencies:
- comment-parser "^0.7.2"
- debug "^4.1.1"
- jsdoctypeparser "^6.1.0"
- lodash "^4.17.15"
- object.entries-ponyfill "^1.0.1"
- regextras "^0.7.0"
- semver "^6.3.0"
- spdx-expression-parse "^3.0.0"
+ comment-parser "^0.7.6"
+ debug "^4.3.1"
+ jsdoctypeparser "^9.0.0"
+ lodash "^4.17.20"
+ regextras "^0.7.1"
+ semver "^7.3.4"
+ spdx-expression-parse "^3.0.1"
eslint-plugin-node@^11.1.0:
version "11.1.0"
@@ -3604,17 +3729,10 @@
resolve "^1.10.1"
semver "^6.1.0"
-eslint-plugin-prettier@^3.1.2:
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2"
- integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==
- dependencies:
- prettier-linter-helpers "^1.0.0"
-
-eslint-plugin-prettier@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz#ae116a0fc0e598fdae48743a4430903de5b4e6ca"
- integrity sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ==
+eslint-plugin-prettier@^3.1.4, eslint-plugin-prettier@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz#61e295349a65688ffac0b7808ef0a8244bdd8d40"
+ integrity sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==
dependencies:
prettier-linter-helpers "^1.0.0"
@@ -3626,14 +3744,15 @@
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-utils@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
- integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
dependencies:
- eslint-visitor-keys "^1.1.0"
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
-eslint-utils@^2.0.0:
+eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
@@ -3645,46 +3764,56 @@
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
-eslint@^6.6.0, eslint@^6.8.0:
- version "6.8.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
- integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
+eslint-visitor-keys@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+ integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+
+eslint-visitor-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+ integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+
+eslint@^7.10.0, eslint@^7.16.0:
+ version "7.16.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.16.0.tgz#a761605bf9a7b32d24bb7cde59aeb0fd76f06092"
+ integrity sha512-iVWPS785RuDA4dWuhhgXTNrGxHHK3a8HLSMBgbbU59ruJDubUraXN8N5rn7kb8tG6sjg74eE0RA3YWT51eusEw==
dependencies:
"@babel/code-frame" "^7.0.0"
+ "@eslint/eslintrc" "^0.2.2"
ajv "^6.10.0"
- chalk "^2.1.0"
- cross-spawn "^6.0.5"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
- eslint-scope "^5.0.0"
- eslint-utils "^1.4.3"
- eslint-visitor-keys "^1.1.0"
- espree "^6.1.2"
- esquery "^1.0.1"
+ enquirer "^2.3.5"
+ eslint-scope "^5.1.1"
+ eslint-utils "^2.1.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.1"
+ esquery "^1.2.0"
esutils "^2.0.2"
- file-entry-cache "^5.0.1"
+ file-entry-cache "^6.0.0"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
- inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
- levn "^0.3.0"
- lodash "^4.17.14"
+ levn "^0.4.1"
+ lodash "^4.17.19"
minimatch "^3.0.4"
- mkdirp "^0.5.1"
natural-compare "^1.4.0"
- optionator "^0.8.3"
+ optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^2.0.1"
- semver "^6.1.2"
- strip-ansi "^5.2.0"
- strip-json-comments "^3.0.1"
- table "^5.2.3"
+ regexpp "^3.1.0"
+ semver "^7.2.1"
+ strip-ansi "^6.0.0"
+ strip-json-comments "^3.1.0"
+ table "^6.0.4"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -3696,26 +3825,26 @@
acorn "^5.5.0"
acorn-jsx "^3.0.0"
-espree@^6.1.2:
- version "6.1.2"
- resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d"
- integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==
+espree@^7.3.0, espree@^7.3.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
+ integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
dependencies:
- acorn "^7.1.0"
- acorn-jsx "^5.1.0"
- eslint-visitor-keys "^1.1.0"
+ acorn "^7.4.0"
+ acorn-jsx "^5.3.1"
+ eslint-visitor-keys "^1.3.0"
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esquery@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
- integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==
+esquery@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
+ integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
dependencies:
- estraverse "^4.0.0"
+ estraverse "^5.1.0"
esrecurse@^4.1.0:
version "4.2.1"
@@ -3724,11 +3853,23 @@
dependencies:
estraverse "^4.1.0"
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.0, estraverse@^4.1.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+estraverse@^5.1.0, estraverse@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+ integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
@@ -3770,19 +3911,19 @@
signal-exit "^3.0.0"
strip-eof "^1.0.0"
-execa@^4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.2.tgz#ad87fb7b2d9d564f70d2b62d511bee41d5cbb240"
- integrity sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==
+execa@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.0.tgz#4029b0007998a841fbd1032e5f4de86a3c1e3376"
+ integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==
dependencies:
- cross-spawn "^7.0.0"
- get-stream "^5.0.0"
- human-signals "^1.1.1"
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
- npm-run-path "^4.0.0"
- onetime "^5.1.0"
- signal-exit "^3.0.2"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
exit-hook@^1.0.0:
@@ -3953,6 +4094,11 @@
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
fast-diff@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
@@ -3970,12 +4116,24 @@
merge2 "^1.2.3"
micromatch "^3.1.10"
+fast-glob@^3.1.1:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3"
+ integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.0"
+ merge2 "^1.3.0"
+ micromatch "^4.0.2"
+ picomatch "^2.2.1"
+
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
-fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+fast-levenshtein@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
@@ -3985,6 +4143,13 @@
resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2"
integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==
+fastq@^1.6.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb"
+ integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==
+ dependencies:
+ reusify "^1.0.4"
+
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@@ -4013,18 +4178,18 @@
escape-string-regexp "^1.0.5"
figures@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec"
- integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
+ integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
dependencies:
escape-string-regexp "^1.0.5"
-file-entry-cache@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c"
- integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==
+file-entry-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a"
+ integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==
dependencies:
- flat-cache "^2.0.1"
+ flat-cache "^3.0.4"
filename-regex@^2.0.0:
version "2.0.1"
@@ -4052,6 +4217,13 @@
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
filled-array@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/filled-array/-/filled-array-1.1.0.tgz#c3c4f6c663b923459a9aa29912d2d031f1507f84"
@@ -4146,19 +4318,18 @@
dependencies:
readable-stream "^2.0.2"
-flat-cache@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
- integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
dependencies:
- flatted "^2.0.0"
- rimraf "2.6.3"
- write "1.0.3"
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
-flatted@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08"
- integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==
+flatted@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067"
+ integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==
follow-redirects@^1.0.0:
version "1.9.0"
@@ -4286,6 +4457,15 @@
strip-ansi "^3.0.1"
wide-align "^1.1.0"
+get-intrinsic@^1.0.0, get-intrinsic@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49"
+ integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.1"
+
get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
@@ -4308,13 +4488,18 @@
dependencies:
pump "^3.0.0"
-get-stream@^5.0.0, get-stream@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
- integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==
+get-stream@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+ integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
dependencies:
pump "^3.0.0"
+get-stream@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718"
+ integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==
+
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -4372,6 +4557,13 @@
dependencies:
is-glob "^4.0.1"
+glob-parent@^5.1.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
+ integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
+ dependencies:
+ is-glob "^4.0.1"
+
glob-stream@^5.3.2:
version "5.3.5"
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22"
@@ -4425,7 +4617,7 @@
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+glob@^7.1.3, glob@^7.1.4:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@@ -4445,11 +4637,11 @@
ini "^1.3.4"
global-dirs@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
- integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d"
+ integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==
dependencies:
- ini "^1.3.5"
+ ini "1.3.7"
global-modules@^0.2.3:
version "0.2.3"
@@ -4506,6 +4698,18 @@
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+globby@^11.0.1:
+ version "11.0.1"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357"
+ integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.1.1"
+ ignore "^5.1.4"
+ merge2 "^1.3.0"
+ slash "^3.0.0"
+
globby@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-4.1.0.tgz#080f54549ec1b82a6c60e631fc82e1211dbe95f8"
@@ -4634,25 +4838,25 @@
dependencies:
lodash "^4.17.2"
-gts@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/gts/-/gts-2.0.2.tgz#b8b28de99361b5c5c24db30a375a0f546bbc04a4"
- integrity sha512-SLytzl2IqKXf6kGULwr07XQ9lVsvjrzFD3OAA7DEfIQYuD+lKBPt/cZ/RYGxaWerY4PTfmnXT7KdxEr9Ec8uHQ==
+gts@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/gts/-/gts-3.0.3.tgz#36716d87680c2d1a0e02867c91bb7169cede9369"
+ integrity sha512-XHFGhDzoyaHDVHlhNfz369erxuSEIyVMtJoRAz8Dt2NpidG5pOJzI/44lWhsLVigph64TgAWPWBsBTQFCQ1mTw==
dependencies:
- "@typescript-eslint/eslint-plugin" "2.31.0"
- "@typescript-eslint/parser" "2.31.0"
- chalk "^4.0.0"
- eslint "^6.8.0"
- eslint-config-prettier "^6.10.1"
+ "@typescript-eslint/eslint-plugin" "^4.2.0"
+ "@typescript-eslint/parser" "^4.2.0"
+ chalk "^4.1.0"
+ eslint "^7.10.0"
+ eslint-config-prettier "^6.12.0"
eslint-plugin-node "^11.1.0"
- eslint-plugin-prettier "^3.1.2"
- execa "^4.0.0"
- inquirer "^7.1.0"
- meow "^7.0.0"
+ eslint-plugin-prettier "^3.1.4"
+ execa "^5.0.0"
+ inquirer "^7.3.3"
+ meow "^8.0.0"
ncp "^2.0.0"
- prettier "^2.0.4"
+ prettier "^2.1.2"
rimraf "^3.0.2"
- update-notifier "^4.1.0"
+ update-notifier "^5.0.0"
write-file-atomic "^3.0.3"
gulp-if@^2.0.2:
@@ -4838,6 +5042,13 @@
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==
+hosted-git-info@^3.0.6:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-3.0.7.tgz#a30727385ea85acfcee94e0aad9e368c792e036c"
+ integrity sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==
+ dependencies:
+ lru-cache "^6.0.0"
+
hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
@@ -4861,17 +5072,15 @@
relateurl "0.2.x"
uglify-js "3.4.x"
-htmlparser2@^3.10.1:
- version "3.10.1"
- resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
- integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
+htmlparser2@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-5.0.1.tgz#7daa6fc3e35d6107ac95a4fc08781f091664f6e7"
+ integrity sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==
dependencies:
- domelementtype "^1.3.1"
- domhandler "^2.3.0"
- domutils "^1.5.1"
- entities "^1.1.1"
- inherits "^2.0.1"
- readable-stream "^3.1.1"
+ domelementtype "^2.0.1"
+ domhandler "^3.3.0"
+ domutils "^2.4.2"
+ entities "^2.0.0"
http-cache-semantics@^4.0.0:
version "4.1.0"
@@ -4948,10 +5157,10 @@
agent-base "^4.3.0"
debug "^3.1.0"
-human-signals@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
- integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
@@ -4982,7 +5191,7 @@
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
-ignore@^5.1.1:
+ignore@^5.1.1, ignore@^5.1.4:
version "5.1.8"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
@@ -4995,6 +5204,14 @@
parent-module "^1.0.0"
resolve-from "^4.0.0"
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
@@ -5045,7 +5262,12 @@
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
+ini@1.3.7:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
+ integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
+
+ini@^1.3.4, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@@ -5089,40 +5311,21 @@
strip-ansi "^5.1.0"
through "^2.3.6"
-inquirer@^7.0.0:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.3.tgz#f9b4cd2dff58b9f73e8d43759436ace15bed4567"
- integrity sha512-+OiOVeVydu4hnCGLCSX+wedovR/Yzskv9BFqUNNKq9uU2qg7LCcCo3R86S2E7WLo0y/x2pnEZfZe1CoYnORUAw==
+inquirer@^7.3.3:
+ version "7.3.3"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
+ integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
dependencies:
ansi-escapes "^4.2.1"
- chalk "^2.4.2"
+ chalk "^4.1.0"
cli-cursor "^3.1.0"
- cli-width "^2.0.0"
+ cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
- lodash "^4.17.15"
- mute-stream "0.0.8"
- run-async "^2.2.0"
- rxjs "^6.5.3"
- string-width "^4.1.0"
- strip-ansi "^5.1.0"
- through "^2.3.6"
-
-inquirer@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.2.0.tgz#63ce99d823090de7eb420e4bb05e6f3449aa389a"
- integrity sha512-E0c4rPwr9ByePfNlTIB8z51kK1s2n6jrHuJeEHENl/sbq2G/S1auvibgEwNR4uSyiU+PiYHqSwsgGiXjG8p5ZQ==
- dependencies:
- ansi-escapes "^4.2.1"
- chalk "^3.0.0"
- cli-cursor "^3.1.0"
- cli-width "^2.0.0"
- external-editor "^3.0.3"
- figures "^3.0.0"
- lodash "^4.17.15"
+ lodash "^4.17.19"
mute-stream "0.0.8"
run-async "^2.4.0"
- rxjs "^6.5.3"
+ rxjs "^6.6.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
@@ -5185,10 +5388,10 @@
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-callable@^1.1.4, is-callable@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab"
- integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==
+is-callable@^1.1.4, is-callable@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9"
+ integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==
is-ci@^1.0.10:
version "1.2.1"
@@ -5204,6 +5407,13 @@
dependencies:
ci-info "^2.0.0"
+is-core-module@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
+ integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
+ dependencies:
+ has "^1.0.3"
+
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -5338,7 +5548,7 @@
global-dirs "^0.1.0"
is-path-inside "^1.0.0"
-is-installed-globally@^0.3.1:
+is-installed-globally@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==
@@ -5346,15 +5556,20 @@
global-dirs "^2.0.1"
is-path-inside "^3.0.1"
+is-negative-zero@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
+ integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
+
is-npm@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
-is-npm@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
- integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
+is-npm@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8"
+ integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==
is-number@^2.1.0:
version "2.1.0"
@@ -5375,6 +5590,11 @@
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
@@ -5458,12 +5678,12 @@
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
-is-regex@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae"
- integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==
+is-regex@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9"
+ integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==
dependencies:
- has "^1.0.3"
+ has-symbols "^1.0.1"
is-retry-allowed@^1.0.0:
version "1.1.0"
@@ -5618,10 +5838,10 @@
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-jsdoctypeparser@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-6.1.0.tgz#acfb936c26300d98f1405cb03e20b06748e512a8"
- integrity sha512-UCQBZ3xCUBv/PLfwKAJhp6jmGOSLFNKzrotXGNgbKhWvz27wPsCsVeP7gIcHPElQw2agBmynAitXqhxR58XAmA==
+jsdoctypeparser@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz#8c97e2fb69315eb274b0f01377eaa5c940bd7b26"
+ integrity sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==
jsesc@^1.3.0:
version "1.3.0"
@@ -5648,6 +5868,11 @@
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+json-parse-even-better-errors@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@@ -5668,6 +5893,13 @@
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+json5@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
+ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ dependencies:
+ minimist "^1.2.0"
+
json5@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850"
@@ -5747,7 +5979,7 @@
dependencies:
package-json "^4.0.0"
-latest-version@^5.0.0:
+latest-version@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
@@ -5780,13 +6012,13 @@
dependencies:
readable-stream "^2.0.5"
-levn@^0.3.0, levn@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
- integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
dependencies:
- prelude-ls "~1.1.2"
- type-check "~0.3.2"
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
lines-and-columns@^1.1.6:
version "1.1.6"
@@ -5947,6 +6179,11 @@
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.12.tgz#a712c74fdc31f7ecb20fe44f157d802d208097ef"
integrity sha512-+CiwtLnsJhX03p20mwXuvhoebatoh5B3tt+VvYlrPgZC1g36y+RRbkufX95Xa+X4I59aWEacDFYwnJZiyBh9gA==
+lodash@^4.17.19, lodash@^4.17.20:
+ version "4.17.20"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+ integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+
log-symbols@^1.0.0, log-symbols@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@@ -6031,6 +6268,13 @@
pseudomap "^1.0.2"
yallist "^2.1.2"
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
macos-release@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
@@ -6147,24 +6391,22 @@
redent "^1.0.0"
trim-newlines "^1.0.0"
-meow@^7.0.0:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc"
- integrity sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==
+meow@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-8.0.0.tgz#1aa10ee61046719e334ffdc038bb5069250ec99a"
+ integrity sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==
dependencies:
"@types/minimist" "^1.2.0"
- arrify "^2.0.1"
- camelcase "^6.0.0"
camelcase-keys "^6.2.2"
decamelize-keys "^1.1.0"
hard-rejection "^2.1.0"
- minimist-options "^4.0.2"
- normalize-package-data "^2.5.0"
+ minimist-options "4.1.0"
+ normalize-package-data "^3.0.0"
read-pkg-up "^7.0.1"
redent "^3.0.0"
trim-newlines "^3.0.0"
- type-fest "^0.13.1"
- yargs-parser "^18.1.3"
+ type-fest "^0.18.0"
+ yargs-parser "^20.2.3"
merge-descriptors@1.0.1:
version "1.0.1"
@@ -6188,6 +6430,11 @@
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5"
integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==
+merge2@^1.3.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@@ -6231,6 +6478,14 @@
snapdragon "^0.8.1"
to-regex "^3.0.2"
+micromatch@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
+ integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
+ dependencies:
+ braces "^3.0.1"
+ picomatch "^2.0.5"
+
mime-db@1.40.0, mime-db@^1.28.0:
version "1.40.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
@@ -6309,7 +6564,7 @@
dependencies:
brace-expansion "^1.1.7"
-minimist-options@^4.0.2:
+minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
@@ -6373,7 +6628,7 @@
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
-ms@^2.1.1:
+ms@2.1.2, ms@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
@@ -6549,6 +6804,16 @@
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
+normalize-package-data@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.0.tgz#1f8a7c423b3d2e85eb36985eaf81de381d01301a"
+ integrity sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==
+ dependencies:
+ hosted-git-info "^3.0.6"
+ resolve "^1.17.0"
+ semver "^7.3.2"
+ validate-npm-package-license "^3.0.1"
+
normalize-path@^2.0.0, normalize-path@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -6586,7 +6851,7 @@
dependencies:
path-key "^2.0.0"
-npm-run-path@^4.0.0:
+npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@@ -6632,10 +6897,10 @@
define-property "^0.2.5"
kind-of "^3.0.3"
-object-inspect@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
- integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
+object-inspect@^1.8.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
+ integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
@@ -6659,10 +6924,15 @@
has-symbols "^1.0.0"
object-keys "^1.0.11"
-object.entries-ponyfill@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/object.entries-ponyfill/-/object.entries-ponyfill-1.0.1.tgz#29abdf77cbfbd26566dd1aa24e9d88f65433d256"
- integrity sha1-Kavfd8v70mVm3RqiTp2I9lQz0lY=
+object.assign@^4.1.1:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
+ integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
+ dependencies:
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+ has-symbols "^1.0.1"
+ object-keys "^1.1.1"
object.omit@^2.0.0:
version "2.0.1"
@@ -6679,14 +6949,14 @@
dependencies:
isobject "^3.0.1"
-object.values@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e"
- integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==
+object.values@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731"
+ integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- es-abstract "^1.17.0-next.1"
- function-bind "^1.1.1"
+ es-abstract "^1.18.0-next.1"
has "^1.0.3"
obuf@^1.0.0, obuf@^1.1.1:
@@ -6735,10 +7005,10 @@
dependencies:
mimic-fn "^1.0.0"
-onetime@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5"
- integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==
+onetime@^5.1.0, onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
@@ -6757,17 +7027,17 @@
minimist "~0.0.1"
wordwrap "~0.0.2"
-optionator@^0.8.3:
- version "0.8.3"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
- integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
dependencies:
- deep-is "~0.1.3"
- fast-levenshtein "~2.0.6"
- levn "~0.3.0"
- prelude-ls "~1.1.2"
- type-check "~0.3.2"
- word-wrap "~1.2.3"
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
ordered-read-streams@^0.3.0:
version "0.3.0"
@@ -6962,13 +7232,13 @@
json-parse-better-errors "^1.0.1"
parse-json@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f"
- integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646"
+ integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==
dependencies:
"@babel/code-frame" "^7.0.0"
error-ex "^1.3.1"
- json-parse-better-errors "^1.0.1"
+ json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
parse-passwd@^1.0.0:
@@ -7094,6 +7364,11 @@
dependencies:
pify "^3.0.0"
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
peek-stream@^1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67"
@@ -7123,6 +7398,11 @@
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+picomatch@^2.0.5, picomatch@^2.2.1:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
+ integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
+
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -7446,10 +7726,10 @@
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-prelude-ls@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
- integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prepend-http@^1.0.1:
version "1.0.4"
@@ -7473,11 +7753,16 @@
dependencies:
fast-diff "^1.1.2"
-prettier@2.0.5, prettier@^2.0.4:
+prettier@2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
+prettier@^2.1.2:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
+ integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
+
pretty-bytes@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"
@@ -7583,10 +7868,10 @@
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-pupa@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726"
- integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==
+pupa@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
+ integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
dependencies:
escape-goat "^2.0.0"
@@ -7861,12 +8146,7 @@
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
-regexpp@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
- integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
-
-regexpp@^3.0.0:
+regexpp@^3.0.0, regexpp@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
@@ -7883,10 +8163,10 @@
unicode-match-property-ecmascript "^1.0.4"
unicode-match-property-value-ecmascript "^1.1.0"
-regextras@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.0.tgz#2298bef8cfb92b1b7e3b9b12aa8f69547b7d71e4"
- integrity sha512-ds+fL+Vhl918gbAUb0k2gVKbTZLsg84Re3DI6p85Et0U0tYME3hyW4nMK8Px4dtDaBA2qNjvG5uWyW7eK5gfmw==
+regextras@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.7.1.tgz#be95719d5f43f9ef0b9fa07ad89b7c606995a3b2"
+ integrity sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==
registry-auth-token@^3.0.1:
version "3.4.0"
@@ -7897,9 +8177,9 @@
safe-buffer "^5.0.1"
registry-auth-token@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479"
- integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
+ integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==
dependencies:
rc "^1.2.8"
@@ -8042,11 +8322,12 @@
dependencies:
path-parse "^1.0.6"
-resolve@^1.12.0, resolve@^1.13.1:
- version "1.15.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"
- integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==
+resolve@^1.13.1, resolve@^1.17.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
+ integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
dependencies:
+ is-core-module "^2.1.0"
path-parse "^1.0.6"
resolve@^1.5.0:
@@ -8092,7 +8373,12 @@
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2:
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
@@ -8146,6 +8432,11 @@
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
+run-parallel@^1.1.9:
+ version "1.1.10"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef"
+ integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==
+
rx@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
@@ -8158,10 +8449,10 @@
dependencies:
tslib "^1.9.0"
-rxjs@^6.5.3:
- version "6.5.4"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
- integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
+rxjs@^6.6.0:
+ version "6.6.3"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
+ integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
dependencies:
tslib "^1.9.0"
@@ -8261,11 +8552,18 @@
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
-semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
+semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+semver@^7.2.1, semver@^7.3.2, semver@^7.3.4:
+ version "7.3.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
+ integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
+ dependencies:
+ lru-cache "^6.0.0"
+
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@@ -8392,6 +8690,11 @@
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
+signal-exit@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
+ integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
@@ -8423,14 +8726,19 @@
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
-slice-ansi@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
- integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slice-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+ integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
dependencies:
- ansi-styles "^3.2.0"
- astral-regex "^1.0.0"
- is-fullwidth-code-point "^2.0.0"
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
slide@^1.1.5:
version "1.1.6"
@@ -8607,6 +8915,14 @@
spdx-exceptions "^2.1.0"
spdx-license-ids "^3.0.0"
+spdx-expression-parse@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
spdx-license-ids@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1"
@@ -8748,7 +9064,7 @@
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
-string-width@^4.0.0, string-width@^4.1.0:
+string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
@@ -8757,21 +9073,21 @@
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.0"
-string.prototype.trimleft@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74"
- integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==
+string.prototype.trimend@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b"
+ integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- function-bind "^1.1.1"
-string.prototype.trimright@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9"
- integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==
+string.prototype.trimstart@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa"
+ integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==
dependencies:
+ call-bind "^1.0.0"
define-properties "^1.1.3"
- function-bind "^1.1.1"
string_decoder@^1.1.1:
version "1.3.0"
@@ -8806,7 +9122,7 @@
dependencies:
ansi-regex "^3.0.0"
-strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+strip-ansi@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
@@ -8882,10 +9198,10 @@
dependencies:
min-indent "^1.0.0"
-strip-json-comments@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
- integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
strip-json-comments@~2.0.1:
version "2.0.1"
@@ -8946,15 +9262,15 @@
typical "^2.6.1"
wordwrapjs "^3.0.0"
-table@^5.2.3:
- version "5.4.6"
- resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
- integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==
+table@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.0.4.tgz#c523dd182177e926c723eb20e1b341238188aa0d"
+ integrity sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw==
dependencies:
- ajv "^6.10.2"
- lodash "^4.17.14"
- slice-ansi "^2.1.0"
- string-width "^3.0.0"
+ ajv "^6.12.4"
+ lodash "^4.17.20"
+ slice-ansi "^4.0.0"
+ string-width "^4.2.0"
tar-fs@^1.12.0:
version "1.16.3"
@@ -9037,9 +9353,9 @@
execa "^0.7.0"
term-size@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753"
- integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
+ integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==
ternary-stream@^2.0.1:
version "2.0.1"
@@ -9209,6 +9525,13 @@
is-number "^3.0.0"
repeat-string "^1.6.1"
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@@ -9259,6 +9582,16 @@
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
+tsconfig-paths@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
+ integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.1"
+ minimist "^1.2.0"
+ strip-bom "^3.0.0"
+
tslib@^1.8.1:
version "1.13.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
@@ -9295,22 +9628,27 @@
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-type-check@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
- integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
dependencies:
- prelude-ls "~1.1.2"
+ prelude-ls "^1.2.1"
type-detect@^4.0.0:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-type-fest@^0.13.1:
- version "0.13.1"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
- integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
+type-fest@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
+ integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
+
+type-fest@^0.18.0:
+ version "0.18.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
+ integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
type-fest@^0.6.0:
version "0.6.0"
@@ -9342,10 +9680,10 @@
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typescript@3.9.5:
- version "3.9.5"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36"
- integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==
+typescript@4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
+ integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
typical@^2.6.1:
version "2.6.1"
@@ -9507,22 +9845,23 @@
semver-diff "^2.0.0"
xdg-basedir "^3.0.0"
-update-notifier@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3"
- integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==
+update-notifier@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.0.1.tgz#1f92d45fb1f70b9e33880a72dd262bc12d22c20d"
+ integrity sha512-BuVpRdlwxeIOvmc32AGYvO1KVdPlsmqSh8KDDBxS6kDE5VR7R8OMP1d8MdhaVBvxl4H3551k9akXr0Y1iIB2Wg==
dependencies:
boxen "^4.2.0"
- chalk "^3.0.0"
+ chalk "^4.1.0"
configstore "^5.0.1"
has-yarn "^2.1.0"
import-lazy "^2.1.0"
is-ci "^2.0.0"
- is-installed-globally "^0.3.1"
- is-npm "^4.0.0"
+ is-installed-globally "^0.3.2"
+ is-npm "^5.0.0"
is-yarn-global "^0.3.0"
- latest-version "^5.0.0"
- pupa "^2.0.1"
+ latest-version "^5.1.0"
+ pupa "^2.1.1"
+ semver "^7.3.2"
semver-diff "^3.1.1"
xdg-basedir "^4.0.0"
@@ -9893,7 +10232,7 @@
p-try "^2.1.0"
pify "^4.0.1"
-word-wrap@~1.2.3:
+word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
@@ -9944,13 +10283,6 @@
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
-write@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"
- integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==
- dependencies:
- mkdirp "^0.5.1"
-
ws@^7.1.2:
version "7.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.1.tgz#03ed52423cd744084b2cf42ed197c8b65a936b8e"
@@ -10010,13 +10342,15 @@
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
-yargs-parser@^18.1.3:
- version "18.1.3"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
- integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
- dependencies:
- camelcase "^5.0.0"
- decamelize "^1.2.0"
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yargs-parser@^20.2.3:
+ version "20.2.4"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
+ integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
yauzl@^2.10.0:
version "2.10.0"