summaryrefslogtreecommitdiffstats
path: root/vendor/gix-submodule/tests/file/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-submodule/tests/file/mod.rs')
-rw-r--r--vendor/gix-submodule/tests/file/mod.rs453
1 files changed, 453 insertions, 0 deletions
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;