@@ -28,13 +28,24 @@ struct GetBlobOpts {
2828 size : u64 ,
2929}
3030
31+ #[ derive( clap:: Parser , Debug ) ]
32+ struct FetchContainerToDevNullOpts {
33+ #[ clap( flatten) ]
34+ metaopts : GetMetadataOpts ,
35+
36+ /// Use the "raw" path for fetching blobs
37+ #[ clap( long) ]
38+ raw_blobs : bool ,
39+ }
40+
3141/// Simple program to greet a person
3242#[ derive( clap:: Parser , Debug ) ]
3343#[ command( version, about, long_about = None ) ]
3444enum Opt {
3545 GetMetadata ( GetMetadataOpts ) ,
3646 GetBlob ( GetBlobOpts ) ,
37- FetchContainerToDevNull ( GetMetadataOpts ) ,
47+ GetBlobRaw ( GetBlobOpts ) ,
48+ FetchContainerToDevNull ( FetchContainerToDevNullOpts ) ,
3849}
3950
4051#[ derive( serde:: Serialize , Debug ) ]
@@ -86,18 +97,49 @@ async fn get_blob(o: GetBlobOpts) -> Result<()> {
8697 Ok ( ( ) )
8798}
8899
89- async fn fetch_container_to_devnull ( o : GetMetadataOpts ) -> Result < ( ) > {
90- let config = o. proxy_opts ( ) ;
100+ async fn get_blob_raw ( o : GetBlobOpts ) -> Result < ( ) > {
101+ let proxy = containers_image_proxy:: ImageProxy :: new ( ) . await ?;
102+ let img = proxy. open_image ( & o. reference ) . await ?;
103+ let ( _, mut datafd, err) = proxy. get_raw_blob ( & img, & o. digest ) . await ?;
104+
105+ let mut stdout = std:: io:: stdout ( ) . lock ( ) ;
106+ let reader = async move {
107+ let mut buffer = [ 0u8 ; 8192 ] ;
108+ loop {
109+ let n = datafd. read ( & mut buffer) . await ?;
110+ if n == 0 {
111+ return anyhow:: Ok ( ( ) ) ;
112+ }
113+ stdout. write_all ( & buffer[ ..n] ) ?;
114+ }
115+ } ;
116+
117+ let ( a, b) = tokio:: join!( reader, err) ;
118+ a?;
119+ b?;
120+ Ok ( ( ) )
121+ }
122+
123+ async fn fetch_container_to_devnull ( o : FetchContainerToDevNullOpts ) -> Result < ( ) > {
124+ let config = o. metaopts . proxy_opts ( ) ;
91125 let proxy = containers_image_proxy:: ImageProxy :: new_with_config ( config) . await ?;
92- let img = & proxy. open_image ( & o. reference ) . await ?;
126+ let img = & proxy. open_image ( & o. metaopts . reference ) . await ?;
93127 let manifest = proxy. fetch_manifest ( img) . await ?. 1 ;
94128 for layer in manifest. layers ( ) {
95- let ( mut blob, driver) = proxy. get_descriptor ( img, layer) . await ?;
96129 let mut devnull = tokio:: io:: sink ( ) ;
97- let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
98- let ( copier, driver) = tokio:: join!( copier, driver) ;
99- copier?;
100- driver?;
130+ if o. raw_blobs {
131+ let ( _, mut blob, err) = proxy. get_raw_blob ( img, layer. digest ( ) ) . await ?;
132+ let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
133+ let ( copier, err) = tokio:: join!( copier, err) ;
134+ copier?;
135+ err?;
136+ } else {
137+ let ( mut blob, driver) = proxy. get_descriptor ( img, layer) . await ?;
138+ let copier = tokio:: io:: copy ( & mut blob, & mut devnull) ;
139+ let ( copier, driver) = tokio:: join!( copier, driver) ;
140+ copier?;
141+ driver?;
142+ }
101143 }
102144 Ok ( ( ) )
103145}
@@ -106,6 +148,7 @@ async fn run() -> Result<()> {
106148 match Opt :: parse ( ) {
107149 Opt :: GetMetadata ( o) => get_metadata ( o) . await ,
108150 Opt :: GetBlob ( o) => get_blob ( o) . await ,
151+ Opt :: GetBlobRaw ( o) => get_blob_raw ( o) . await ,
109152 Opt :: FetchContainerToDevNull ( o) => fetch_container_to_devnull ( o) . await ,
110153 }
111154}
0 commit comments