@@ -6,7 +6,8 @@ use console::Term;
66use iroh:: { NodeId , SecretKey } ;
77use iroh_blobs:: {
88 downloader2:: {
9- DownloadRequest , Downloader , ObserveEvent , ObserveRequest , StaticContentDiscovery ,
9+ print_bitmap, DownloadRequest , Downloader , ObserveEvent , ObserveRequest ,
10+ StaticContentDiscovery ,
1011 } ,
1112 store:: Store ,
1213 util:: total_bytes,
@@ -30,7 +31,11 @@ struct DownloadArgs {
3031 #[ clap( help = "hash to download" ) ]
3132 hash : Hash ,
3233
34+ #[ clap( help = "providers to download from" ) ]
3335 providers : Vec < NodeId > ,
36+
37+ #[ clap( long, help = "path to save to" ) ]
38+ path : Option < PathBuf > ,
3439}
3540
3641#[ derive( Debug , Parser ) ]
@@ -139,77 +144,28 @@ impl BlobDownloadProgress {
139144 }
140145}
141146
142- fn bitmap ( current : & [ ChunkNum ] , requested : & [ ChunkNum ] , n : usize ) -> String {
143- // If n is 0, return an empty string.
144- if n == 0 {
145- return String :: new ( ) ;
146- }
147-
148- // Determine the overall bitfield size.
149- // Since the ranges are sorted, we take the last element as the total size.
150- let total = if let Some ( & last) = requested. last ( ) {
151- last. 0
152- } else {
153- // If there are no ranges, we assume the bitfield is empty.
154- 0
155- } ;
156-
157- // If total is 0, output n spaces.
158- if total == 0 {
159- return " " . repeat ( n) ;
160- }
161-
162- let mut result = String :: with_capacity ( n) ;
163-
164- // For each of the n output buckets:
165- for bucket in 0 ..n {
166- // Calculate the bucket's start and end in the overall bitfield.
167- let bucket_start = bucket as u64 * total / n as u64 ;
168- let bucket_end = ( bucket as u64 + 1 ) * total / n as u64 ;
169- let bucket_size = bucket_end. saturating_sub ( bucket_start) ;
170-
171- // Sum the number of bits that are set in this bucket.
172- let mut set_bits = 0u64 ;
173- for pair in current. chunks_exact ( 2 ) {
174- let start = pair[ 0 ] ;
175- let end = pair[ 1 ] ;
176- // Determine the overlap between the bucket and the current range.
177- let overlap_start = start. 0 . max ( bucket_start) ;
178- let overlap_end = end. 0 . min ( bucket_end) ;
179- if overlap_start < overlap_end {
180- set_bits += overlap_end - overlap_start;
181- }
147+ async fn download ( args : DownloadArgs ) -> anyhow:: Result < ( ) > {
148+ match & args. path {
149+ Some ( path) => {
150+ tokio:: fs:: create_dir_all ( path) . await ?;
151+ let store = iroh_blobs:: store:: fs:: Store :: load ( path) . await ?;
152+ // make sure we properly shut down the store on ctrl-c
153+ let res = tokio:: select! {
154+ x = download_impl( args, store. clone( ) ) => x,
155+ _ = tokio:: signal:: ctrl_c( ) => Ok ( ( ) ) ,
156+ } ;
157+ store. shutdown ( ) . await ;
158+ res
159+ }
160+ None => {
161+ let store = iroh_blobs:: store:: mem:: Store :: new ( ) ;
162+ download_impl ( args, store) . await
182163 }
183-
184- // Calculate the fraction of the bucket that is set.
185- let fraction = if bucket_size > 0 {
186- set_bits as f64 / bucket_size as f64
187- } else {
188- 0.0
189- } ;
190-
191- // Map the fraction to a grayscale character.
192- let ch = if fraction == 0.0 {
193- ' ' // completely empty
194- } else if fraction == 1.0 {
195- '█' // completely full
196- } else if fraction < 0.25 {
197- '░'
198- } else if fraction < 0.5 {
199- '▒'
200- } else {
201- '▓'
202- } ;
203-
204- result. push ( ch) ;
205164 }
206-
207- result
208165}
209166
210- async fn download ( args : DownloadArgs ) -> anyhow:: Result < ( ) > {
167+ async fn download_impl < S : Store > ( args : DownloadArgs , store : S ) -> anyhow:: Result < ( ) > {
211168 let endpoint = iroh:: Endpoint :: builder ( ) . discovery_n0 ( ) . bind ( ) . await ?;
212- let store = iroh_blobs:: store:: mem:: Store :: new ( ) ;
213169 let discovery = StaticContentDiscovery :: new ( Default :: default ( ) , args. providers ) ;
214170 let downloader = Downloader :: builder ( endpoint, store)
215171 . discovery ( discovery)
@@ -233,7 +189,7 @@ async fn download(args: DownloadArgs) -> anyhow::Result<()> {
233189 progress. update ( chunk) ;
234190 let current = progress. current . boundaries ( ) ;
235191 let requested = progress. request . ranges . boundaries ( ) ;
236- let bitmap = bitmap ( current, requested, rows as usize ) ;
192+ let bitmap = print_bitmap ( current, requested, rows as usize ) ;
237193 print ! ( "\r {bitmap}" ) ;
238194 if progress. is_done ( ) {
239195 println ! ( ) ;
0 commit comments