1- use std:: { fs, marker:: PhantomData , path :: PathBuf } ;
1+ use std:: { fs, marker:: PhantomData } ;
22
33use indexmap:: IndexMap ;
44use serde:: { Deserialize , Serialize } ;
55use thiserror:: Error ;
6- use url:: Url ;
76
87use crate :: utils:: {
98 path:: PathOrUrl ,
10- read:: { read_cached_yaml_data, read_yaml_data, CacheSettings , CacheStatus , RemoteReadError } ,
9+ read:: {
10+ read_cached_yaml_data, read_yaml_data_from_file, read_yaml_data_from_remote, CacheSettings ,
11+ CacheStatus , CachedReadError , LocalReadError , RemoteReadError ,
12+ } ,
1113} ;
1214
1315pub trait SpecIter < S > {
@@ -19,14 +21,23 @@ pub enum ListError {
1921 #[ error( "io error: {0}" ) ]
2022 IoError ( #[ from] std:: io:: Error ) ,
2123
22- #[ error( "read error: {0}" ) ]
23- ReadError ( #[ from] RemoteReadError ) ,
24+ #[ error( "local read error: {0}" ) ]
25+ LocalReadError ( #[ from] LocalReadError ) ,
26+
27+ #[ error( "remote read error: {0}" ) ]
28+ RemoteReadError ( #[ from] RemoteReadError ) ,
29+
30+ #[ error( "cached read error: {0}" ) ]
31+ CachedReadError ( #[ from] CachedReadError ) ,
2432
2533 #[ error( "url parse error: {0}" ) ]
2634 ParseUrlError ( #[ from] url:: ParseError ) ,
2735
2836 #[ error( "yaml error: {0}" ) ]
2937 YamlError ( #[ from] serde_yaml:: Error ) ,
38+
39+ #[ error( "invalid file url" ) ]
40+ InvalidFileUrl ,
3041}
3142
3243/// A [`List`] describes a list of specs. The list can contain any specs, for example demos, stacks or releases. The
@@ -46,35 +57,43 @@ where
4657 L : for < ' a > Deserialize < ' a > + Serialize + SpecIter < S > ,
4758 S : for < ' a > Deserialize < ' a > + Serialize + Clone ,
4859{
49- pub async fn build < U , T > ( files : T , cache_settings : CacheSettings ) -> Result < Self , ListError >
60+ pub async fn build < T > ( files : T , cache_settings : CacheSettings ) -> Result < Self , ListError >
5061 where
51- U : AsRef < str > ,
5262 T : AsRef < [ PathOrUrl ] > ,
5363 {
5464 let mut map = IndexMap :: new ( ) ;
55- // let remote_url = Url::parse(remote_url.as_ref())?;
5665
5766 for file in files. as_ref ( ) {
58- match file {
59- PathOrUrl :: Path ( path) => todo ! ( ) ,
60- PathOrUrl :: Url ( _) => todo ! ( ) ,
61- }
62- }
63-
64- // First load the remote demo file. This uses the cached file if present, and if not, requests the remote file
65- // and then saves the contents on disk for cached use later
66- for ( spec_name, spec) in Self :: get_remote_or_cached_file ( remote_url, cache_settings)
67- . await ?
68- . inner ( )
69- {
70- map. insert ( spec_name. clone ( ) , spec. clone ( ) ) ;
71- }
67+ let specs = match file {
68+ PathOrUrl :: Path ( path) => read_yaml_data_from_file :: < L > ( path. clone ( ) ) ?,
69+ PathOrUrl :: Url ( url) => {
70+ if cache_settings. use_cache {
71+ let file_name = url
72+ . path_segments ( )
73+ . ok_or ( ListError :: InvalidFileUrl ) ?
74+ . last ( )
75+ . ok_or ( ListError :: InvalidFileUrl ) ?;
76+
77+ let file_path = cache_settings. base_path . join ( file_name) ;
78+
79+ match read_cached_yaml_data :: < L > ( file_path. clone ( ) , & cache_settings) ? {
80+ CacheStatus :: Hit ( specs) => specs,
81+ CacheStatus :: Expired | CacheStatus :: Miss => {
82+ let data = read_yaml_data_from_remote :: < L > ( url. clone ( ) ) . await ?;
83+ let yaml = serde_yaml:: to_string ( & data) ?;
84+ fs:: write ( file_path, yaml) ?;
85+
86+ data
87+ }
88+ }
89+ } else {
90+ read_yaml_data_from_remote :: < L > ( url. clone ( ) ) . await ?
91+ }
92+ }
93+ } ;
7294
73- // Iterate over all provided files, either from ENV var or CLI argument
74- for file in files. as_ref ( ) {
75- let demos = read_yaml_data :: < L > ( file) . await ?;
76- for ( demo_name, demo) in demos. inner ( ) {
77- map. insert ( demo_name. to_owned ( ) , demo. to_owned ( ) ) ;
95+ for ( spec_name, spec) in specs. inner ( ) {
96+ map. insert ( spec_name. clone ( ) , spec. clone ( ) ) ;
7897 }
7998 }
8099
@@ -96,24 +115,4 @@ where
96115 {
97116 self . inner . get ( & name. into ( ) )
98117 }
99-
100- async fn get_remote_or_cached_file (
101- remote_url : Url ,
102- cache_settings : CacheSettings ,
103- ) -> Result < L , ListError > {
104- let specs = if cache_settings. use_cache {
105- match read_cached_yaml_data :: < L > ( & cache_settings) ? {
106- CacheStatus :: Hit ( demos) => demos,
107- CacheStatus :: Expired | CacheStatus :: Miss => {
108- let demos = read_yaml_data :: < L > ( remote_url) . await ?;
109- fs:: write ( cache_settings. file_path , serde_yaml:: to_string ( & demos) ?) ?;
110- demos
111- }
112- }
113- } else {
114- read_yaml_data :: < L > ( remote_url) . await ?
115- } ;
116-
117- Ok ( specs)
118- }
119118}
0 commit comments