@@ -26,6 +26,7 @@ pub struct ToolSpec {
2626pub enum Protocol {
2727 Github ,
2828 Gitlab ,
29+ Artifactory ,
2930}
3031
3132impl ToolSpec {
@@ -96,13 +97,15 @@ impl ToolSpec {
9697 match self . protocol {
9798 Protocol :: Github => CiString ( format ! ( "{}" , self . path) ) ,
9899 Protocol :: Gitlab => CiString ( format ! ( "gitlab@{}" , self . path) ) ,
100+ Protocol :: Artifactory => CiString ( format ! ( "{}@{}" , self . host, self . path) ) ,
99101 }
100102 }
101103
102104 pub fn source ( & self ) -> String {
103105 let provider = match self . protocol {
104106 Protocol :: Github => "github.com" ,
105107 Protocol :: Gitlab => "gitlab.com" ,
108+ Protocol :: Artifactory => "artifactory.com" ,
106109 } ;
107110
108111 format ! ( "{}/{}" , provider, self . path)
@@ -120,6 +123,7 @@ impl ToolSpec {
120123 match self . protocol {
121124 Protocol :: Github => Provider :: Github ,
122125 Protocol :: Gitlab => Provider :: Gitlab ,
126+ Protocol :: Artifactory => Provider :: Artifactory ,
123127 }
124128 }
125129}
@@ -130,7 +134,7 @@ impl fmt::Display for ToolSpec {
130134 }
131135}
132136
133- #[ derive( Debug ) ]
137+ #[ derive( Debug , PartialEq ) ]
134138pub struct ConfigFile {
135139 pub tools : BTreeMap < String , ToolSpec > ,
136140 pub hosts : HashMap < String , Host > ,
@@ -149,6 +153,57 @@ impl Host {
149153 protocol,
150154 }
151155 }
156+
157+ pub fn from_value ( value : & Value ) -> ConfigFileParseResult < Self > {
158+ if let Value :: Table ( mut map) = value. clone ( ) {
159+ let source = map
160+ . remove ( "source" )
161+ . ok_or_else ( || ConfigFileParseError :: Host {
162+ host : value. to_string ( ) ,
163+ } ) ?
164+ . as_str ( )
165+ . ok_or_else ( || ConfigFileParseError :: Host {
166+ host : value. to_string ( ) ,
167+ } ) ?
168+ . to_string ( ) ;
169+
170+ let protocol_value =
171+ map. remove ( "protocol" )
172+ . ok_or_else ( || ConfigFileParseError :: Host {
173+ host : value. to_string ( ) ,
174+ } ) ?;
175+
176+ if !map. is_empty ( ) {
177+ return Err ( ConfigFileParseError :: Host {
178+ host : value. to_string ( ) ,
179+ } ) ;
180+ }
181+
182+ let protocol_str =
183+ protocol_value
184+ . as_str ( )
185+ . ok_or_else ( || ConfigFileParseError :: Host {
186+ host : value. to_string ( ) ,
187+ } ) ?;
188+
189+ let protocol = match protocol_str {
190+ "github" => Protocol :: Github ,
191+ "gitlab" => Protocol :: Gitlab ,
192+ "artifactory" => Protocol :: Artifactory ,
193+ _ => {
194+ return Err ( ConfigFileParseError :: InvalidProtocol {
195+ protocol : protocol_str. to_string ( ) ,
196+ } )
197+ }
198+ } ;
199+
200+ Ok ( Self { source, protocol } )
201+ } else {
202+ Err ( ConfigFileParseError :: Host {
203+ host : value. to_string ( ) ,
204+ } )
205+ }
206+ }
152207}
153208
154209impl ConfigFile {
@@ -167,6 +222,18 @@ impl ConfigFile {
167222 let mut config = ConfigFile :: new_with_defaults ( ) ;
168223
169224 if let Value :: Table ( top_level) = & value {
225+ if let Some ( hosts) = & top_level. get ( "hosts" ) {
226+ if let Value :: Table ( hosts) = hosts {
227+ for ( host, toml) in hosts {
228+ let host_source =
229+ Host :: from_value ( & toml) . map_err ( |_| ConfigFileParseError :: Tool {
230+ tool : value. to_string ( ) ,
231+ } ) ?;
232+ config. hosts . insert ( host. to_owned ( ) , host_source) ;
233+ }
234+ }
235+ }
236+
170237 if let Some ( tools) = & top_level. get ( "tools" ) {
171238 if let Value :: Table ( tools) = tools {
172239 for ( tool, toml) in tools {
@@ -260,6 +327,7 @@ impl fmt::Display for ConfigFile {
260327
261328#[ cfg( test) ]
262329mod test {
330+ const ARTIFACTORY : & ' static str = "https://artifactory.com" ;
263331 use super :: * ;
264332
265333 fn new_github < S : Into < String > > ( github : S , version : VersionReq ) -> ToolSpec {
@@ -280,10 +348,32 @@ mod test {
280348 }
281349 }
282350
351+ fn new_artifactory < S : Into < String > > ( host : S , path : S , version : VersionReq ) -> ToolSpec {
352+ ToolSpec {
353+ host : host. into ( ) ,
354+ path : path. into ( ) ,
355+ version : version,
356+ protocol : Protocol :: Artifactory ,
357+ }
358+ }
359+
360+ fn new_config ( tools : BTreeMap < String , ToolSpec > , hosts : HashMap < String , Host > ) -> ConfigFile {
361+ let mut config = ConfigFile :: new_with_defaults ( ) ;
362+ config. fill_from ( ConfigFile { tools, hosts } ) ;
363+ config
364+ }
365+
283366 fn version ( string : & str ) -> VersionReq {
284367 VersionReq :: parse ( string) . unwrap ( )
285368 }
286369
370+ fn new_host < S : Into < String > > ( source : S , protocol : Protocol ) -> Host {
371+ Host {
372+ source : source. into ( ) ,
373+ protocol,
374+ }
375+ }
376+
287377 fn default_hosts ( ) -> HashMap < String , Host > {
288378 HashMap :: from ( [
289379 (
@@ -301,7 +391,17 @@ mod test {
301391 ] )
302392 }
303393
394+ fn artifactory_host ( ) -> HashMap < String , Host > {
395+ let mut hosts = default_hosts ( ) ;
396+ hosts. insert (
397+ "artifactory" . to_string ( ) ,
398+ Host :: new ( ARTIFACTORY . to_string ( ) , Protocol :: Artifactory ) ,
399+ ) ;
400+ hosts
401+ }
402+
304403 mod deserialization {
404+
305405 use super :: * ;
306406
307407 #[ test]
@@ -333,25 +433,65 @@ mod test {
333433 assert_eq ! ( gitlab, new_gitlab( "user/repo" , version( "0.1.0" ) ) ) ;
334434 }
335435
436+ #[ test]
437+ fn artifactory_from_artifactory_field ( ) {
438+ let value: Value = toml:: from_str (
439+ & [
440+ r#"artifactory = "generic-rbx-local-tools/rotriever/""# ,
441+ r#"version = "0.5.4""# ,
442+ ]
443+ . join ( "\n " ) ,
444+ )
445+ . unwrap ( ) ;
446+
447+ let artifactory = ToolSpec :: from_value ( & value, & artifactory_host ( ) ) . unwrap ( ) ;
448+ assert_eq ! (
449+ artifactory,
450+ new_artifactory(
451+ "https://artifactory.com" ,
452+ "generic-rbx-local-tools/rotriever/" ,
453+ version( "0.5.4" )
454+ )
455+ ) ;
456+ }
457+
458+ #[ test]
459+ fn host_artifactory ( ) {
460+ let value: Value = toml:: from_str (
461+ & [
462+ r#"source = "https://artifactory.com""# ,
463+ r#"protocol = "artifactory""# ,
464+ ]
465+ . join ( "\n " ) ,
466+ )
467+ . unwrap ( ) ;
468+
469+ let host = Host :: from_value ( & value) . unwrap ( ) ;
470+ assert_eq ! (
471+ host,
472+ new_host( "https://artifactory.com" , Protocol :: Artifactory )
473+ )
474+ }
475+
336476 #[ test]
337477 fn extraneous_fields_tools ( ) {
338478 let value: Value = toml:: from_str (
339479 & [
340- r#"github = "Roblox /rotriever""# ,
341- r#"path = "Roblox /rotriever""# ,
480+ r#"rbx_artifactory = "generic-rbx-local-tools /rotriever/ ""# ,
481+ r#"path = "generic-rbx-local-tools /rotriever/ ""# ,
342482 r#"version = "0.5.4""# ,
343483 ]
344484 . join ( "\n " ) ,
345485 )
346486 . unwrap ( ) ;
347487
348- let artifactory = ToolSpec :: from_value ( & value, & default_hosts ( ) ) . unwrap_err ( ) ;
488+ let artifactory = ToolSpec :: from_value ( & value, & artifactory_host ( ) ) . unwrap_err ( ) ;
349489 assert_eq ! (
350490 artifactory,
351491 ConfigFileParseError :: Tool {
352492 tool: [
353- r#"github = "Roblox /rotriever""# ,
354- r#"path = "Roblox /rotriever""# ,
493+ r#"path = "generic-rbx-local-tools /rotriever/ ""# ,
494+ r#"rbx_artifactory = "generic-rbx-local-tools /rotriever/ ""# ,
355495 r#"version = "0.5.4""# ,
356496 r#""# ,
357497 ]
@@ -360,6 +500,68 @@ mod test {
360500 }
361501 )
362502 }
503+
504+ #[ test]
505+ fn extraneous_fields_host ( ) {
506+ let value: Value = toml:: from_str (
507+ & [
508+ r#"source = "https://artifactory.com""# ,
509+ r#"protocol = "artifactory""# ,
510+ r#"extra = "field""# ,
511+ ]
512+ . join ( "\n " ) ,
513+ )
514+ . unwrap ( ) ;
515+
516+ let err = Host :: from_value ( & value) . unwrap_err ( ) ;
517+ assert_eq ! (
518+ err,
519+ ConfigFileParseError :: Host {
520+ host: [
521+ r#"extra = "field""# ,
522+ r#"protocol = "artifactory""# ,
523+ r#"source = "https://artifactory.com""# ,
524+ r#""# ,
525+ ]
526+ . join( "\n " )
527+ . to_string( )
528+ }
529+ )
530+ }
531+ #[ test]
532+ fn config_file_with_hosts ( ) {
533+ let value: Value = toml:: from_str ( & [
534+ r#"[hosts]"# ,
535+ r#"artifactory = {source = "https://artifactory.com", protocol = "artifactory"}"# ,
536+ r#""# ,
537+ r#"[tools]"# ,
538+ r#"tool = {artifactory = "path/to/tool", version = "1.0.0"}"# ,
539+ ] . join ( "\n " ) )
540+ . unwrap ( ) ;
541+
542+ let config = ConfigFile :: from_value ( value) . unwrap ( ) ;
543+ assert_eq ! (
544+ config,
545+ new_config(
546+ BTreeMap :: from( [ (
547+ "tool" . to_string( ) ,
548+ ToolSpec {
549+ host: "https://artifactory.com" . to_string( ) ,
550+ path: "path/to/tool" . to_string( ) ,
551+ version: VersionReq :: parse( "1.0.0" ) . unwrap( ) ,
552+ protocol: Protocol :: Artifactory
553+ }
554+ ) ] ) ,
555+ HashMap :: from( [ (
556+ "artifactory" . to_string( ) ,
557+ Host {
558+ source: "https://artifactory.com" . to_string( ) ,
559+ protocol: Protocol :: Artifactory
560+ }
561+ ) ] )
562+ )
563+ )
564+ }
363565 }
364566
365567 #[ test]
0 commit comments