@@ -2,7 +2,12 @@ use std::str::FromStr;
2
2
3
3
use serde:: { Deserialize , Serialize } ;
4
4
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
+ } ;
6
11
7
12
use super :: Engine ;
8
13
@@ -21,18 +26,23 @@ impl std::fmt::Display for Image {
21
26
22
27
#[ derive( Debug , Clone , Deserialize , Serialize , PartialEq , Eq ) ]
23
28
pub struct PossibleImage {
24
- pub name : String ,
29
+ #[ serde( rename = "name" ) ]
30
+ pub reference : ImageReference ,
25
31
// The toolchain triple the image is built for
26
32
pub toolchain : Vec < ImagePlatform > ,
27
33
}
28
34
29
35
impl 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
+
31
41
if self . toolchain . is_empty ( ) {
32
- Image {
33
- name : self . name . clone ( ) ,
42
+ Ok ( Image {
43
+ name,
34
44
platform : ImagePlatform :: DEFAULT ,
35
- }
45
+ } )
36
46
} else {
37
47
let platform = if self . toolchain . len ( ) == 1 {
38
48
self . toolchain . first ( ) . expect ( "should contain at least one" )
@@ -71,18 +81,18 @@ impl PossibleImage {
71
81
platform
72
82
}
73
83
} ;
74
- Image {
84
+ Ok ( Image {
75
85
platform : platform. clone ( ) ,
76
- name : self . name . clone ( ) ,
77
- }
86
+ name,
87
+ } )
78
88
}
79
89
}
80
90
}
81
91
82
92
impl < T : AsRef < str > > From < T > for PossibleImage {
83
93
fn from ( s : T ) -> Self {
84
94
PossibleImage {
85
- name : s. as_ref ( ) . to_owned ( ) ,
95
+ reference : s. as_ref ( ) . to_owned ( ) . into ( ) ,
86
96
toolchain : vec ! [ ] ,
87
97
}
88
98
}
@@ -98,9 +108,57 @@ impl FromStr for PossibleImage {
98
108
99
109
impl std:: fmt:: Display for PossibleImage {
100
110
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
101
- f. write_str ( & self . name )
111
+ f. write_str ( self . reference . get ( ) )
102
112
}
103
113
}
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
+
104
162
/// The architecture/platform to use in the image
105
163
///
106
164
/// <https://github.com/containerd/containerd/blob/release/1.6/platforms/platforms.go#L63>
0 commit comments