Skip to content

Commit 0e502c5

Browse files
committed
squash: feat/new-from-files
1 parent 7518460 commit 0e502c5

3 files changed

Lines changed: 92 additions & 14 deletions

File tree

src/commands/new_version.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use std::{
55
};
66

77
use anstream::println;
8-
use camino::Utf8PathBuf;
8+
use camino::{Utf8Path, Utf8PathBuf};
99
use clap::Parser;
1010
use color_eyre::eyre::Result;
11+
use color_eyre::eyre::ensure;
1112
use indicatif::ProgressBar;
1213
use inquire::CustomType;
1314
use ordinal::Ordinal;
@@ -34,7 +35,7 @@ use crate::{
3435
commands::utils::{
3536
SPINNER_TICK_RATE, SubmitOption, prompt_existing_pull_request, write_changes_to_dir,
3637
},
37-
download::Downloader,
38+
download::{DownloadedFile, Downloader},
3839
download_file::process_files,
3940
github::{
4041
GITHUB_HOST, WINGET_PKGS_FULL_NAME,
@@ -67,6 +68,10 @@ pub struct NewVersion {
6768
#[arg(short, long, num_args = 1.., value_hint = clap::ValueHint::Url)]
6869
urls: Vec<Url>,
6970

71+
/// The list of files to use instead of downloading urls
72+
#[arg(short, long, num_args = 1.., value_hint = clap::ValueHint::FilePath, requires = "urls", value_parser = is_valid_file)]
73+
files: Vec<Utf8PathBuf>,
74+
7075
#[arg(long)]
7176
package_locale: Option<LanguageTag>,
7277

@@ -155,6 +160,15 @@ pub struct NewVersion {
155160

156161
impl NewVersion {
157162
pub async fn run(self) -> Result<()> {
163+
if !self.files.is_empty() {
164+
ensure!(
165+
self.urls.len() == self.files.len(),
166+
"Number of URLs ({}) must match number of files ({})",
167+
self.urls.len(),
168+
self.files.len()
169+
);
170+
}
171+
158172
let token = TokenManager::handle(self.token).await?;
159173
let github = GitHub::new(&token)?;
160174

@@ -219,20 +233,27 @@ impl NewVersion {
219233
}
220234
});
221235

222-
let downloader = Downloader::new_with_concurrent(self.concurrent_downloads)?;
223-
let mut files = downloader.download(urls.iter().cloned()).await?;
236+
let mut files = if self.files.is_empty() {
237+
let downloader = Downloader::new_with_concurrent(self.concurrent_downloads)?;
238+
downloader.download(urls.iter().cloned()).await?
239+
} else {
240+
self.files
241+
.iter()
242+
.zip(urls.iter().cloned())
243+
.map(|(path, url)| DownloadedFile::from_local(path, url))
244+
.collect::<Result<Vec<_>>>()?
245+
};
246+
224247
let mut download_results = process_files(&mut files).await?;
225248

226249
let mut installers = Vec::new();
227250
for analyser in &mut download_results.values_mut() {
228251
let mut silent = None;
229252
let mut silent_with_progress = None;
230253
let mut custom = None;
231-
if analyser
232-
.installers
233-
.iter()
234-
.any(|installer| installer.r#type == Some(InstallerType::Exe))
235-
{
254+
if analyser.installers.iter().any(|installer| {
255+
installer.r#type == Some(InstallerType::Exe) && installer.switches.is_empty()
256+
}) {
236257
if confirm_prompt(&format!("Is {} a portable exe?", analyser.file_name))? {
237258
for installer in &mut analyser.installers {
238259
installer.r#type = Some(InstallerType::Portable);
@@ -480,3 +501,10 @@ impl NewVersion {
480501
Ok(())
481502
}
482503
}
504+
505+
fn is_valid_file(path: &str) -> Result<Utf8PathBuf> {
506+
let path = Utf8Path::new(path);
507+
ensure!(path.exists(), "{path} does not exist");
508+
ensure!(path.is_file(), "{path} is not a file");
509+
Ok(path.to_path_buf())
510+
}

src/commands/update_version.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use std::{
66
};
77

88
use anstream::println;
9-
use camino::Utf8PathBuf;
9+
use camino::{Utf8Path, Utf8PathBuf};
1010
use clap::Parser;
11-
use color_eyre::eyre::{Error, Result, bail};
11+
use color_eyre::eyre::{Error, Result, bail, ensure};
1212
use futures_util::TryFutureExt;
1313
use indicatif::ProgressBar;
1414
use 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

108112
impl 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+
}

src/download/file.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::fs::File;
22

3+
use camino::Utf8Path;
34
use chrono::NaiveDate;
5+
use color_eyre::eyre::Result;
46
use memmap2::Mmap;
7+
use sha2::{Digest, Sha256};
58
use winget_types::Sha256String;
69

710
use crate::manifests::Url;
@@ -18,3 +21,20 @@ pub struct DownloadedFile {
1821
pub file_name: String,
1922
pub last_modified: Option<NaiveDate>,
2023
}
24+
25+
impl DownloadedFile {
26+
pub fn from_local(path: &Utf8Path, url: Url) -> Result<Self> {
27+
let file = File::open(path)?;
28+
let mmap = unsafe { Mmap::map(&file) }?;
29+
let sha_256 = Sha256String::from_digest(&Sha256::digest(&mmap));
30+
let file_name = path.file_name().unwrap_or_else(|| path.as_str()).to_owned();
31+
Ok(Self {
32+
file,
33+
url,
34+
mmap,
35+
sha_256,
36+
file_name,
37+
last_modified: None,
38+
})
39+
}
40+
}

0 commit comments

Comments
 (0)