@@ -4,9 +4,11 @@ use std::sync::LazyLock;
44use regex:: Regex ;
55
66// Matches tags that are numeric-only (e.g. "1.2.3" or "1_2-3")
7- static VERSION_RE : LazyLock < Regex > = LazyLock :: new ( || Regex :: new ( r"^(?:\d+(?:[._-]\d+)*)$" ) . unwrap ( ) ) ;
7+ static VERSION_RE : LazyLock < Regex > =
8+ LazyLock :: new ( || Regex :: new ( r"^(?:\d+(?:[._-]\d+)*)$" ) . unwrap ( ) ) ;
89// Capture a numeric version inside a tag (e.g. "v1.2" -> captures "1.2")
9- static VER_CAPTURE_RE : LazyLock < Regex > = LazyLock :: new ( || Regex :: new ( r"(?P<ver>\d+(?:[._-]\d+)*)" ) . unwrap ( ) ) ;
10+ static VER_CAPTURE_RE : LazyLock < Regex > =
11+ LazyLock :: new ( || Regex :: new ( r"(?P<ver>\d+(?:[._-]\d+)*)" ) . unwrap ( ) ) ;
1012
1113// Compare two numeric-version vectors treating missing components as zeros.
1214fn compare_version_vec ( a : & [ u64 ] , b : & [ u64 ] ) -> std:: cmp:: Ordering {
@@ -48,7 +50,10 @@ pub fn split_repo_tag_digest(s: &str) -> (&str, Option<&str>, Option<&str>) {
4850 ( s, None , None )
4951}
5052
51- pub fn derive_image_prefill ( container_name : & str , candidates : Option < & [ String ] > ) -> ( String , Option < String > ) {
53+ pub fn derive_image_prefill (
54+ container_name : & str ,
55+ candidates : Option < & [ String ] > ,
56+ ) -> ( String , Option < String > ) {
5257 // Basic normalization: trim, lowercase, replace spaces with '-', keep ascii alnum, '.', '_', '-', '/',
5358 // but preserve registry port patterns like ':5000' when immediately before '/' or end of component.
5459 let s = container_name. trim ( ) . to_lowercase ( ) ;
@@ -130,15 +135,17 @@ pub fn derive_image_prefill(container_name: &str, candidates: Option<&[String]>)
130135 }
131136
132137 // Trim leading/trailing '-' '.' '/'
133- let filter = norm. trim_matches ( |c| c == '-' || c == '.' || c == '/' ) . to_string ( ) ;
138+ let filter = norm
139+ . trim_matches ( |c| c == '-' || c == '.' || c == '/' )
140+ . to_string ( ) ;
134141 if filter. is_empty ( ) {
135142 return ( filter, None ) ;
136143 }
137144
138145 // If candidates are provided, try to pick the best matching image tag
139146 if let Some ( cands) = candidates {
140147 // collect matching candidates where repo ends with filter or equals it
141- let matching: Vec < & String > = cands
148+ let matching: Vec < & String > = cands
142149 . iter ( )
143150 . filter ( |img| {
144151 let s = img. as_str ( ) ;
@@ -220,11 +227,26 @@ mod tests {
220227
221228 #[ test]
222229 fn split_repo_tag_digest_examples ( ) {
223- assert_eq ! ( split_repo_tag_digest( "repo:1.2.3" ) , ( "repo" , Some ( "1.2.3" ) , None ) ) ;
224- assert_eq ! ( split_repo_tag_digest( "repo@sha256:abcdef" ) , ( "repo" , None , Some ( "sha256:abcdef" ) ) ) ;
225- assert_eq ! ( split_repo_tag_digest( "host:5000/repo:1.0" ) , ( "host:5000/repo" , Some ( "1.0" ) , None ) ) ;
226- assert_eq ! ( split_repo_tag_digest( "host:5000/repo@sha256:abc" ) , ( "host:5000/repo" , None , Some ( "sha256:abc" ) ) ) ;
227- assert_eq ! ( split_repo_tag_digest( "repo:tag@sha256:abc" ) , ( "repo" , None , Some ( "sha256:abc" ) ) ) ;
230+ assert_eq ! (
231+ split_repo_tag_digest( "repo:1.2.3" ) ,
232+ ( "repo" , Some ( "1.2.3" ) , None )
233+ ) ;
234+ assert_eq ! (
235+ split_repo_tag_digest( "repo@sha256:abcdef" ) ,
236+ ( "repo" , None , Some ( "sha256:abcdef" ) )
237+ ) ;
238+ assert_eq ! (
239+ split_repo_tag_digest( "host:5000/repo:1.0" ) ,
240+ ( "host:5000/repo" , Some ( "1.0" ) , None )
241+ ) ;
242+ assert_eq ! (
243+ split_repo_tag_digest( "host:5000/repo@sha256:abc" ) ,
244+ ( "host:5000/repo" , None , Some ( "sha256:abc" ) )
245+ ) ;
246+ assert_eq ! (
247+ split_repo_tag_digest( "repo:tag@sha256:abc" ) ,
248+ ( "repo" , None , Some ( "sha256:abc" ) )
249+ ) ;
228250 }
229251
230252 #[ test]
@@ -272,7 +294,10 @@ mod tests {
272294
273295 #[ test]
274296 fn candidates_none_matching_returns_none ( ) {
275- let cands = vec ! [ "other/repo:1.0" . to_string( ) , "another/repo:latest" . to_string( ) ] ;
297+ let cands = vec ! [
298+ "other/repo:1.0" . to_string( ) ,
299+ "another/repo:latest" . to_string( ) ,
300+ ] ;
276301 let ( f, s) = derive_image_prefill ( "doesnotexist" , Some ( & cands) ) ;
277302 assert_eq ! ( f, "doesnotexist" ) ;
278303 assert ! ( s. is_none( ) ) ;
@@ -281,11 +306,20 @@ mod tests {
281306 #[ test]
282307 fn split_repo_tag_digest_more_cases ( ) {
283308 // triple combo: repo:tag@sha256: -> digest should win, tag discarded
284- assert_eq ! ( split_repo_tag_digest( "repo:tag@sha256:abc" ) , ( "repo" , None , Some ( "sha256:abc" ) ) ) ;
309+ assert_eq ! (
310+ split_repo_tag_digest( "repo:tag@sha256:abc" ) ,
311+ ( "repo" , None , Some ( "sha256:abc" ) )
312+ ) ;
285313 // host with port, tag and digest -> digest wins and repo includes host:port/repo
286- assert_eq ! ( split_repo_tag_digest( "example.com:5000/repo:1.0@sha256:abc" ) , ( "example.com:5000/repo" , None , Some ( "sha256:abc" ) ) ) ;
314+ assert_eq ! (
315+ split_repo_tag_digest( "example.com:5000/repo:1.0@sha256:abc" ) ,
316+ ( "example.com:5000/repo" , None , Some ( "sha256:abc" ) )
317+ ) ;
287318 // plain repo no tag/digest
288- assert_eq ! ( split_repo_tag_digest( "plainrepo" ) , ( "plainrepo" , None , None ) ) ;
319+ assert_eq ! (
320+ split_repo_tag_digest( "plainrepo" ) ,
321+ ( "plainrepo" , None , None )
322+ ) ;
289323 }
290324
291325 #[ test]
@@ -313,8 +347,14 @@ mod tests {
313347
314348 #[ test]
315349 fn ipv6_and_bracketed_host_handling ( ) {
316- assert_eq ! ( split_repo_tag_digest( "[::1]:5000/repo:1.0" ) , ( "[::1]:5000/repo" , Some ( "1.0" ) , None ) ) ;
317- assert_eq ! ( split_repo_tag_digest( "[::1]:5000/repo@sha256:abc" ) , ( "[::1]:5000/repo" , None , Some ( "sha256:abc" ) ) ) ;
350+ assert_eq ! (
351+ split_repo_tag_digest( "[::1]:5000/repo:1.0" ) ,
352+ ( "[::1]:5000/repo" , Some ( "1.0" ) , None )
353+ ) ;
354+ assert_eq ! (
355+ split_repo_tag_digest( "[::1]:5000/repo@sha256:abc" ) ,
356+ ( "[::1]:5000/repo" , None , Some ( "sha256:abc" ) )
357+ ) ;
318358 }
319359
320360 #[ test]
0 commit comments