@@ -6,9 +6,9 @@ use std::{
66} ;
77
88use anstream:: println;
9- use camino:: Utf8PathBuf ;
9+ use camino:: { Utf8Path , Utf8PathBuf } ;
1010use clap:: Parser ;
11- use color_eyre:: eyre:: { Error , Result , bail} ;
11+ use color_eyre:: eyre:: { Error , Result , bail, ensure } ;
1212use futures_util:: TryFutureExt ;
1313use indicatif:: ProgressBar ;
1414use owo_colors:: OwoColorize ;
@@ -25,7 +25,7 @@ use crate::{
2525 commands:: utils:: {
2626 SPINNER_TICK_RATE , SubmitOption , prompt_existing_pull_request, write_changes_to_dir,
2727 } ,
28- download:: Downloader ,
28+ download:: { DownloadedFile , Downloader } ,
2929 download_file:: process_files,
3030 github:: {
3131 GITHUB_HOST , GitHubError , WINGET_PKGS_FULL_NAME ,
@@ -56,6 +56,10 @@ pub struct UpdateVersion {
5656 #[ arg( short, long, num_args = 1 .., required = true , value_hint = clap:: ValueHint :: Url ) ]
5757 urls : Vec < Url > ,
5858
59+ /// The list of files to use instead of downloading urls
60+ #[ arg( short, long, num_args = 1 .., requires = "urls" , value_parser = is_valid_file, value_hint = clap:: ValueHint :: FilePath ) ]
61+ files : Vec < Utf8PathBuf > ,
62+
5963 /// Number of installers to download at the same time
6064 #[ arg( long, default_value_t = NonZeroUsize :: new( num_cpus:: get( ) ) . unwrap( ) ) ]
6165 concurrent_downloads : NonZeroUsize ,
@@ -107,6 +111,15 @@ pub struct UpdateVersion {
107111
108112impl UpdateVersion {
109113 pub async fn run ( self ) -> Result < ( ) > {
114+ if !self . files . is_empty ( ) {
115+ ensure ! (
116+ self . urls. len( ) == self . files. len( ) ,
117+ "Number of URLs ({}) must match number of files ({})" ,
118+ self . urls. len( ) ,
119+ self . files. len( )
120+ ) ;
121+ }
122+
110123 let token = TokenManager :: handle ( self . token . as_deref ( ) ) . await ?;
111124 let github = GitHub :: new ( & token) ?;
112125
@@ -127,13 +140,23 @@ impl UpdateVersion {
127140 return Ok ( ( ) ) ;
128141 }
129142
130- let downloader = Downloader :: new_with_concurrent ( self . concurrent_downloads ) ?;
131143 let ( mut manifests, mut github_values, mut files) = try_join ! (
132144 github
133145 . get_manifests( & self . package_identifier, latest_version)
134146 . map_err( Error :: new) ,
135147 self . fetch_github_values( & github) . map_err( Error :: new) ,
136- downloader. download( self . urls. iter( ) . cloned( ) ) ,
148+ async {
149+ if self . files. is_empty( ) {
150+ let downloader = Downloader :: new_with_concurrent( self . concurrent_downloads) ?;
151+ downloader. download( self . urls. iter( ) . cloned( ) ) . await
152+ } else {
153+ self . files
154+ . iter( )
155+ . zip( self . urls. iter( ) . cloned( ) )
156+ . map( |( path, url) | DownloadedFile :: from_local( path, url) )
157+ . collect:: <Result <Vec <_>>>( )
158+ }
159+ } ,
137160 ) ?;
138161
139162 let mut download_results = process_files ( & mut files) . await ?;
@@ -385,3 +408,10 @@ fn fix_relative_paths<R: Read + Seek>(
385408 } )
386409 . collect :: < BTreeSet < _ > > ( )
387410}
411+
412+ fn is_valid_file ( path : & str ) -> Result < Utf8PathBuf > {
413+ let path = Utf8Path :: new ( path) ;
414+ ensure ! ( path. exists( ) , "{path} does not exist" ) ;
415+ ensure ! ( path. is_file( ) , "{path} is not a file" ) ;
416+ Ok ( path. to_path_buf ( ) )
417+ }
0 commit comments