summaryrefslogtreecommitdiffstats
path: root/vendor/gix-submodule
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/gix-submodule
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-submodule')
-rw-r--r--vendor/gix-submodule/.cargo-checksum.json1
-rw-r--r--vendor/gix-submodule/CHANGELOG.md179
-rw-r--r--vendor/gix-submodule/Cargo.toml47
-rw-r--r--vendor/gix-submodule/LICENSE-APACHE191
-rw-r--r--vendor/gix-submodule/LICENSE-MIT21
-rw-r--r--vendor/gix-submodule/src/access.rs248
-rw-r--r--vendor/gix-submodule/src/config.rs216
-rw-r--r--vendor/gix-submodule/src/is_active_platform.rs49
-rw-r--r--vendor/gix-submodule/src/lib.rs144
-rw-r--r--vendor/gix-submodule/tests/file/baseline.rs80
-rw-r--r--vendor/gix-submodule/tests/file/mod.rs453
-rwxr-xr-xvendor/gix-submodule/tests/fixtures/basic.sh48
-rw-r--r--vendor/gix-submodule/tests/fixtures/generated-archives/basic.tar.xzbin0 -> 32472 bytes
-rw-r--r--vendor/gix-submodule/tests/submodule.rs3
14 files changed, 1680 insertions, 0 deletions
diff --git a/vendor/gix-submodule/.cargo-checksum.json b/vendor/gix-submodule/.cargo-checksum.json
new file mode 100644
index 000000000..6b7ad8938
--- /dev/null
+++ b/vendor/gix-submodule/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"0aea97d3e31f29941e3a88f4860b893321f455ee0e1244ce08bce0e5446c41a0","Cargo.toml":"7dab80e931c6f5c9fae910a71694c95b229756153f0aff62cfd548d438a3b6e8","LICENSE-APACHE":"cb4780590812826851ba250f90bed0ed19506ec98f6865a0e2e20bbf62391ff9","LICENSE-MIT":"49df47913ab2beafe8dc45607877ae64198bf0eee64aaad3e82ed9e4d27424e8","src/access.rs":"162ad231287795c40681f47eb516b91c706215687ea7ed7d7a98b762feb46d8c","src/config.rs":"2062c34f82e42517ac0d8d2d564643883249f6f44b5e8cc49f00f085ce66b31d","src/is_active_platform.rs":"fa89ba25ae7cde8f0b04bb032a27ad22919aeea7d285c003355cd9ea0d980157","src/lib.rs":"a896e4f0188322673835674b49be1b013f4aefa997fe25f34ad8d4fcc9c8d850","tests/file/baseline.rs":"8d80db5bdfcb0625153617c39fdada700921487a083391822dec4363c33fadb4","tests/file/mod.rs":"aa7b943bf8518e79df663e0de32b0266ac00bae2aa9f9c7653cf6745031a14a1","tests/fixtures/basic.sh":"22a14fd8fac3377b9a7653f60348ba0906777b2ecc23405c4b604c4834e7eec4","tests/fixtures/generated-archives/basic.tar.xz":"f1213af1023577c8c59e1a065530785e28ee10e4e04f731597aebc6a63e3dc86","tests/submodule.rs":"e42d1f34b35a3230f29ae4f04524c113b5059aa5753bbee1818e245888457ddd"},"package":"dd0150e82e9282d3f2ab2dd57a22f9f6c3447b9d9856e5321ac92d38e3e0e2b7"} \ No newline at end of file
diff --git a/vendor/gix-submodule/CHANGELOG.md b/vendor/gix-submodule/CHANGELOG.md
new file mode 100644
index 000000000..f5a4ed63e
--- /dev/null
+++ b/vendor/gix-submodule/CHANGELOG.md
@@ -0,0 +1,179 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 0.4.0 (2023-09-24)
+
+A maintenance release without user-facing changes.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 1 commit contributed to the release.
+ - 15 days passed between releases.
+ - 0 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Prepare changelogs prior to release ([`8a60d5b`](https://github.com/Byron/gitoxide/commit/8a60d5b80877c213c3b646d3061e8a33e0e433ec))
+</details>
+
+## 0.3.0 (2023-09-08)
+
+### Bug Fixes (BREAKING)
+
+ - <csr-id-072ee32f693a31161cd6a843da6582d13efbb20b/> use `dyn` trait where possible.
+ This reduces compile time due to avoiding duplication.
+ - <csr-id-25c5bcebd4dbc4ac189d8af044ed0352c6188ce8/> `IsActivePlatform::is_active()` now only considers the URL in passed configuration
+ Previously, it would consider the presence of `url` in the `.gitmodules` file as well, which is
+ not the way git does it.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 10 commits contributed to the release over the course of 17 calendar days.
+ - 17 days passed between releases.
+ - 2 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-transport v0.36.0, gix-protocol v0.39.0, gix-revision v0.21.0, gix-refspec v0.17.0, gix-submodule v0.3.0, gix-worktree v0.25.0, gix-worktree-state v0.2.0, gix v0.53.0 ([`1ff3064`](https://github.com/Byron/gitoxide/commit/1ff30641b8724efd6699d8bef5c71d28454e98b9))
+ - Release gix-date v0.8.0, gix-hash v0.13.0, gix-features v0.34.0, gix-actor v0.26.0, gix-object v0.36.0, gix-path v0.10.0, gix-glob v0.12.0, gix-attributes v0.18.0, gix-packetline-blocking v0.16.6, gix-filter v0.4.0, gix-fs v0.6.0, gix-commitgraph v0.20.0, gix-hashtable v0.4.0, gix-revwalk v0.7.0, gix-traverse v0.32.0, gix-worktree-stream v0.4.0, gix-archive v0.4.0, gix-config-value v0.14.0, gix-tempfile v9.0.0, gix-lock v9.0.0, gix-ref v0.36.0, gix-sec v0.10.0, gix-config v0.29.0, gix-prompt v0.7.0, gix-url v0.23.0, gix-credentials v0.19.0, gix-diff v0.35.0, gix-discover v0.24.0, gix-ignore v0.7.0, gix-index v0.24.0, gix-macros v0.1.0, gix-mailmap v0.18.0, gix-negotiate v0.7.0, gix-pack v0.42.0, gix-odb v0.52.0, gix-pathspec v0.2.0, gix-packetline v0.16.6, gix-transport v0.36.0, gix-protocol v0.39.0, gix-revision v0.21.0, gix-refspec v0.17.0, gix-submodule v0.3.0, gix-worktree v0.25.0, gix-worktree-state v0.2.0, gix v0.53.0, safety bump 39 crates ([`8bd0456`](https://github.com/Byron/gitoxide/commit/8bd045676bb2cdc02624ab93e73ff8518064ca38))
+ - Prepare changelogs for release ([`375db06`](https://github.com/Byron/gitoxide/commit/375db06a8442378c3f7a922fae38e2a6694d9d04))
+ - Merge branch 'optimizations' ([`6135a5e`](https://github.com/Byron/gitoxide/commit/6135a5ea8709646f01da62939a59dd3a9750e007))
+ - Add example that tries to trip someone who reads something from the index ([`b35e544`](https://github.com/Byron/gitoxide/commit/b35e544383b9a7571961ff0628ca8db1b232bf52))
+ - Merge branch `dyn`ification ([`f658fcc`](https://github.com/Byron/gitoxide/commit/f658fcc52dc2200ae34ca53dc10be97fb9012057))
+ - Use `dyn` trait where possible. ([`072ee32`](https://github.com/Byron/gitoxide/commit/072ee32f693a31161cd6a843da6582d13efbb20b))
+ - Merge branch 'adjustments-for-cargo' ([`b7560a2`](https://github.com/Byron/gitoxide/commit/b7560a2445b62f888bf5aa2ba4c5a47ae037cb23))
+ - `IsActivePlatform::is_active()` now only considers the URL in passed configuration ([`25c5bce`](https://github.com/Byron/gitoxide/commit/25c5bcebd4dbc4ac189d8af044ed0352c6188ce8))
+ - Merge branch 'gix-submodule' ([`363ee77`](https://github.com/Byron/gitoxide/commit/363ee77400805f473c9ad66eadad9214e7ab66f4))
+</details>
+
+## 0.2.0 (2023-08-22)
+
+<csr-id-229bd4899213f749a7cc124aa2b82a1368fba40f/>
+
+### Chore
+
+ - <csr-id-229bd4899213f749a7cc124aa2b82a1368fba40f/> don't call crate 'WIP' in manifest anymore.
+
+### New Features
+
+ - <csr-id-af1cab31fd5ead445c988cce058c136c81229ad1/> TBD a way to learn if submodules are active efficiently
+
+### Bug Fixes
+
+ - <csr-id-e0d9b09d02f88536b93ab6a31fddf9483881c5c1/> `Modules::is_active()` now counts everything that doesn't match `submodule.active` (if present) as inactive.
+ - <csr-id-8172f0e0f19e84fdaedceb87399f3fab4a1eb563/> Assure `gix-submodule` works with Rust 1.65.
+ The previous version of this loop, possibly preferable, ran into
+ a borrow-check issue that was no more from Rust 1.70 onwards.
+
+### New Features (BREAKING)
+
+ - <csr-id-3503f4948b42854256c9e8d8336ebe222fee980b/> remove `File::names_and_active_state()` in favor of `File::is_active_platform()`.
+ With this platform it's possible to make repeated checks to see if a named submodule is active.
+ - <csr-id-4a443e453285095daccdca0fed9e8486ce7892ab/> make API less error prone by enforcing overrides at instantiation time.
+ It's made so that overrides can still be applied at a later point.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 13 commits contributed to the release over the course of 4 calendar days.
+ - 15 days passed between releases.
+ - 6 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 0 issues like '(#ID)' were seen in commit messages
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **Uncategorized**
+ - Release gix-url v0.22.0, gix-credentials v0.18.0, gix-diff v0.34.0, gix-discover v0.23.0, gix-ignore v0.6.0, gix-bitmap v0.2.7, gix-index v0.22.0, gix-mailmap v0.17.0, gix-negotiate v0.6.0, gix-pack v0.41.0, gix-odb v0.51.0, gix-pathspec v0.1.0, gix-packetline v0.16.5, gix-transport v0.35.0, gix-protocol v0.38.0, gix-revision v0.20.0, gix-refspec v0.16.0, gix-submodule v0.2.0, gix-worktree v0.24.0, gix-worktree-state v0.1.0, gix v0.52.0, gitoxide-core v0.31.0, gitoxide v0.29.0 ([`6c62e74`](https://github.com/Byron/gitoxide/commit/6c62e748240ac0980fc23fdf30f8477dea8b9bc3))
+ - Release gix-date v0.7.3, gix-hash v0.12.0, gix-features v0.33.0, gix-actor v0.25.0, gix-object v0.35.0, gix-path v0.9.0, gix-glob v0.11.0, gix-quote v0.4.7, gix-attributes v0.17.0, gix-command v0.2.9, gix-packetline-blocking v0.16.5, gix-filter v0.3.0, gix-fs v0.5.0, gix-commitgraph v0.19.0, gix-hashtable v0.3.0, gix-revwalk v0.6.0, gix-traverse v0.31.0, gix-worktree-stream v0.3.0, gix-archive v0.3.0, gix-config-value v0.13.0, gix-tempfile v8.0.0, gix-lock v8.0.0, gix-ref v0.35.0, gix-sec v0.9.0, gix-config v0.28.0, gix-prompt v0.6.0, gix-url v0.22.0, gix-credentials v0.18.0, gix-diff v0.34.0, gix-discover v0.23.0, gix-ignore v0.6.0, gix-bitmap v0.2.7, gix-index v0.22.0, gix-mailmap v0.17.0, gix-negotiate v0.6.0, gix-pack v0.41.0, gix-odb v0.51.0, gix-pathspec v0.1.0, gix-packetline v0.16.5, gix-transport v0.35.0, gix-protocol v0.38.0, gix-revision v0.20.0, gix-refspec v0.16.0, gix-submodule v0.2.0, gix-worktree v0.24.0, gix-worktree-state v0.1.0, gix v0.52.0, gitoxide-core v0.31.0, gitoxide v0.29.0, safety bump 41 crates ([`30b2761`](https://github.com/Byron/gitoxide/commit/30b27615047692d3ced1b2d9c2ac15a80f79fbee))
+ - Update changelogs prior to release ([`f23ea88`](https://github.com/Byron/gitoxide/commit/f23ea8828f2d9ba7559973daca388c9591bcc5fc))
+ - Merge branch 'gix-submodule' ([`8f3f358`](https://github.com/Byron/gitoxide/commit/8f3f358800f1fe77d7ba7ebd396a90b692d3c0c1))
+ - `Modules::is_active()` now counts everything that doesn't match `submodule.active` (if present) as inactive. ([`e0d9b09`](https://github.com/Byron/gitoxide/commit/e0d9b09d02f88536b93ab6a31fddf9483881c5c1))
+ - Just fmt ([`0d258f4`](https://github.com/Byron/gitoxide/commit/0d258f40afcd848509e2b0c7c264e9f346ed1726))
+ - Merge branch 'submodule-in-gix' ([`36f7b78`](https://github.com/Byron/gitoxide/commit/36f7b783c67b8a087076a130f5ee9b90b23bc3cc))
+ - Remove `File::names_and_active_state()` in favor of `File::is_active_platform()`. ([`3503f49`](https://github.com/Byron/gitoxide/commit/3503f4948b42854256c9e8d8336ebe222fee980b))
+ - Make API less error prone by enforcing overrides at instantiation time. ([`4a443e4`](https://github.com/Byron/gitoxide/commit/4a443e453285095daccdca0fed9e8486ce7892ab))
+ - Assure `gix-submodule` works with Rust 1.65. ([`8172f0e`](https://github.com/Byron/gitoxide/commit/8172f0e0f19e84fdaedceb87399f3fab4a1eb563))
+ - Don't call crate 'WIP' in manifest anymore. ([`229bd48`](https://github.com/Byron/gitoxide/commit/229bd4899213f749a7cc124aa2b82a1368fba40f))
+ - Merge branch 'submodule-active' ([`a3afaa4`](https://github.com/Byron/gitoxide/commit/a3afaa42741616a0f1abeef9b54557e7c2b800cb))
+ - TBD a way to learn if submodules are active efficiently ([`af1cab3`](https://github.com/Byron/gitoxide/commit/af1cab31fd5ead445c988cce058c136c81229ad1))
+</details>
+
+## 0.1.0 (2023-08-07)
+
+<csr-id-f7f136dbe4f86e7dee1d54835c420ec07c96cd78/>
+<csr-id-533e887e80c5f7ede8392884562e1c5ba56fb9a8/>
+<csr-id-3d8fa8fef9800b1576beab8a5bc39b821157a5ed/>
+
+The initial release.
+
+### Commit Statistics
+
+<csr-read-only-do-not-edit/>
+
+ - 27 commits contributed to the release over the course of 518 calendar days.
+ - 3 commits were understood as [conventional](https://www.conventionalcommits.org).
+ - 2 unique issues were worked on: [#301](https://github.com/Byron/gitoxide/issues/301), [#691](https://github.com/Byron/gitoxide/issues/691)
+
+### Commit Details
+
+<csr-read-only-do-not-edit/>
+
+<details><summary>view details</summary>
+
+ * **[#301](https://github.com/Byron/gitoxide/issues/301)**
+ - Prepare changelog ([`010ab15`](https://github.com/Byron/gitoxide/commit/010ab1542ec447bb2b825335dab322c5bb21a1aa))
+ - Add stub for git-submodule ([`3f9bcd8`](https://github.com/Byron/gitoxide/commit/3f9bcd8a0608dbdc5673da055c65d9dc995f03f1))
+ * **[#691](https://github.com/Byron/gitoxide/issues/691)**
+ - Set `rust-version` to 1.64 ([`55066ce`](https://github.com/Byron/gitoxide/commit/55066ce5fd71209abb5d84da2998b903504584bb))
+ * **Uncategorized**
+ - Release gix-glob v0.10.2, gix-date v0.7.2, gix-validate v0.8.0, gix-object v0.34.0, gix-ref v0.34.0, gix-config v0.27.0, gix-commitgraph v0.18.2, gix-revwalk v0.5.0, gix-revision v0.19.0, gix-refspec v0.15.0, gix-submodule v0.1.0, safety bump 18 crates ([`4604f83`](https://github.com/Byron/gitoxide/commit/4604f83ef238dc07c85aaeae097399b67f3cfd0c))
+ - Finailize `gix-submodule` changelog ([`cbe8e62`](https://github.com/Byron/gitoxide/commit/cbe8e622b306d072fa8e7f5bf25dc596810a48d2))
+ - Set `gix-submodule` to version 0.1.0 ([`931fd1e`](https://github.com/Byron/gitoxide/commit/931fd1ec4416aa4869f097b1a3a2e82744da4c21))
+ - Prepare changelogs prior to release of `gix-submodule` ([`f3c4311`](https://github.com/Byron/gitoxide/commit/f3c43110e8d5f16cf87e50821044d8b3edbae235))
+ - Merge branch 'submodules' ([`b629f8a`](https://github.com/Byron/gitoxide/commit/b629f8a774931d58c0a9b124fa75f85807c6c5d1))
+ - `.gitmodule` file abstraction ([`6a2e6a4`](https://github.com/Byron/gitoxide/commit/6a2e6a436f76c8bbf2487f9967413a51356667a0))
+ - Update license field following SPDX 2.1 license expression standard ([`9064ea3`](https://github.com/Byron/gitoxide/commit/9064ea31fae4dc59a56bdd3a06c0ddc990ee689e))
+ - Merge branch 'corpus' ([`aa16c8c`](https://github.com/Byron/gitoxide/commit/aa16c8ce91452a3e3063cf1cf0240b6014c4743f))
+ - Change MSRV to 1.65 ([`4f635fc`](https://github.com/Byron/gitoxide/commit/4f635fc4429350bae2582d25de86429969d28f30))
+ - Merge branch 'main' into auto-clippy ([`3ef5c90`](https://github.com/Byron/gitoxide/commit/3ef5c90aebce23385815f1df674c1d28d58b4b0d))
+ - Merge branch 'blinxen/main' ([`9375cd7`](https://github.com/Byron/gitoxide/commit/9375cd75b01aa22a0e2eed6305fe45fabfd6c1ac))
+ - Include license files in all crates ([`facaaf6`](https://github.com/Byron/gitoxide/commit/facaaf633f01c857dcf2572c6dbe0a92b7105c1c))
+ - Merge branch 'rename-crates' into inform-about-gix-rename ([`c9275b9`](https://github.com/Byron/gitoxide/commit/c9275b99ea43949306d93775d9d78c98fb86cfb1))
+ - Adjust to renaming of `git-submodule` to `gix-submodule` ([`2c4a2d0`](https://github.com/Byron/gitoxide/commit/2c4a2d0113d5e60c50d2d72a1ff1cdf3e8ae77af))
+ - Rename `git-submodule` to `gix-submodule` ([`d9a84a2`](https://github.com/Byron/gitoxide/commit/d9a84a2a4f5ca9b62857379135ac6be742363156))
+ - Merge branch 'main' into http-config ([`bcd9654`](https://github.com/Byron/gitoxide/commit/bcd9654e56169799eb706646da6ee1f4ef2021a9))
+ - Merge branch 'version2021' ([`0e4462d`](https://github.com/Byron/gitoxide/commit/0e4462df7a5166fe85c23a779462cdca8ee013e8))
+ - Upgrade edition to 2021 in most crates. ([`3d8fa8f`](https://github.com/Byron/gitoxide/commit/3d8fa8fef9800b1576beab8a5bc39b821157a5ed))
+ - Merge branch 'main' into index-from-tree ([`bc64b96`](https://github.com/Byron/gitoxide/commit/bc64b96a2ec781c72d1d4daad38aa7fb8b74f99b))
+ - Merge branch 'main' into remote-ls-refs ([`e2ee3de`](https://github.com/Byron/gitoxide/commit/e2ee3ded97e5c449933712883535b30d151c7c78))
+ - Merge branch 'docsrs-show-features' ([`31c2351`](https://github.com/Byron/gitoxide/commit/31c235140cad212d16a56195763fbddd971d87ce))
+ - Uniformize deny attributes ([`f7f136d`](https://github.com/Byron/gitoxide/commit/f7f136dbe4f86e7dee1d54835c420ec07c96cd78))
+ - Remove default link to cargo doc everywhere ([`533e887`](https://github.com/Byron/gitoxide/commit/533e887e80c5f7ede8392884562e1c5ba56fb9a8))
+ - Release git-submodule v0.0.0 ([`d16821a`](https://github.com/Byron/gitoxide/commit/d16821a20d8446004d4a4e0f52fd50ba68e95eb1))
+</details>
+
diff --git a/vendor/gix-submodule/Cargo.toml b/vendor/gix-submodule/Cargo.toml
new file mode 100644
index 000000000..51c44c86a
--- /dev/null
+++ b/vendor/gix-submodule/Cargo.toml
@@ -0,0 +1,47 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.65"
+name = "gix-submodule"
+version = "0.4.0"
+authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
+description = "A crate of the gitoxide project dealing git submodules"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/Byron/gitoxide"
+
+[lib]
+doctest = false
+
+[dependencies.bstr]
+version = "1.5.0"
+default-features = false
+
+[dependencies.gix-config]
+version = "^0.30.0"
+
+[dependencies.gix-path]
+version = "^0.10.0"
+
+[dependencies.gix-pathspec]
+version = "^0.3.0"
+
+[dependencies.gix-refspec]
+version = "^0.18.0"
+
+[dependencies.gix-url]
+version = "^0.24.0"
+
+[dependencies.thiserror]
+version = "1.0.44"
+
+[dev-dependencies]
diff --git a/vendor/gix-submodule/LICENSE-APACHE b/vendor/gix-submodule/LICENSE-APACHE
new file mode 100644
index 000000000..a51f59a06
--- /dev/null
+++ b/vendor/gix-submodule/LICENSE-APACHE
@@ -0,0 +1,191 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors)
+
+ 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.
diff --git a/vendor/gix-submodule/LICENSE-MIT b/vendor/gix-submodule/LICENSE-MIT
new file mode 100644
index 000000000..b58e818f1
--- /dev/null
+++ b/vendor/gix-submodule/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018-2021 Sebastian Thiel, and [contributors](https://github.com/byron/gitoxide/contributors).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/gix-submodule/src/access.rs b/vendor/gix-submodule/src/access.rs
new file mode 100644
index 000000000..4def2f42f
--- /dev/null
+++ b/vendor/gix-submodule/src/access.rs
@@ -0,0 +1,248 @@
+use std::{borrow::Cow, collections::HashSet, path::Path};
+
+use bstr::BStr;
+
+use crate::{
+ config,
+ config::{Branch, FetchRecurse, Ignore, Update},
+ File, IsActivePlatform,
+};
+
+/// High-Level Access
+///
+/// Note that all methods perform validation of the requested value and report issues right away.
+/// If a bypass is needed, use [`config()`](File::config()) for direct access.
+impl File {
+ /// Return the underlying configuration file.
+ ///
+ /// Note that it might have been merged with values from another configuration file and may
+ /// thus not be accurately reflecting that state of a `.gitmodules` file anymore.
+ pub fn config(&self) -> &gix_config::File<'static> {
+ &self.config
+ }
+
+ /// Return the path at which the `.gitmodules` file lives, if it is known.
+ pub fn config_path(&self) -> Option<&Path> {
+ self.config.sections().filter_map(|s| s.meta().path.as_deref()).next()
+ }
+
+ /// Return the unvalidated names of the submodules for which configuration is present.
+ ///
+ /// Note that these exact names have to be used for querying submodule values.
+ pub fn names(&self) -> impl Iterator<Item = &BStr> {
+ let mut seen = HashSet::<&BStr>::default();
+ self.config
+ .sections_by_name("submodule")
+ .into_iter()
+ .flatten()
+ .filter_map(move |s| {
+ s.header()
+ .subsection_name()
+ .filter(|_| s.meta().source == crate::init::META_MARKER)
+ .filter(|name| seen.insert(*name))
+ })
+ }
+
+ /// Similar to [Self::is_active_platform()], but automatically applies it to each name to learn if a submodule is active or not.
+ pub fn names_and_active_state<'a>(
+ &'a self,
+ config: &'a gix_config::File<'static>,
+ defaults: gix_pathspec::Defaults,
+ attributes: &'a mut (dyn FnMut(
+ &BStr,
+ gix_pathspec::attributes::glob::pattern::Case,
+ bool,
+ &mut gix_pathspec::attributes::search::Outcome,
+ ) -> bool
+ + 'a),
+ ) -> Result<
+ impl Iterator<Item = (&BStr, Result<bool, gix_config::value::Error>)> + 'a,
+ crate::is_active_platform::Error,
+ > {
+ let mut platform = self.is_active_platform(config, defaults)?;
+ let iter = self
+ .names()
+ .map(move |name| (name, platform.is_active(config, name, attributes)));
+ Ok(iter)
+ }
+
+ /// Return a platform which allows to check if a submodule name is active or inactive.
+ /// Use `defaults` for parsing the pathspecs used to later match on names via `submodule.active` configuration retrieved from `config`.
+ ///
+ /// All `submodule.active` pathspecs are considered to be top-level specs and match the name of submodules, which are active
+ /// on inclusive match.
+ /// The full algorithm is described as [hierarchy of rules](https://git-scm.com/docs/gitsubmodules#_active_submodules).
+ pub fn is_active_platform(
+ &self,
+ config: &gix_config::File<'_>,
+ defaults: gix_pathspec::Defaults,
+ ) -> Result<IsActivePlatform, crate::is_active_platform::Error> {
+ let search = config
+ .strings_by_key("submodule.active")
+ .map(|patterns| -> Result<_, crate::is_active_platform::Error> {
+ let patterns = patterns
+ .into_iter()
+ .map(|pattern| gix_pathspec::parse(&pattern, defaults))
+ .collect::<Result<Vec<_>, _>>()?;
+ Ok(gix_pathspec::Search::from_specs(
+ patterns,
+ None,
+ std::path::Path::new(""),
+ )?)
+ })
+ .transpose()?;
+ Ok(IsActivePlatform { search })
+ }
+
+ /// Given the `relative_path` (as seen from the root of the worktree) of a submodule with possibly platform-specific
+ /// component separators, find the submodule's name associated with this path, or `None` if none was found.
+ ///
+ /// Note that this does a linear search and compares `relative_path` in a normalized form to the same form of the path
+ /// associated with the submodule.
+ pub fn name_by_path(&self, relative_path: &BStr) -> Option<&BStr> {
+ self.names()
+ .filter_map(|n| self.path(n).ok().map(|p| (n, p)))
+ .find_map(|(n, p)| (p == relative_path).then_some(n))
+ }
+}
+
+/// Per-Submodule Access
+impl File {
+ /// Return the path relative to the root directory of the working tree at which the submodule is expected to be checked out.
+ /// It's an error if the path doesn't exist as it's the only way to associate a path in the index with additional submodule
+ /// information, like the URL to fetch from.
+ ///
+ /// ### Deviation
+ ///
+ /// Git currently allows absolute paths to be used when adding submodules, but fails later as it can't find the submodule by
+ /// relative path anymore. Let's play it safe here.
+ pub fn path(&self, name: &BStr) -> Result<Cow<'_, BStr>, config::path::Error> {
+ let path_bstr =
+ self.config
+ .string("submodule", Some(name), "path")
+ .ok_or_else(|| config::path::Error::Missing {
+ submodule: name.to_owned(),
+ })?;
+ if path_bstr.is_empty() {
+ return Err(config::path::Error::Missing {
+ submodule: name.to_owned(),
+ });
+ }
+ let path = gix_path::from_bstr(path_bstr.as_ref());
+ if path.is_absolute() {
+ return Err(config::path::Error::Absolute {
+ submodule: name.to_owned(),
+ actual: path_bstr.into_owned(),
+ });
+ }
+ if gix_path::normalize(path, "".as_ref()).is_none() {
+ return Err(config::path::Error::OutsideOfWorktree {
+ submodule: name.to_owned(),
+ actual: path_bstr.into_owned(),
+ });
+ }
+ Ok(path_bstr)
+ }
+
+ /// Retrieve the `url` field of the submodule named `name`. It's an error if it doesn't exist or is empty.
+ pub fn url(&self, name: &BStr) -> Result<gix_url::Url, config::url::Error> {
+ let url = self
+ .config
+ .string("submodule", Some(name), "url")
+ .ok_or_else(|| config::url::Error::Missing {
+ submodule: name.to_owned(),
+ })?;
+
+ if url.is_empty() {
+ return Err(config::url::Error::Missing {
+ submodule: name.to_owned(),
+ });
+ }
+ gix_url::Url::from_bytes(url.as_ref()).map_err(|err| config::url::Error::Parse {
+ submodule: name.to_owned(),
+ source: err,
+ })
+ }
+
+ /// Retrieve the `update` field of the submodule named `name`, if present.
+ pub fn update(&self, name: &BStr) -> Result<Option<Update>, config::update::Error> {
+ let value: Update = match self.config.string("submodule", Some(name), "update") {
+ Some(v) => v.as_ref().try_into().map_err(|()| config::update::Error::Invalid {
+ submodule: name.to_owned(),
+ actual: v.into_owned(),
+ })?,
+ None => return Ok(None),
+ };
+
+ if let Update::Command(cmd) = &value {
+ let ours = self.config.meta();
+ let has_value_from_foreign_section = self
+ .config
+ .sections_by_name("submodule")
+ .into_iter()
+ .flatten()
+ .any(|s| (s.header().subsection_name() == Some(name) && s.meta() as *const _ != ours as *const _));
+ if !has_value_from_foreign_section {
+ return Err(config::update::Error::CommandForbiddenInModulesConfiguration {
+ submodule: name.to_owned(),
+ actual: cmd.to_owned(),
+ });
+ }
+ }
+ Ok(Some(value))
+ }
+
+ /// Retrieve the `branch` field of the submodule named `name`, or `None` if unset.
+ ///
+ /// Note that `Default` is implemented for [`Branch`].
+ pub fn branch(&self, name: &BStr) -> Result<Option<Branch>, config::branch::Error> {
+ let branch = match self.config.string("submodule", Some(name), "branch") {
+ Some(v) => v,
+ None => return Ok(None),
+ };
+
+ Branch::try_from(branch.as_ref())
+ .map(Some)
+ .map_err(|err| config::branch::Error {
+ submodule: name.to_owned(),
+ actual: branch.into_owned(),
+ source: err,
+ })
+ }
+
+ /// Retrieve the `fetchRecurseSubmodules` field of the submodule named `name`, or `None` if unset.
+ ///
+ /// Note that if it's unset, it should be retrieved from `fetch.recurseSubmodules` in the configuration.
+ pub fn fetch_recurse(&self, name: &BStr) -> Result<Option<FetchRecurse>, config::Error> {
+ self.config
+ .boolean("submodule", Some(name), "fetchRecurseSubmodules")
+ .map(FetchRecurse::new)
+ .transpose()
+ .map_err(|value| config::Error {
+ field: "fetchRecurseSubmodules",
+ submodule: name.to_owned(),
+ actual: value,
+ })
+ }
+
+ /// Retrieve the `ignore` field of the submodule named `name`, or `None` if unset.
+ pub fn ignore(&self, name: &BStr) -> Result<Option<Ignore>, config::Error> {
+ self.config
+ .string("submodule", Some(name), "ignore")
+ .map(|value| {
+ Ignore::try_from(value.as_ref()).map_err(|()| config::Error {
+ field: "ignore",
+ submodule: name.to_owned(),
+ actual: value.into_owned(),
+ })
+ })
+ .transpose()
+ }
+
+ /// Retrieve the `shallow` field of the submodule named `name`, or `None` if unset.
+ ///
+ /// If `true`, the submodule will be checked out with `depth = 1`. If unset, `false` is assumed.
+ pub fn shallow(&self, name: &BStr) -> Result<Option<bool>, gix_config::value::Error> {
+ self.config.boolean("submodule", Some(name), "shallow").transpose()
+ }
+}
diff --git a/vendor/gix-submodule/src/config.rs b/vendor/gix-submodule/src/config.rs
new file mode 100644
index 000000000..202696691
--- /dev/null
+++ b/vendor/gix-submodule/src/config.rs
@@ -0,0 +1,216 @@
+use bstr::{BStr, BString, ByteSlice};
+
+/// Determine how the submodule participates in `git status` queries. This setting also affects `git diff`.
+#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub enum Ignore {
+ /// Submodule changes won't be considered at all, which is the fastest option.
+ ///
+ /// Note that changes to the submodule hash in the superproject will still be observable.
+ All,
+ /// Ignore any changes to the submodule working tree, only show committed differences between the `HEAD` of the submodule
+ /// compared to the recorded commit in the superproject.
+ Dirty,
+ /// Only ignore untracked files in the submodule, but show modifications to the submodule working tree as well as differences
+ /// between the recorded commit in the superproject and the checked-out commit in the submodule.
+ Untracked,
+ /// No modifications to the submodule are ignored, which shows untracked files, modified files in the submodule worktree as well as
+ /// differences between the recorded commit in the superproject and the checked-out commit in the submodule.
+ #[default]
+ None,
+}
+
+impl TryFrom<&BStr> for Ignore {
+ type Error = ();
+
+ fn try_from(value: &BStr) -> Result<Self, Self::Error> {
+ Ok(match value.as_bytes() {
+ b"all" => Ignore::All,
+ b"dirty" => Ignore::Dirty,
+ b"untracked" => Ignore::Untracked,
+ b"none" => Ignore::None,
+ _ => return Err(()),
+ })
+ }
+}
+
+/// Determine how to recurse into this module from the superproject when fetching.
+///
+/// Generally, a fetch is only performed if the submodule commit referenced by the superproject isn't already
+/// present in the submodule repository.
+///
+/// Note that when unspecified, the `fetch.recurseSubmodules` configuration variable should be used instead.
+#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub enum FetchRecurse {
+ /// Fetch only changed submodules.
+ #[default]
+ OnDemand,
+ /// Fetch all populated submodules, changed or not.
+ ///
+ /// This skips the work needed to determine whether a submodule has changed in the first place, but may work
+ /// more as some fetches might not be necessary.
+ Always,
+ /// Submodules are never fetched.
+ Never,
+}
+
+impl FetchRecurse {
+ /// Check if `boolean` is set and translate it the respective variant, or check the underlying string
+ /// value for non-boolean options.
+ /// On error, it returns the obtained string value which would be the invalid value.
+ pub fn new(boolean: Result<bool, gix_config::value::Error>) -> Result<Self, BString> {
+ Ok(match boolean {
+ Ok(value) => {
+ if value {
+ FetchRecurse::Always
+ } else {
+ FetchRecurse::Never
+ }
+ }
+ Err(err) => {
+ if err.input != "on-demand" {
+ return Err(err.input);
+ }
+ FetchRecurse::OnDemand
+ }
+ })
+ }
+}
+
+/// Describes the branch that should be tracked on the remote.
+#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
+pub enum Branch {
+ /// The name of the remote branch should be the same as the one currently checked out in the superproject.
+ CurrentInSuperproject,
+ /// The validated remote-only branch that could be used for fetching.
+ Name(BString),
+}
+
+impl Default for Branch {
+ fn default() -> Self {
+ Branch::Name("HEAD".into())
+ }
+}
+
+impl TryFrom<&BStr> for Branch {
+ type Error = gix_refspec::parse::Error;
+
+ fn try_from(value: &BStr) -> Result<Self, Self::Error> {
+ if value == "." {
+ return Ok(Branch::CurrentInSuperproject);
+ }
+
+ gix_refspec::parse(value, gix_refspec::parse::Operation::Fetch)
+ .map(|spec| Branch::Name(spec.source().expect("no object").to_owned()))
+ }
+}
+
+/// Determine how `git submodule update` should deal with this submodule to bring it up-to-date with the
+/// super-project's expectations.
+#[derive(Default, Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)]
+pub enum Update {
+ /// The commit recorded in the superproject should be checked out on a detached `HEAD`.
+ #[default]
+ Checkout,
+ /// The current branch in the submodule will be rebased onto the commit recorded in the superproject.
+ Rebase,
+ /// The commit recorded in the superproject will merged into the current branch of the submodule.
+ Merge,
+ /// A custom command to be called like `<command> hash-of-submodule-commit` that is to be executed to
+ /// perform the submodule update.
+ ///
+ /// Note that this variant is only allowed if the value is coming from an override. Thus it's not allowed to distribute
+ /// arbitrary commands via `.gitmodules` for security reasons.
+ Command(BString),
+ /// The submodule update is not performed at all.
+ None,
+}
+
+impl TryFrom<&BStr> for Update {
+ type Error = ();
+
+ fn try_from(value: &BStr) -> Result<Self, Self::Error> {
+ Ok(match value.as_bstr().as_bytes() {
+ b"checkout" => Update::Checkout,
+ b"rebase" => Update::Rebase,
+ b"merge" => Update::Merge,
+ b"none" => Update::None,
+ command if command.first() == Some(&b'!') => Update::Command(command[1..].to_owned().into()),
+ _ => return Err(()),
+ })
+ }
+}
+
+/// The error returned by [File::fetch_recurse()](crate::File::fetch_recurse) and [File::ignore()](crate::File::ignore).
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+#[error("The '{field}' field of submodule '{submodule}' was invalid: '{actual}'")]
+pub struct Error {
+ pub field: &'static str,
+ pub submodule: BString,
+ pub actual: BString,
+}
+
+///
+pub mod branch {
+ use bstr::BString;
+
+ /// The error returned by [File::branch()](crate::File::branch).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ #[error("The value '{actual}' of the 'branch' field of submodule '{submodule}' couldn't be turned into a valid fetch refspec")]
+ pub struct Error {
+ pub submodule: BString,
+ pub actual: BString,
+ pub source: gix_refspec::parse::Error,
+ }
+}
+
+///
+pub mod update {
+ use bstr::BString;
+
+ /// The error returned by [File::update()](crate::File::update).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("The 'update' field of submodule '{submodule}' tried to set command '{actual}' to be shared")]
+ CommandForbiddenInModulesConfiguration { submodule: BString, actual: BString },
+ #[error("The 'update' field of submodule '{submodule}' was invalid: '{actual}'")]
+ Invalid { submodule: BString, actual: BString },
+ }
+}
+
+///
+pub mod url {
+ use bstr::BString;
+
+ /// The error returned by [File::url()](crate::File::url).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("The url of submodule '{submodule}' could not be parsed")]
+ Parse {
+ submodule: BString,
+ source: gix_url::parse::Error,
+ },
+ #[error("The submodule '{submodule}' was missing its 'url' field or it was empty")]
+ Missing { submodule: BString },
+ }
+}
+
+///
+pub mod path {
+ use bstr::BString;
+
+ /// The error returned by [File::path()](crate::File::path).
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ pub enum Error {
+ #[error("The path '{actual}' of submodule '{submodule}' needs to be relative")]
+ Absolute { actual: BString, submodule: BString },
+ #[error("The submodule '{submodule}' was missing its 'path' field or it was empty")]
+ Missing { submodule: BString },
+ #[error("The path '{actual}' would lead outside of the repository worktree")]
+ OutsideOfWorktree { actual: BString, submodule: BString },
+ }
+}
diff --git a/vendor/gix-submodule/src/is_active_platform.rs b/vendor/gix-submodule/src/is_active_platform.rs
new file mode 100644
index 000000000..01d72f510
--- /dev/null
+++ b/vendor/gix-submodule/src/is_active_platform.rs
@@ -0,0 +1,49 @@
+use bstr::BStr;
+
+use crate::IsActivePlatform;
+
+/// The error returned by [File::names_and_active_state](crate::File::names_and_active_state()).
+#[derive(Debug, thiserror::Error)]
+#[allow(missing_docs)]
+pub enum Error {
+ #[error(transparent)]
+ NormalizePattern(#[from] gix_pathspec::normalize::Error),
+ #[error(transparent)]
+ ParsePattern(#[from] gix_pathspec::parse::Error),
+}
+
+impl IsActivePlatform {
+ /// Returns `true` if the submodule named `name` is active or `false` otherwise.
+ /// `config` is the configuration that was passed to the originating [modules file](crate::File).
+ /// `attributes(relative_path, case, is_dir, outcome)` provides a way to resolve the attributes mentioned
+ /// in `submodule.active` pathspecs that are evaluated in the platforms git configuration.
+ ///
+ /// A submodule's active state is determined in the following order
+ ///
+ /// * it's `submodule.<name>.active` is set in `config`
+ /// * it matches a `submodule.active` pathspec either positively or negatively via `:!<spec>`
+ /// * it's active if it has any `url` set in `config`
+ pub fn is_active(
+ &mut self,
+ config: &gix_config::File<'static>,
+ name: &BStr,
+ attributes: &mut dyn FnMut(
+ &BStr,
+ gix_pathspec::attributes::glob::pattern::Case,
+ bool,
+ &mut gix_pathspec::attributes::search::Outcome,
+ ) -> bool,
+ ) -> Result<bool, gix_config::value::Error> {
+ if let Some(val) = config.boolean("submodule", Some(name), "active").transpose()? {
+ return Ok(val);
+ };
+ if let Some(val) = self.search.as_mut().map(|search| {
+ search
+ .pattern_matching_relative_path(name, Some(true), attributes)
+ .map_or(false, |m| !m.is_excluded())
+ }) {
+ return Ok(val);
+ }
+ Ok(config.string("submodule", Some(name), "url").is_some())
+ }
+}
diff --git a/vendor/gix-submodule/src/lib.rs b/vendor/gix-submodule/src/lib.rs
new file mode 100644
index 000000000..639af30fa
--- /dev/null
+++ b/vendor/gix-submodule/src/lib.rs
@@ -0,0 +1,144 @@
+//! Primitives for describing git submodules.
+#![deny(rust_2018_idioms, missing_docs)]
+#![forbid(unsafe_code)]
+
+use std::{borrow::Cow, collections::BTreeMap};
+
+use bstr::BStr;
+
+/// All relevant information about a git module, typically from `.gitmodules` files.
+///
+/// Note that overrides from other configuration might be relevant, which is why this type
+/// can be used to take these into consideration when presented with other configuration
+/// from the superproject.
+#[derive(Clone)]
+pub struct File {
+ config: gix_config::File<'static>,
+}
+
+mod access;
+
+///
+pub mod config;
+
+///
+pub mod is_active_platform;
+
+/// A platform to keep the state necessary to perform repeated active checks, created by [File::is_active_platform()].
+pub struct IsActivePlatform {
+ pub(crate) search: Option<gix_pathspec::Search>,
+}
+
+/// Mutation
+impl File {
+ /// This can be used to let `config` override some values we know about submodules, namely…
+ ///
+ /// * `url`
+ /// * `fetchRecurseSubmodules`
+ /// * `ignore`
+ /// * `update`
+ /// * `branch`
+ ///
+ /// These values aren't validated yet, which will happen upon query.
+ pub fn append_submodule_overrides(&mut self, config: &gix_config::File<'_>) -> &mut Self {
+ let mut values = BTreeMap::<_, Vec<_>>::new();
+ for (module_name, section) in config
+ .sections_by_name("submodule")
+ .into_iter()
+ .flatten()
+ .filter_map(|s| s.header().subsection_name().map(|n| (n, s)))
+ {
+ for field in ["url", "fetchRecurseSubmodules", "ignore", "update", "branch"] {
+ if let Some(value) = section.value(field) {
+ values.entry((module_name, field)).or_default().push(value);
+ }
+ }
+ }
+
+ let values = {
+ let mut v: Vec<_> = values.into_iter().collect();
+ v.sort_by_key(|a| a.0 .0);
+ v
+ };
+
+ let mut config_to_append = gix_config::File::new(config.meta_owned());
+ let mut prev_name = None;
+ for ((module_name, field), values) in values {
+ if prev_name.map_or(true, |pn: &BStr| pn != module_name) {
+ config_to_append
+ .new_section("submodule", Some(Cow::Owned(module_name.to_owned())))
+ .expect("all names come from valid configuration, so remain valid");
+ prev_name = Some(module_name);
+ }
+ config_to_append
+ .section_mut("submodule", Some(module_name))
+ .expect("always set at this point")
+ .push(
+ field.try_into().expect("statically known key"),
+ Some(values.last().expect("at least one value or we wouldn't be here")),
+ );
+ }
+
+ self.config.append(config_to_append);
+ self
+ }
+}
+
+///
+mod init {
+ use std::path::PathBuf;
+
+ use crate::File;
+
+ impl std::fmt::Debug for File {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("File")
+ .field("config_path", &self.config_path())
+ .field("config", &format_args!("r#\"{}\"#", self.config))
+ .finish()
+ }
+ }
+
+ /// A marker we use when listing names to not pick them up from overridden sections.
+ pub(crate) const META_MARKER: gix_config::Source = gix_config::Source::Api;
+
+ /// Lifecycle
+ impl File {
+ /// Parse `bytes` as git configuration, typically from `.gitmodules`, without doing any further validation.
+ /// `path` can be provided to keep track of where the file was read from in the underlying [`config`](Self::config())
+ /// instance.
+ /// `config` is used to [apply value overrides](File::append_submodule_overrides), which can be empty if overrides
+ /// should be applied at a later time.
+ ///
+ /// Future access to the module information is lazy and configuration errors are exposed there on a per-value basis.
+ ///
+ /// ### Security Considerations
+ ///
+ /// The information itself should be used with care as it can direct the caller to fetch from remotes. It is, however,
+ /// on the caller to assure the input data can be trusted.
+ pub fn from_bytes(
+ bytes: &[u8],
+ path: impl Into<Option<PathBuf>>,
+ config: &gix_config::File<'_>,
+ ) -> Result<Self, gix_config::parse::Error> {
+ let metadata = {
+ let mut meta = gix_config::file::Metadata::from(META_MARKER);
+ meta.path = path.into();
+ meta
+ };
+ let modules = gix_config::File::from_parse_events_no_includes(
+ gix_config::parse::Events::from_bytes_owned(bytes, None)?,
+ metadata,
+ );
+
+ let mut res = Self { config: modules };
+ res.append_submodule_overrides(config);
+ Ok(res)
+ }
+
+ /// Turn ourselves into the underlying parsed configuration file.
+ pub fn into_config(self) -> gix_config::File<'static> {
+ self.config
+ }
+ }
+}
diff --git a/vendor/gix-submodule/tests/file/baseline.rs b/vendor/gix-submodule/tests/file/baseline.rs
new file mode 100644
index 000000000..dc71ed3ab
--- /dev/null
+++ b/vendor/gix-submodule/tests/file/baseline.rs
@@ -0,0 +1,80 @@
+use std::{ffi::OsStr, path::PathBuf};
+
+use bstr::ByteSlice;
+use gix_features::fs::walkdir::Parallelism;
+
+#[test]
+fn common_values_and_names_by_path() -> crate::Result {
+ let modules = module_files()
+ .map(|(path, stripped)| {
+ gix_submodule::File::from_bytes(&std::fs::read(path).unwrap(), stripped, &Default::default())
+ })
+ .collect::<Result<Vec<_>, _>>()?;
+
+ assert_eq!(
+ modules
+ .iter()
+ .map(|m| { m.config_path().expect("present").to_owned() })
+ .collect::<Vec<_>>(),
+ [
+ "empty-clone/.gitmodules",
+ "multiple/.gitmodules",
+ "not-a-submodule/.gitmodules",
+ "recursive-clone/.gitmodules",
+ "recursive-clone/submodule/.gitmodules",
+ "relative-clone/.gitmodules",
+ "relative-clone/submodule/.gitmodules",
+ "super/.gitmodules",
+ "super/submodule/.gitmodules",
+ "super-clone/.gitmodules",
+ "super-clone/submodule/.gitmodules",
+ "top-only-clone/.gitmodules"
+ ]
+ .into_iter()
+ .map(PathBuf::from)
+ .collect::<Vec<_>>(),
+ "config_path() yields the path provided when instantiating (for .gitmodules), and not the path of a submodule."
+ );
+
+ assert_eq!(
+ {
+ let mut v = modules.iter().flat_map(gix_submodule::File::names).collect::<Vec<_>>();
+ v.sort();
+ v.dedup();
+ v
+ },
+ [".a/..c", "a/b", "a/d\\", "a\\e", "submodule"]
+ .into_iter()
+ .map(|n| n.as_bytes().as_bstr())
+ .collect::<Vec<_>>(),
+ "names can be iterated"
+ );
+
+ for module in &modules {
+ for name in module.names() {
+ let path = module.path(name)?;
+ assert_eq!(module.name_by_path(path.as_ref()).expect("found"), name);
+ }
+ }
+ Ok(())
+}
+
+fn module_files() -> impl Iterator<Item = (PathBuf, PathBuf)> {
+ let dir = gix_testtools::scripted_fixture_read_only("basic.sh").expect("valid fixture");
+ gix_features::fs::walkdir_sorted_new(&dir, Parallelism::Serial)
+ .follow_links(false)
+ .into_iter()
+ .filter_map(move |entry| {
+ let entry = entry.unwrap();
+ (entry.file_name() == OsStr::new(".gitmodules")).then(|| {
+ (
+ entry.path().to_owned(),
+ entry
+ .path()
+ .strip_prefix(&dir)
+ .expect("can only provide sub-dirs")
+ .to_owned(),
+ )
+ })
+ })
+}
diff --git a/vendor/gix-submodule/tests/file/mod.rs b/vendor/gix-submodule/tests/file/mod.rs
new file mode 100644
index 000000000..cecb7b759
--- /dev/null
+++ b/vendor/gix-submodule/tests/file/mod.rs
@@ -0,0 +1,453 @@
+fn submodule(bytes: &str) -> gix_submodule::File {
+ gix_submodule::File::from_bytes(bytes.as_bytes(), None, &Default::default()).expect("valid module")
+}
+
+mod is_active_platform {
+ use std::str::FromStr;
+
+ fn module_file(name: &str) -> crate::Result<gix_submodule::File> {
+ let modules = gix_testtools::scripted_fixture_read_only("basic.sh")?
+ .join(name)
+ .join(".gitmodules");
+ Ok(gix_submodule::File::from_bytes(
+ std::fs::read(&modules)?.as_slice(),
+ modules,
+ &Default::default(),
+ )?)
+ }
+
+ use bstr::{BStr, ByteSlice};
+
+ fn multi_modules() -> crate::Result<gix_submodule::File> {
+ module_file("multiple")
+ }
+
+ fn assume_valid_active_state<'a>(
+ module: &'a gix_submodule::File,
+ config: &'a gix_config::File<'static>,
+ defaults: gix_pathspec::Defaults,
+ ) -> crate::Result<Vec<(&'a str, bool)>> {
+ assume_valid_active_state_with_attrs(module, config, defaults, |_, _, _, _| {
+ unreachable!("shouldn't be called")
+ })
+ }
+
+ fn assume_valid_active_state_with_attrs<'a>(
+ module: &'a gix_submodule::File,
+ config: &'a gix_config::File<'static>,
+ defaults: gix_pathspec::Defaults,
+ mut attributes: impl FnMut(
+ &BStr,
+ gix_pathspec::attributes::glob::pattern::Case,
+ bool,
+ &mut gix_pathspec::attributes::search::Outcome,
+ ) -> bool
+ + 'a,
+ ) -> crate::Result<Vec<(&'a str, bool)>> {
+ let mut platform = module.is_active_platform(config, defaults)?;
+ Ok(module
+ .names()
+ .map(|name| {
+ (
+ name.to_str().expect("valid"),
+ platform.is_active(config, name, &mut attributes).expect("valid"),
+ )
+ })
+ .collect())
+ }
+
+ #[test]
+ fn without_submodule_in_index() -> crate::Result {
+ let module = module_file("not-a-submodule")?;
+ assert_eq!(
+ module.names().map(ToOwned::to_owned).collect::<Vec<_>>(),
+ ["submodule"],
+ "entries can be read"
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn without_any_additional_settings_all_are_inactive_if_they_have_a_url() -> crate::Result {
+ let module = multi_modules()?;
+ assert_eq!(
+ assume_valid_active_state(&module, &Default::default(), Default::default())?,
+ &[
+ ("submodule", false),
+ ("a/b", false),
+ (".a/..c", false),
+ ("a/d\\", false),
+ ("a\\e", false)
+ ]
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn submodules_with_active_config_are_considered_active_or_inactive() -> crate::Result {
+ let module = multi_modules()?;
+ assert_eq!(
+ assume_valid_active_state(
+ &module,
+ &gix_config::File::from_str(
+ "[submodule.submodule]\n active = 0\n url = set \n[submodule \"a/b\"]\n active = false \n url = set \n[submodule \".a/..c\"] active = 1"
+ )?,
+ Default::default()
+ )?,
+ &[
+ ("submodule", false),
+ ("a/b", false),
+ (".a/..c", true),
+ ("a/d\\", false),
+ ("a\\e", false)
+ ]
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn submodules_with_active_config_override_pathspecs() -> crate::Result {
+ let module = multi_modules()?;
+ assert_eq!(
+ assume_valid_active_state(
+ &module,
+ &gix_config::File::from_str(
+ "[submodule.submodule]\n active = 0\n[submodule]\n active = *\n[submodule]\n active = :!a*"
+ )?,
+ Default::default()
+ )?,
+ &[
+ ("submodule", false),
+ ("a/b", false),
+ (".a/..c", true),
+ ("a/d\\", false),
+ ("a\\e", false)
+ ]
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn pathspecs_matter_even_if_they_do_not_match() -> crate::Result {
+ let module = multi_modules()?;
+ assert_eq!(
+ assume_valid_active_state(
+ &module,
+ &gix_config::File::from_str("[submodule]\n active = submodule ")?,
+ Default::default()
+ )?,
+ &[
+ ("submodule", true),
+ ("a/b", false),
+ (".a/..c", false),
+ ("a/d\\", false),
+ ("a\\e", false)
+ ]
+ );
+ assert_eq!(
+ assume_valid_active_state(
+ &module,
+ &gix_config::File::from_str("[submodule]\n active = :!submodule ")?,
+ Default::default()
+ )?,
+ &[
+ ("submodule", false),
+ ("a/b", true),
+ (".a/..c", true),
+ ("a/d\\", true),
+ ("a\\e", true)
+ ]
+ );
+ Ok(())
+ }
+}
+
+mod path {
+ use gix_submodule::config::path::Error;
+
+ use crate::file::submodule;
+
+ fn submodule_path(value: &str) -> Error {
+ let module = submodule(&format!("[submodule.a]\npath = {value}"));
+ module.path("a".into()).unwrap_err()
+ }
+
+ #[test]
+ fn valid() -> crate::Result {
+ let module = submodule("[submodule.a]\n path = relative/path/submodule");
+ assert_eq!(module.path("a".into())?.as_ref(), "relative/path/submodule");
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() {
+ assert!(matches!(
+ submodule_path(if cfg!(windows) {
+ "c:\\\\hello"
+ } else {
+ "/definitely/absolute\\\\"
+ }),
+ Error::Absolute { .. }
+ ));
+ assert!(matches!(submodule_path(""), Error::Missing { .. }));
+ assert!(matches!(submodule_path("../attack"), Error::OutsideOfWorktree { .. }));
+
+ {
+ let module = submodule("[submodule.a]\n path");
+ assert!(matches!(module.path("a".into()).unwrap_err(), Error::Missing { .. }));
+ }
+
+ {
+ let module = submodule("[submodule.a]\n");
+ assert!(matches!(module.path("a".into()).unwrap_err(), Error::Missing { .. }));
+ }
+ }
+}
+
+mod url {
+ use gix_submodule::config::url::Error;
+
+ use crate::file::submodule;
+
+ fn submodule_url(value: &str) -> Error {
+ let module = submodule(&format!("[submodule.a]\nurl = {value}"));
+ module.url("a".into()).unwrap_err()
+ }
+
+ #[test]
+ fn valid() -> crate::Result {
+ let module = submodule("[submodule.a]\n url = path-to-repo");
+ assert_eq!(module.url("a".into())?.to_bstring(), "path-to-repo");
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() {
+ assert!(matches!(submodule_url(""), Error::Missing { .. }));
+ {
+ let module = submodule("[submodule.a]\n url");
+ assert!(matches!(module.url("a".into()).unwrap_err(), Error::Missing { .. }));
+ }
+
+ {
+ let module = submodule("[submodule.a]\n");
+ assert!(matches!(module.url("a".into()).unwrap_err(), Error::Missing { .. }));
+ }
+
+ assert!(matches!(submodule_url("file://"), Error::Parse { .. }));
+ }
+}
+
+mod update {
+ use std::str::FromStr;
+
+ use gix_submodule::config::{update::Error, Update};
+
+ use crate::file::submodule;
+
+ fn submodule_update(value: &str) -> Error {
+ let module = submodule(&format!("[submodule.a]\nupdate = {value}"));
+ module.update("a".into()).unwrap_err()
+ }
+
+ #[test]
+ fn default() {
+ assert_eq!(Update::default(), Update::Checkout, "as defined in the docs");
+ }
+
+ #[test]
+ fn valid() -> crate::Result {
+ for (valid, expected) in [
+ ("checkout", Update::Checkout),
+ ("rebase", Update::Rebase),
+ ("merge", Update::Merge),
+ ("none", Update::None),
+ ] {
+ let module = submodule(&format!("[submodule.a]\n update = {valid}"));
+ assert_eq!(module.update("a".into())?.expect("present"), expected);
+ }
+ Ok(())
+ }
+
+ #[test]
+ fn valid_in_overrides() -> crate::Result {
+ let mut module = submodule("[submodule.a]\n update = merge");
+ let repo_config = gix_config::File::from_str("[submodule.a]\n update = !dangerous")?;
+ let prev_names = module.names().map(ToOwned::to_owned).collect::<Vec<_>>();
+ module.append_submodule_overrides(&repo_config);
+
+ assert_eq!(
+ module.update("a".into())?.expect("present"),
+ Update::Command("dangerous".into()),
+ "overridden values are picked up and make commands possible - these are local"
+ );
+ assert_eq!(
+ module.names().map(ToOwned::to_owned).collect::<Vec<_>>(),
+ prev_names,
+ "Appending more configuration sections doesn't affect name listing"
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() {
+ assert!(matches!(submodule_update(""), Error::Invalid { .. }));
+ assert!(matches!(submodule_update("bogus"), Error::Invalid { .. }));
+ assert!(
+ matches!(
+ submodule_update("!dangerous"),
+ Error::CommandForbiddenInModulesConfiguration { .. }
+ ),
+ "forbidden unless it's an override"
+ );
+ }
+}
+
+mod fetch_recurse {
+ use gix_submodule::config::FetchRecurse;
+
+ use crate::file::submodule;
+
+ #[test]
+ fn default() {
+ assert_eq!(
+ FetchRecurse::default(),
+ FetchRecurse::OnDemand,
+ "as defined in git codebase actually"
+ );
+ }
+
+ #[test]
+ fn valid() -> crate::Result {
+ for (valid, expected) in [
+ ("yes", FetchRecurse::Always),
+ ("true", FetchRecurse::Always),
+ ("", FetchRecurse::Never),
+ ("no", FetchRecurse::Never),
+ ("false", FetchRecurse::Never),
+ ("on-demand", FetchRecurse::OnDemand),
+ ] {
+ let module = submodule(&format!("[submodule.a]\n fetchRecurseSubmodules = {valid}"));
+ assert_eq!(module.fetch_recurse("a".into())?.expect("present"), expected);
+ }
+ let module = submodule("[submodule.a]\n fetchRecurseSubmodules");
+ assert_eq!(
+ module.fetch_recurse("a".into())?.expect("present"),
+ FetchRecurse::Always,
+ "no value means true, which means to always recurse"
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() -> crate::Result {
+ for invalid in ["foo", "ney", "On-demand"] {
+ let module = submodule(&format!("[submodule.a]\n fetchRecurseSubmodules = \"{invalid}\""));
+ assert!(module.fetch_recurse("a".into()).is_err());
+ }
+ Ok(())
+ }
+}
+
+mod ignore {
+ use gix_submodule::config::Ignore;
+
+ use crate::file::submodule;
+
+ #[test]
+ fn default() {
+ assert_eq!(Ignore::default(), Ignore::None, "as defined in the docs");
+ }
+
+ #[test]
+ fn valid() -> crate::Result {
+ for (valid, expected) in [
+ ("all", Ignore::All),
+ ("dirty", Ignore::Dirty),
+ ("untracked", Ignore::Untracked),
+ ("none", Ignore::None),
+ ] {
+ let module = submodule(&format!("[submodule.a]\n ignore = {valid}"));
+ assert_eq!(module.ignore("a".into())?.expect("present"), expected);
+ }
+ let module = submodule("[submodule.a]\n ignore");
+ assert!(
+ module.ignore("a".into())?.is_none(),
+ "no value is interpreted as non-existing string, hence the caller will see None"
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() -> crate::Result {
+ for invalid in ["All", ""] {
+ let module = submodule(&format!("[submodule.a]\n ignore = \"{invalid}\""));
+ assert!(module.ignore("a".into()).is_err());
+ }
+ Ok(())
+ }
+}
+
+mod branch {
+ use gix_submodule::config::Branch;
+
+ use crate::file::submodule;
+
+ #[test]
+ fn valid() -> crate::Result {
+ for (valid, expected) in [
+ (".", Branch::CurrentInSuperproject),
+ ("", Branch::Name("HEAD".into())),
+ ("master", Branch::Name("master".into())),
+ ("feature/a", Branch::Name("feature/a".into())),
+ (
+ "abcde12345abcde12345abcde12345abcde12345",
+ Branch::Name("abcde12345abcde12345abcde12345abcde12345".into()),
+ ),
+ ] {
+ let module = submodule(&format!("[submodule.a]\n branch = {valid}"));
+ assert_eq!(module.branch("a".into())?.expect("present"), expected);
+ }
+ let module = submodule("[submodule.a]\n branch");
+ assert!(
+ module.branch("a".into())?.is_none(),
+ "no value implies it's not set, but the caller will then default"
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn validate_upon_retrieval() -> crate::Result {
+ let module = submodule("[submodule.a]\n branch = /invalid");
+ assert!(module.branch("a".into()).is_err());
+ Ok(())
+ }
+}
+
+#[test]
+fn shallow() -> crate::Result {
+ let module = submodule("[submodule.a]\n shallow");
+ assert_eq!(
+ module.shallow("a".into())?,
+ Some(true),
+ "shallow is a simple boolean without anything special (yet)"
+ );
+ Ok(())
+}
+
+mod append_submodule_overrides {
+ use std::str::FromStr;
+
+ use crate::file::submodule;
+
+ #[test]
+ fn last_of_multiple_values_wins() -> crate::Result {
+ let mut module = submodule("[submodule.a] url = from-module");
+ let repo_config =
+ gix_config::File::from_str("[submodule.a]\n url = a\n url = b\n ignore = x\n [submodule.a]\n url = c\n[submodule.b] url = not-relevant")?;
+ module.append_submodule_overrides(&repo_config);
+ Ok(())
+ }
+}
+
+mod baseline;
diff --git a/vendor/gix-submodule/tests/fixtures/basic.sh b/vendor/gix-submodule/tests/fixtures/basic.sh
new file mode 100755
index 000000000..203e6afde
--- /dev/null
+++ b/vendor/gix-submodule/tests/fixtures/basic.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+set -eu -o pipefail
+
+set -x
+git init
+touch empty && git add empty
+git commit -m upstream
+git clone . super
+git clone super multiple
+(cd multiple
+ git submodule add ../multiple submodule
+ git submodule add ../multiple a/b
+ git submodule add --name .a/..c ../multiple a\\c
+ git submodule add --name a/d\\ ../multiple a/d\\
+ git submodule add --name a\\e ../multiple a/e/
+ git commit -m "subsubmodule-a"
+)
+
+(cd super
+ git submodule add ../multiple submodule
+ git commit -m "submodule"
+)
+git clone super super-clone
+(cd super-clone
+ git submodule update --init --recursive
+)
+git clone super empty-clone
+(cd empty-clone
+ git submodule init
+)
+git clone super top-only-clone
+git clone super relative-clone
+(cd relative-clone
+ git submodule update --init --recursive
+)
+git clone super recursive-clone
+(cd recursive-clone
+ git submodule update --init --recursive
+)
+
+git clone super not-a-submodule
+(cd not-a-submodule
+ cp .gitmodules modules.bak
+ git rm submodule
+ echo fake > submodule
+ mv modules.bak .gitmodules
+ git add submodule && git commit -m "no submodule in index and commit, but in configuration"
+)
diff --git a/vendor/gix-submodule/tests/fixtures/generated-archives/basic.tar.xz b/vendor/gix-submodule/tests/fixtures/generated-archives/basic.tar.xz
new file mode 100644
index 000000000..d483db5e7
--- /dev/null
+++ b/vendor/gix-submodule/tests/fixtures/generated-archives/basic.tar.xz
Binary files differ
diff --git a/vendor/gix-submodule/tests/submodule.rs b/vendor/gix-submodule/tests/submodule.rs
new file mode 100644
index 000000000..75144b10c
--- /dev/null
+++ b/vendor/gix-submodule/tests/submodule.rs
@@ -0,0 +1,3 @@
+use gix_testtools::Result;
+
+mod file;