@@ -2,10 +2,11 @@ use std::{
22 fmt:: { Debug , Display } ,
33 path:: PathBuf ,
44 str:: FromStr ,
5+ sync:: LazyLock ,
56} ;
67
78use clap:: { Args , ValueHint , value_parser} ;
8- use semver :: Version ;
9+ use regex :: Regex ;
910use snafu:: { ResultExt , Snafu , ensure} ;
1011use strum:: EnumDiscriminants ;
1112use url:: Host ;
@@ -30,7 +31,7 @@ pub struct BuildArguments {
3031 default_value_t = Self :: default_image_version( ) ,
3132 help_heading = "Image Options"
3233 ) ]
33- pub image_version : Version ,
34+ pub image_version : String ,
3435
3536 /// Target platform of the image.
3637 #[ arg(
@@ -129,16 +130,29 @@ pub struct BuildArguments {
129130 pub rest : Vec < String > ,
130131}
131132
133+ // This is derived from the general rule where the length of the tag can be up to 128 chars
134+ // But that checking needs to be at a higher layer.
135+ static VALID_IMAGE_TAG : LazyLock < Regex > =
136+ LazyLock :: new ( || Regex :: new ( r"^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$" ) . expect ( "regex is valid" ) ) ;
137+
132138impl BuildArguments {
133- fn parse_image_version ( input : & str ) -> Result < Version , ParseImageVersionError > {
134- let version = Version :: from_str ( input) . context ( ParseVersionSnafu ) ?;
135- ensure ! ( version. build. is_empty( ) , ContainsBuildMetadataSnafu ) ;
139+ /// Ensure that the given version will be valid for use in the image tag
140+ fn parse_image_version ( version : & str ) -> Result < String , ParseImageVersionError > {
141+ // TODO (@NickLarsenNZ): Probably want to minus the characters used in front (x.y.z-stackable).
142+ // But maybe that validation needs to go up a layer.
143+ if version. len ( ) > 128 {
144+ return VersionTooLongSnafu . fail ( ) ;
145+ }
146+
147+ if !VALID_IMAGE_TAG . is_match ( version) {
148+ return ParseVersionSnafu { version } . fail ( ) ;
149+ }
136150
137- Ok ( version)
151+ Ok ( version. to_owned ( ) )
138152 }
139153
140- fn default_image_version ( ) -> Version {
141- "0.0.0-dev" . parse ( ) . expect ( "must be a valid SemVer" )
154+ fn default_image_version ( ) -> String {
155+ "0.0.0-dev" . to_owned ( )
142156 }
143157
144158 fn default_registry ( ) -> HostPort {
@@ -160,11 +174,11 @@ impl BuildArguments {
160174
161175#[ derive( Debug , Snafu ) ]
162176pub enum ParseImageVersionError {
163- #[ snafu( display( "failed to parse semantic version " ) ) ]
164- ParseVersion { source : semver :: Error } ,
177+ #[ snafu( display( "The version exceeds the 128 character limit " ) ) ]
178+ VersionTooLong ,
165179
166- #[ snafu( display( "semantic version must not contain build metadata " ) ) ]
167- ContainsBuildMetadata ,
180+ #[ snafu( display( "invalid image tag characters for {version:?} " ) ) ]
181+ ParseVersion { version : String } ,
168182}
169183
170184#[ derive( Debug , PartialEq , Snafu , EnumDiscriminants ) ]
0 commit comments