@@ -2,7 +2,12 @@ use std::str::FromStr;
22
33use serde:: { Deserialize , Serialize } ;
44
5- use crate :: { errors:: * , shell:: MessageInfo , TargetTriple } ;
5+ use crate :: {
6+ docker:: { CROSS_IMAGE , DEFAULT_IMAGE_VERSION } ,
7+ errors:: * ,
8+ shell:: MessageInfo ,
9+ TargetTriple ,
10+ } ;
611
712use super :: Engine ;
813
@@ -21,18 +26,23 @@ impl std::fmt::Display for Image {
2126
2227#[ derive( Debug , Clone , Deserialize , Serialize , PartialEq , Eq ) ]
2328pub struct PossibleImage {
24- pub name : String ,
29+ #[ serde( rename = "name" ) ]
30+ pub reference : ImageReference ,
2531 // The toolchain triple the image is built for
2632 pub toolchain : Vec < ImagePlatform > ,
2733}
2834
2935impl PossibleImage {
30- pub fn to_definite_with ( & self , engine : & Engine , msg_info : & mut MessageInfo ) -> Image {
36+ pub fn to_definite_with ( & self , engine : & Engine , msg_info : & mut MessageInfo ) -> Result < Image > {
37+ let ImageReference :: Name ( name) = self . reference . clone ( ) else {
38+ eyre:: bail!( "cannot make definite Image from unqualified PossibleImage" ) ;
39+ } ;
40+
3141 if self . toolchain . is_empty ( ) {
32- Image {
33- name : self . name . clone ( ) ,
42+ Ok ( Image {
43+ name,
3444 platform : ImagePlatform :: DEFAULT ,
35- }
45+ } )
3646 } else {
3747 let platform = if self . toolchain . len ( ) == 1 {
3848 self . toolchain . first ( ) . expect ( "should contain at least one" )
@@ -71,18 +81,18 @@ impl PossibleImage {
7181 platform
7282 }
7383 } ;
74- Image {
84+ Ok ( Image {
7585 platform : platform. clone ( ) ,
76- name : self . name . clone ( ) ,
77- }
86+ name,
87+ } )
7888 }
7989 }
8090}
8191
8292impl < T : AsRef < str > > From < T > for PossibleImage {
8393 fn from ( s : T ) -> Self {
8494 PossibleImage {
85- name : s. as_ref ( ) . to_owned ( ) ,
95+ reference : s. as_ref ( ) . to_owned ( ) . into ( ) ,
8696 toolchain : vec ! [ ] ,
8797 }
8898 }
@@ -98,9 +108,57 @@ impl FromStr for PossibleImage {
98108
99109impl std:: fmt:: Display for PossibleImage {
100110 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
101- f. write_str ( & self . name )
111+ f. write_str ( self . reference . get ( ) )
102112 }
103113}
114+
115+ #[ derive( Debug , Clone , Deserialize , Serialize , PartialEq , Eq ) ]
116+ #[ serde( from = "String" , untagged) ]
117+ pub enum ImageReference {
118+ /// Partially qualified reference, with or without tag/digest
119+ Name ( String ) ,
120+ /// Unqualified reference, only a tag or digest
121+ Identifier ( String ) ,
122+ /// Unqualified reference, only a subtarget
123+ Subtarget ( String ) ,
124+ }
125+
126+ impl ImageReference {
127+ pub fn get ( & self ) -> & str {
128+ match self {
129+ Self :: Name ( s) => s,
130+ Self :: Identifier ( s) => s,
131+ Self :: Subtarget ( s) => s,
132+ }
133+ }
134+
135+ pub fn ensure_qualified ( & mut self , target_name : & str ) {
136+ let image_name = match self {
137+ Self :: Name ( _) => return ,
138+ Self :: Identifier ( id) => {
139+ format ! ( "{CROSS_IMAGE}/{target_name}{id}" )
140+ }
141+ Self :: Subtarget ( sub) => {
142+ format ! ( "{CROSS_IMAGE}/{target_name}:{DEFAULT_IMAGE_VERSION}{sub}" )
143+ }
144+ } ;
145+
146+ * self = Self :: Name ( image_name) ;
147+ }
148+ }
149+
150+ impl From < String > for ImageReference {
151+ fn from ( s : String ) -> Self {
152+ if s. starts_with ( '-' ) {
153+ Self :: Subtarget ( s)
154+ } else if s. starts_with ( ':' ) || s. starts_with ( '@' ) {
155+ Self :: Identifier ( s)
156+ } else {
157+ Self :: Name ( s)
158+ }
159+ }
160+ }
161+
104162/// The architecture/platform to use in the image
105163///
106164/// <https://github.com/containerd/containerd/blob/release/1.6/platforms/platforms.go#L63>
0 commit comments