Sebastian Thielmake fmt47724c04 years agoHistory
197 lines · 6.2 KB · Rust
RawDownload
use std::{fs, path::PathBuf}; use git_config::{File, Source};use tempfile::tempdir; use crate::file::cow_str; /// Escapes backslash when writing a path as string so that it is a valid windows pathpub(crate) fn escape_backslashes(path: impl AsRef<std::path::Path>) -> String {    path.as_ref().to_str().unwrap().replace('\\', "\\\\")} mod from_path_no_includes {    #[test]    fn file_not_found() {        let dir = tempfile::tempdir().unwrap();        let config_path = dir.path().join("config");         let err = git_config::File::from_path_no_includes(config_path, git_config::Source::Local).unwrap_err();        assert!(            matches!(err,  git_config::file::init::from_paths::Error::Io(io_error) if io_error.kind() == std::io::ErrorKind::NotFound)        );    }     #[test]    fn single_path() {        let dir = tempfile::tempdir().unwrap();        let config_path = dir.path().join("config");        std::fs::write(config_path.as_path(), b"[core]\nboolean = true").unwrap();         let config = git_config::File::from_path_no_includes(config_path, git_config::Source::Local).unwrap();         assert_eq!(config.raw_value("core", None, "boolean").unwrap().as_ref(), "true");        assert_eq!(config.num_values(), 1);    }} #[test]fn multiple_paths_single_value() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    fs::write(a_path.as_path(), b"[core]\na = true")?;     let b_path = dir.path().join("b");    fs::write(b_path.as_path(), b"[core]\nb = true")?;     let c_path = dir.path().join("c");    fs::write(c_path.as_path(), b"[core]\nc = true")?;     let d_path = dir.path().join("d");    fs::write(d_path.as_path(), b"[core]\na = false")?;     let paths = vec![a_path, b_path, c_path, d_path];    let config = File::from_paths_metadata(into_meta(paths), Default::default())?.expect("non-empty");     assert_eq!(config.boolean("core", None, "a"), Some(Ok(false)));    assert_eq!(config.boolean("core", None, "b"), Some(Ok(true)));    assert_eq!(config.boolean("core", None, "c"), Some(Ok(true)));    assert_eq!(config.num_values(), 4);    assert_eq!(config.sections().count(), 4, "each value is in a dedicated section");     Ok(())} #[test]fn frontmatter_is_maintained_in_multiple_files() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    fs::write(a_path.as_path(), b";before a\n[core]\na = true")?;     let b_path = dir.path().join("b");    fs::write(b_path.as_path(), b";before b\n [core]\nb = true")?;     let c_path = dir.path().join("c");    fs::write(c_path.as_path(), b"# nothing in c")?;     let d_path = dir.path().join("d");    fs::write(d_path.as_path(), b"\n; nothing in d")?;     let paths = vec![a_path, b_path, c_path, d_path];    let mut config = File::from_paths_metadata(into_meta(paths), Default::default())?.expect("non-empty");     assert_eq!(        config.to_string(),        ";before a\n[core]\na = true\n;before b\n [core]\nb = true\n# nothing in c\n; nothing in d\n"    );     config.append(config.clone());    assert_eq!(        config.to_string(),        ";before a\n[core]\na = true\n;before b\n [core]\nb = true\n# nothing in c\n; nothing in d\n;before a\n[core]\na = true\n;before b\n [core]\nb = true\n# nothing in c\n; nothing in d\n",        "other files post-section matter works as well, adding newlines as needed"    );     assert_eq!(        config            .frontmatter()            .expect("present")            .map(|e| e.to_string())            .collect::<Vec<_>>()            .join(""),        ";before a\n"    );     assert_eq!(        config.sections_and_postmatter().count(),        4,        "we trust rust here and don't validate it's actually what we think it is"    );    Ok(())} #[test]fn multiple_paths_multi_value_and_filter() -> crate::Result {    let dir = tempdir()?;     let a_path = dir.path().join("a");    fs::write(a_path.as_path(), b"[core]\nkey = a")?;     let b_path = dir.path().join("b");    fs::write(b_path.as_path(), b"[core]\nkey = b")?;     let c_path = dir.path().join("c");    fs::write(c_path.as_path(), b"[core]\nkey = c")?;     let d_path = dir.path().join("d");    fs::write(d_path.as_path(), b"[include]\npath = d_path")?;     let e_path = dir.path().join("e");    fs::write(e_path.as_path(), b"[include]\npath = e_path")?;     let paths_and_source = vec![        (a_path, Source::System),        (b_path, Source::Git),        (c_path, Source::User),        (d_path, Source::Worktree),        (e_path, Source::Local),    ];     let config = File::from_paths_metadata(        paths_and_source            .iter()            .map(|(p, s)| git_config::file::Metadata::try_from_path(p, *s).unwrap()),        Default::default(),    )?    .expect("non-empty");     assert_eq!(        config.strings("core", None, "key"),        Some(vec![cow_str("a"), cow_str("b"), cow_str("c"),])    );     assert_eq!(        config.string_filter("core", None, "key", &mut |m| m.source == Source::System),        Some(cow_str("a")),        "the filter discards all values with higher priority"    );     assert_eq!(        config.strings_filter("core", None, "key", &mut |m| m.source == Source::Git            || m.source == Source::User),        Some(vec![cow_str("b"), cow_str("c")])    );     assert_eq!(        config.strings("include", None, "path"),        Some(vec![cow_str("d_path"), cow_str("e_path")])    );     assert_eq!(config.num_values(), 5);    assert_eq!(        config            .sections()            .map(|s| (                s.meta().path.as_ref().expect("each section has file source").to_owned(),                s.meta().source,                s.meta().level            ))            .collect::<Vec<_>>(),        paths_and_source.into_iter().map(|(p, s)| (p, s, 0)).collect::<Vec<_>>(),        "sections are added in order and their path and sources are set as given, levels are 0 for the non-included ones"    );    Ok(())} fn into_meta(paths: impl IntoIterator<Item = PathBuf>) -> impl IntoIterator<Item = git_config::file::Metadata> {    paths        .into_iter()        .map(|p| git_config::file::Metadata::try_from_path(p, git_config::Source::Local).unwrap())} mod includes {    mod conditional;    mod unconditional;}