mod util; use git_testtools::Env; use serial_test::serial; use util::{assert_section_value, Condition, GitEnv}; use crate::file::init::from_paths::escape_backslashes; #[test] fn relative_path_with_trailing_slash_matches_like_star_star() -> crate::Result { assert_section_value(Condition::new("gitdir:worktree/"), GitEnv::repo_name("worktree")?) } #[test] fn relative_path_without_trailing_slash_does_not_match() -> crate::Result { assert_section_value( Condition::new("gitdir:worktree").expect_original_value(), GitEnv::repo_name("worktree")?, ) } #[test] fn relative_path_without_trailing_slash_and_dot_git_suffix_matches() -> crate::Result { assert_section_value(Condition::new("gitdir:worktree/.git"), GitEnv::repo_name("worktree")?) } #[test] fn tilde_slash_expands_the_current_user_home() -> crate::Result { let env = GitEnv::repo_name(std::path::Path::new("subdir").join("worktree"))?; assert_section_value(Condition::new("gitdir:~/subdir/worktree/"), env) } #[test] fn tilde_alone_does_not_match_even_if_home_is_git_directory() -> crate::Result { let env = GitEnv::repo_in_home()?; assert_section_value(Condition::new("gitdir:~").expect_original_value(), env) } #[test] fn explicit_star_star_prefix_and_suffix_match_zero_or_more_path_components() -> crate::Result { assert_section_value(Condition::new("gitdir:**/worktree/**"), GitEnv::repo_name("worktree")?) } #[test] fn double_slash_does_not_match() -> crate::Result { assert_section_value( Condition::new("gitdir://worktree").expect_original_value(), GitEnv::repo_name("worktree")?, ) } #[test] fn absolute_git_dir_with_os_separators_match() -> crate::Result { assert_section_value( original_value_on_windows(Condition::new("gitdir:$gitdir")), GitEnv::repo_name("worktree")?, ) } #[test] fn absolute_worktree_dir_with_os_separators_does_not_match_if_trailing_slash_is_missing() -> crate::Result { assert_section_value( Condition::new("gitdir:$worktree").expect_original_value(), GitEnv::repo_name("worktree")?, ) } #[test] fn absolute_worktree_dir_with_os_separators_matches_with_trailing_glob() -> crate::Result { assert_section_value( original_value_on_windows(Condition::new(format!( "gitdir:$worktree{}**", std::path::MAIN_SEPARATOR ))), GitEnv::repo_name("worktree")?, ) } #[test] fn dot_slash_path_is_replaced_with_directory_containing_the_including_config_file() -> crate::Result { assert_section_value( Condition::new("gitdir:./").set_user_config_instead_of_repo_config(), GitEnv::repo_name("worktree")?, // the user configuration is in $HOME, which is parent to $HOME/worktree, and the pattern path ends up being $HOME/**, including worktree/.git ) } #[test] #[serial] fn dot_slash_from_environment_causes_error() -> crate::Result { let env = GitEnv::repo_name("worktree")?; { let _environment = Env::new() .set("GIT_CONFIG_COUNT", "1") .set( "GIT_CONFIG_KEY_0", format!("includeIf.gitdir:{}.path", escape_backslashes(env.git_dir())), ) .set("GIT_CONFIG_VALUE_0", "./include.path"); let res = git_config::File::from_env(env.to_init_options()); assert!( matches!( res, Err(git_config::file::init::from_env::Error::Includes( git_config::file::includes::Error::MissingConfigPath )) ), "this is a failure of resolving the include path, after trying to include it" ); } let absolute_path = escape_backslashes(env.home_dir().join("include.config")); { let _environment = Env::new() .set("GIT_CONFIG_COUNT", "1") .set("GIT_CONFIG_KEY_0", "includeIf.gitdir:./worktree/.path") .set("GIT_CONFIG_VALUE_0", &absolute_path); let res = git_config::File::from_env(env.to_init_options()); assert!( matches!( res, Err(git_config::file::init::from_env::Error::Includes( git_config::file::includes::Error::MissingConfigPath )) ), "here the pattern path tries to be resolved and fails as target config isn't set" ); } { let _environment = Env::new() .set("GIT_CONFIG_COUNT", "1") .set( "GIT_CONFIG_KEY_0", format!("includeIf.gitdir:{}.path", escape_backslashes(env.git_dir())), ) .set("GIT_CONFIG_VALUE_0", absolute_path); let res = git_config::File::from_env(env.to_init_options()); assert!(res.is_ok(), "missing paths are ignored as before"); } Ok(()) } #[test] fn dot_dot_slash_prefixes_are_not_special_and_are_not_what_you_want() -> crate::Result { assert_section_value( Condition::new("gitdir:../") .set_user_config_instead_of_repo_config() .expect_no_value(), GitEnv::repo_name("worktree")?, ) } #[test] fn leading_dots_are_not_special() -> crate::Result { assert_section_value(Condition::new("gitdir:.hidden/"), GitEnv::repo_name(".hidden")?) } #[test] fn dot_slash_path_with_dot_git_suffix_matches() -> crate::Result { assert_section_value( Condition::new("gitdir:./worktree/.git").set_user_config_instead_of_repo_config(), GitEnv::repo_name("worktree")?, ) } #[test] fn globbing_and_wildcards() -> crate::Result { assert_section_value( Condition::new("gitdir:stan?ard/glo*ng/[xwz]ildcards/.git").set_user_config_instead_of_repo_config(), GitEnv::repo_name("standard/globbing/wildcards")?, ) } #[test] fn case_insensitive_matches_any_case() -> crate::Result { assert_section_value(Condition::new("gitdir/i:WORKTREE/"), GitEnv::repo_name("worktree")?)?; assert_section_value( Condition::new("gitdir:WORKTREE/").expect_original_value(), GitEnv::repo_name("worktree")?, ) } #[test] fn pattern_with_escaped_backslash() -> crate::Result { assert_section_value( original_value_on_windows(Condition::new(r#"gitdir:\\work\\tree\\/"#)), GitEnv::repo_name("worktree")?, ) } #[test] fn pattern_with_backslash() -> crate::Result { assert_section_value(Condition::new(r#"gitdir:work\tree/"#), GitEnv::repo_name("worktree")?) } #[test] fn star_star_in_the_middle() -> crate::Result { assert_section_value( Condition::new("gitdir:**/dir/**/worktree/**"), GitEnv::repo_name("dir/worktree")?, ) } #[test] #[cfg(not(windows))] fn tilde_expansion_with_symlink() -> crate::Result { let env = util::git_env_with_symlinked_repo()?; assert_section_value(Condition::new("gitdir:~/worktree/"), env) } #[test] #[cfg(not(windows))] fn dot_path_with_symlink() -> crate::Result { let env = util::git_env_with_symlinked_repo()?; assert_section_value( Condition::new("gitdir:./symlink-worktree/.git").set_user_config_instead_of_repo_config(), env, ) } #[test] #[cfg(not(windows))] fn relative_path_matching_symlink() -> crate::Result { let env = util::git_env_with_symlinked_repo()?; assert_section_value( Condition::new("gitdir:symlink-worktree/").set_user_config_instead_of_repo_config(), env, ) } #[test] #[cfg(not(windows))] fn dot_path_matching_symlink_with_icase() -> crate::Result { let env = util::git_env_with_symlinked_repo()?; assert_section_value( Condition::new("gitdir/i:SYMLINK-WORKTREE/").set_user_config_instead_of_repo_config(), env, ) } fn original_value_on_windows(c: Condition) -> Condition { if cfg!(windows) { c.expect_original_value() } else { c } }