@@ -16,7 +16,12 @@ pub use run::resolve_pattern_repositories;
1616
1717#[ cfg( test) ]
1818mod tests {
19+ use std:: cell:: RefCell ;
20+
21+ use crate :: config;
22+
1923 use super :: git:: { is_git_source, is_safe_git_url} ;
24+ use super :: run:: resolve_pattern_repositories_with;
2025
2126 #[ test]
2227 fn test_is_git_source_https ( ) {
@@ -81,4 +86,80 @@ mod tests {
8186 fn test_is_safe_git_url_rejects_http_without_git_suffix ( ) {
8287 assert ! ( !is_safe_git_url( "http://example.com/repo" ) ) ;
8388 }
89+
90+ #[ test]
91+ fn test_resolve_pattern_repositories_accepts_repo_relative_local_paths ( ) {
92+ let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
93+ let repo_root = tempdir. path ( ) ;
94+ let local_repo = repo_root. join ( "patterns/local-rules" ) ;
95+ std:: fs:: create_dir_all ( & local_repo) . unwrap ( ) ;
96+
97+ let mut config = config:: Config :: default ( ) ;
98+ config. pattern_repositories = vec ! [ config:: PatternRepositoryConfig {
99+ source: "patterns/local-rules" . to_string( ) ,
100+ ..Default :: default ( )
101+ } ] ;
102+
103+ let resolved = resolve_pattern_repositories_with ( & config, repo_root, |_| None ) ;
104+
105+ assert_eq ! ( resolved. len( ) , 1 ) ;
106+ assert_eq ! (
107+ resolved. get( "patterns/local-rules" ) ,
108+ Some ( & local_repo. canonicalize( ) . unwrap( ) )
109+ ) ;
110+ }
111+
112+ #[ test]
113+ fn test_resolve_pattern_repositories_accepts_git_sources_via_checkout_helper ( ) {
114+ let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
115+ let repo_root = tempdir. path ( ) ;
116+ let checkout_path = repo_root. join ( "cloned-rules" ) ;
117+ std:: fs:: create_dir_all ( & checkout_path) . unwrap ( ) ;
118+
119+ let mut config = config:: Config :: default ( ) ;
120+ let source = "https://github.com/example/rules.git" . to_string ( ) ;
121+ config. pattern_repositories = vec ! [ config:: PatternRepositoryConfig {
122+ source: source. clone( ) ,
123+ ..Default :: default ( )
124+ } ] ;
125+
126+ let checkout_calls = RefCell :: new ( Vec :: new ( ) ) ;
127+ let resolved = resolve_pattern_repositories_with ( & config, repo_root, |candidate| {
128+ checkout_calls. borrow_mut ( ) . push ( candidate. to_string ( ) ) ;
129+ Some ( checkout_path. clone ( ) )
130+ } ) ;
131+
132+ assert_eq ! ( checkout_calls. into_inner( ) , vec![ source. clone( ) ] ) ;
133+ assert_eq ! ( resolved. get( & source) , Some ( & checkout_path) ) ;
134+ }
135+
136+ #[ test]
137+ fn test_resolve_pattern_repositories_skips_broken_sources ( ) {
138+ let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ;
139+ let repo_root = tempdir. path ( ) ;
140+
141+ let mut config = config:: Config :: default ( ) ;
142+ config. pattern_repositories = vec ! [
143+ config:: PatternRepositoryConfig {
144+ source: "missing/local-rules" . to_string( ) ,
145+ ..Default :: default ( )
146+ } ,
147+ config:: PatternRepositoryConfig {
148+ source: "https://github.com/example/broken.git" . to_string( ) ,
149+ ..Default :: default ( )
150+ } ,
151+ ] ;
152+
153+ let checkout_calls = RefCell :: new ( Vec :: new ( ) ) ;
154+ let resolved = resolve_pattern_repositories_with ( & config, repo_root, |candidate| {
155+ checkout_calls. borrow_mut ( ) . push ( candidate. to_string ( ) ) ;
156+ None
157+ } ) ;
158+
159+ assert ! ( resolved. is_empty( ) ) ;
160+ assert_eq ! (
161+ checkout_calls. into_inner( ) ,
162+ vec![ "https://github.com/example/broken.git" . to_string( ) ]
163+ ) ;
164+ }
84165}
0 commit comments