@@ -3,6 +3,7 @@ use std::collections::HashMap;
33use serde:: Deserialize ;
44use snafu:: { OptionExt , ResultExt , Snafu } ;
55use tracing:: debug;
6+ use url:: Url ;
67use urlencoding:: encode;
78
89use crate :: {
@@ -29,6 +30,12 @@ pub enum Error {
2930
3031 #[ snafu( display( "unexpected OCI repository name" ) ) ]
3132 UnexpectedOciRepositoryName ,
33+
34+ #[ snafu( display( "cannot resolve path segments" ) ) ]
35+ GetPathSegments ,
36+
37+ #[ snafu( display( "failed to parse URL" ) ) ]
38+ UrlParse { source : url:: ParseError } ,
3239}
3340
3441/// Identifies an operator-specific root folder in the repository e.g.
@@ -70,6 +77,46 @@ pub struct Artifact {
7077 pub tags : Option < Vec < Tag > > ,
7178}
7279
80+ trait OciUrlExt {
81+ fn oci_artifacts_page (
82+ & self ,
83+ project_name : & str ,
84+ repository_name : & str ,
85+ page_size : usize ,
86+ page : usize ,
87+ ) -> Result < Url , Error > ;
88+ }
89+
90+ impl OciUrlExt for Url {
91+ fn oci_artifacts_page (
92+ & self ,
93+ project_name : & str ,
94+ repository_name : & str ,
95+ page_size : usize ,
96+ page : usize ,
97+ ) -> Result < Url , Error > {
98+ let encoded_project = encode ( project_name) ;
99+ let encoded_repo = encode ( repository_name) ;
100+
101+ let mut url = self . clone ( ) ;
102+ url. path_segments_mut ( )
103+ . map_err ( |_| Error :: GetPathSegments ) ?
104+ . extend ( & [
105+ "projects" ,
106+ & encoded_project,
107+ "repositories" ,
108+ & encoded_repo,
109+ "artifacts" ,
110+ ] ) ;
111+
112+ url. query_pairs_mut ( )
113+ . append_pair ( "page_size" , & page_size. to_string ( ) )
114+ . append_pair ( "page" , & page. to_string ( ) ) ;
115+
116+ Ok ( url)
117+ }
118+ }
119+
73120pub async fn get_oci_index < ' a > ( ) -> Result < HashMap < & ' a str , ChartSourceMetadata > , Error > {
74121 let mut source_index_files: HashMap < & str , ChartSourceMetadata > = HashMap :: new ( ) ;
75122
@@ -121,15 +168,9 @@ pub async fn get_oci_index<'a>() -> Result<HashMap<&'a str, ChartSourceMetadata>
121168 let mut page = 1 ;
122169
123170 loop {
124- let url = format ! (
125- "{}/projects/{}/repositories/{}/artifacts?page_size={}&page={}" ,
126- base_url,
127- encode( project_name) ,
128- encode( repository_name) ,
129- OCI_INDEX_PAGE_SIZE ,
130- page
131- ) ;
132-
171+ let root = Url :: parse ( base_url. as_str ( ) ) . context ( UrlParseSnafu ) ?;
172+ let url =
173+ root. oci_artifacts_page ( project_name, repository_name, OCI_INDEX_PAGE_SIZE , page) ?;
133174 let artifacts_page = client
134175 . get ( url)
135176 . send ( )
@@ -138,7 +179,6 @@ pub async fn get_oci_index<'a>() -> Result<HashMap<&'a str, ChartSourceMetadata>
138179 . json :: < Vec < Artifact > > ( )
139180 . await
140181 . context ( ParseArtifactsSnafu ) ?;
141-
142182 let count = artifacts_page. len ( ) ;
143183 artifacts. extend ( artifacts_page) ;
144184 if count < OCI_INDEX_PAGE_SIZE {
0 commit comments