Sebastian Thielmake fmt47724c04 years agoHistory
324 lines · 8.7 KB · Rust
RawDownload
use std::fs; use git_config::{    file::{includes, init, init::from_paths},    File,};use tempfile::tempdir; use crate::file::{    cow_str,    init::from_paths::{escape_backslashes, into_meta},}; fn follow_options() -> init::Options<'static> {    init::Options {        includes: includes::Options::follow(Default::default(), Default::default()),        ..Default::default()    }} #[test]fn multiple() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    fs::write(        a_path.as_path(),        "[core]  a = false  sslVerify = true  d = 41",    )?;     let b_path = dir.path().join("b");    let relative_b_path: std::path::PathBuf = "b".into();    fs::write(        b_path.as_path(),        "[diff]  renames = true",    )?;    let ignore_path = dir.path().join("ignore");    fs::write(        ignore_path.as_path(),        "[diff]  renames = invalid",    )?;     let a_path_string = escape_backslashes(a_path.parent().unwrap());    let non_canonical_path_a = format!("{}/./a", a_path_string);    let non_existing_path = "/dfgwfsghfdsfs";    let c_path = dir.path().join("c");    fs::write(        c_path.as_path(),        format!(            "[core]  c = 12  d = 42[include]  path = {}  path = {}  path = {}[include.ignore]  path = {}[http]  sslVerify = false",            non_existing_path,            non_canonical_path_a,            relative_b_path.as_path().to_str().unwrap(),            escape_backslashes(&ignore_path)        ),    )?;     let config = File::from_paths_metadata(into_meta(vec![c_path]), follow_options())?.expect("non-empty");     assert_eq!(config.string("core", None, "c"), Some(cow_str("12")));    assert_eq!(config.integer("core", None, "d"), Some(Ok(41)));    assert_eq!(config.boolean("http", None, "sslVerify"), Some(Ok(false)));    assert_eq!(config.boolean("diff", None, "renames"), Some(Ok(true)));    assert_eq!(config.boolean("core", None, "a"), Some(Ok(false)));     Ok(())} #[test]fn respect_max_depth() -> crate::Result {    let dir = tempdir()?;     // 0 includes 1 - base level    // 1 includes 2    // 2 includes 3    // 3 includes 4    // 4 has no includes    let max_depth = 4u8;    for (i, next_i) in (0..max_depth).zip(1..=max_depth) {        let path = dir.path().join(i.to_string());        let next_path = dir.path().join(next_i.to_string());        fs::write(            path.as_path(),            format!(                "        [core]          i = {i}         [include]          path = {}",                escape_backslashes(&next_path),            ),        )?;    }     fs::write(        dir.path().join(max_depth.to_string()),        "        [core]          i = {}"            .replace("{}", &max_depth.to_string()),    )?;     let config =        File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), follow_options())?.expect("non-empty");    assert_eq!(config.integers("core", None, "i"), Some(Ok(vec![0, 1, 2, 3, 4])));     fn make_options(max_depth: u8, error_on_max_depth_exceeded: bool) -> init::Options<'static> {        init::Options {            includes: includes::Options {                max_depth,                err_on_max_depth_exceeded: error_on_max_depth_exceeded,                ..Default::default()            },            ..Default::default()        }    }     // with max_allowed_depth of 1 and 4 levels of includes and error_on_max_depth_exceeded: false, max_allowed_depth is exceeded and the value of level 1 is returned    // this is equivalent to running git with --no-includes option    let options = make_options(1, false);    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options)?.expect("non-empty");    assert_eq!(config.integer("core", None, "i"), Some(Ok(1)));     // with default max_allowed_depth of 10 and 4 levels of includes, last level is read    let options = init::Options {        includes: includes::Options::follow(Default::default(), Default::default()),        ..Default::default()    };    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options)?.expect("non-empty");    assert_eq!(config.integer("core", None, "i"), Some(Ok(4)));     // with max_allowed_depth of 5, the base and 4 levels of includes, last level is read    let options = make_options(5, false);    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options)?.expect("non-empty");    assert_eq!(config.integer("core", None, "i"), Some(Ok(4)));     // with max_allowed_depth of 2 and 4 levels of includes, max_allowed_depth is exceeded and error is returned    let options = make_options(2, true);    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options);    assert!(matches!(        config.unwrap_err(),        from_paths::Error::Init(init::Error::Includes(includes::Error::IncludeDepthExceeded {            max_depth: 2        }))    ));     // with max_allowed_depth of 2 and 4 levels of includes and error_on_max_depth_exceeded: false , max_allowed_depth is exceeded and the value of level 2 is returned    let options = make_options(2, false);    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options)?.expect("non-empty");    assert_eq!(config.integer("core", None, "i"), Some(Ok(2)));     // with max_allowed_depth of 0 and 4 levels of includes, max_allowed_depth is exceeded and error is returned    let options = make_options(0, true);    let config = File::from_paths_metadata(into_meta(vec![dir.path().join("0")]), options);    assert!(matches!(        config.unwrap_err(),        from_paths::Error::Init(init::Error::Includes(includes::Error::IncludeDepthExceeded {            max_depth: 0        }))    ));    Ok(())} #[test]fn simple() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    let b_path = dir.path().join("b");     fs::write(        a_path.as_path(),        format!(            "[core]  b = true[include]  path = {}[core]  b = true[include]  path = {}",            escape_backslashes(&b_path),            escape_backslashes(&b_path)        ),    )?;     fs::write(        b_path.as_path(),        "[core]  b = false",    )?;     let config = File::from_paths_metadata(into_meta(vec![a_path]), follow_options())?.expect("non-empty");    assert_eq!(config.boolean("core", None, "b"), Some(Ok(false)));    Ok(())} #[test]fn cycle_detection() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    let b_path = dir.path().join("b");     fs::write(        a_path.as_path(),        format!(            "[core]  b = 0[include]  path = {}",            escape_backslashes(&b_path),        ),    )?;     fs::write(        b_path.as_path(),        format!(            "[core]  b = 1[include]  path = {}",            escape_backslashes(&a_path),        ),    )?;     let options = init::Options {        includes: includes::Options {            max_depth: 4,            err_on_max_depth_exceeded: true,            ..Default::default()        },        ..Default::default()    };    let config = File::from_paths_metadata(into_meta(vec![a_path.clone()]), options);    assert!(matches!(        config.unwrap_err(),        from_paths::Error::Init(init::Error::Includes(includes::Error::IncludeDepthExceeded {            max_depth: 4        }))    ));     let options = init::Options {        includes: includes::Options {            max_depth: 4,            err_on_max_depth_exceeded: false,            ..Default::default()        },        ..Default::default()    };    let config = File::from_paths_metadata(into_meta(vec![a_path]), options)?.expect("non-empty");    assert_eq!(config.integers("core", None, "b"), Some(Ok(vec![0, 1, 0, 1, 0])));    Ok(())} #[test]fn nested() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    fs::write(        a_path.as_path(),        "[core]  a = false  c = 1",    )?;     let b_path = dir.path().join("b");    fs::write(        b_path.as_path(),        format!(            "[core]  b = true[include]  path = {}",            escape_backslashes(&a_path)        ),    )?;     let c_path = dir.path().join("c");    fs::write(        c_path.as_path(),        format!(            "[core]  c = 12[include]  path = {}",            escape_backslashes(&b_path)        ),    )?;     let config = File::from_paths_metadata(into_meta(vec![c_path]), follow_options())?.expect("non-empty");     assert_eq!(config.integer("core", None, "c"), Some(Ok(1)));    assert_eq!(config.boolean("core", None, "b"), Some(Ok(true)));    assert_eq!(config.boolean("core", None, "a"), Some(Ok(false)));    Ok(())}