From 0f1150093bdb7c9a5b723eb352e236de195120a2 Mon Sep 17 00:00:00 2001 From: UnownPlain <38232575+UnownPlain@users.noreply.github.com> Date: Sun, 9 Feb 2025 17:47:34 -0500 Subject: [PATCH 1/2] Add `replace` update option --- src/commands/update_version.rs | 23 +++++++++++++++++++++++ src/github/github_client.rs | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/commands/update_version.rs b/src/commands/update_version.rs index 25df885b..d9557540 100644 --- a/src/commands/update_version.rs +++ b/src/commands/update_version.rs @@ -83,6 +83,10 @@ pub struct UpdateVersion { #[arg(long, env = "DRY_RUN")] dry_run: bool, + /// Package version to replace + #[arg(short, long, num_args = 0..=1, default_missing_value = "latest")] + replace: Option, + /// GitHub personal access token with the `public_repo` scope #[arg(short, long, env = "GITHUB_TOKEN")] token: Option, @@ -107,6 +111,24 @@ impl UpdateVersion { self.package_identifier ); + let mut replace = match self.replace.clone() { + Some(version) if version.to_string() == "latest" => Some(latest_version.clone()), + other => other, + }; + + if let Some(ref replace_version) = replace { + if !versions.iter().any(|v| v == replace_version) { + return Err(color_eyre::eyre::eyre!( + "Replacement version '{}' not found.", + replace_version + )); + } + } + + if replace.as_ref() == Some(&self.package_version) { + replace = None; + } + if let Some(pull_request) = existing_pr.await? { if !self.dry_run && !prompt_existing_pull_request( @@ -250,6 +272,7 @@ impl UpdateVersion { .version(&self.package_version) .versions(&versions) .changes(changes) + .maybe_replace(replace) .maybe_issue_resolves(self.resolves) .maybe_created_with(self.created_with) .maybe_created_with_url(self.created_with_url) diff --git a/src/github/github_client.rs b/src/github/github_client.rs index 4d3f5bed..0f63c5b2 100644 --- a/src/github/github_client.rs +++ b/src/github/github_client.rs @@ -788,6 +788,7 @@ impl GitHub { issue_resolves: Option>, created_with: Option, created_with_url: Option, + replace: Option, ) -> Result { let current_user = self.get_username(); let winget_pkgs = self.get_winget_pkgs().send().await?; @@ -799,6 +800,24 @@ impl GitHub { .await?; let commit_title = get_commit_title(identifier, version, &UpdateState::get(version, versions)); + let directory_content = self + .get_directory_content( + ¤t_user, + &branch_name, + &get_package_path(identifier, replace.as_ref(), None), + ) + .await? + .collect::>(); + let deletions = if replace.is_some() { + Some( + directory_content + .iter() + .map(|s| FileDeletion { path: s.as_str() }) + .collect::>(), + ) + } else { + None + }; let changes = changes .iter() .map(|(path, content)| FileAddition { @@ -812,6 +831,7 @@ impl GitHub { .head_sha(pull_request_branch.target.map(|target| target.oid).unwrap()) .message(&commit_title) .additions(changes) + .maybe_deletions(deletions) .send() .await?; self.create_pull_request( From 1ae181d1eca42b9574da1bbfe9d8c202a0383c96 Mon Sep 17 00:00:00 2001 From: Russell Banks <74878137+russellbanks@users.noreply.github.com> Date: Mon, 10 Feb 2025 00:33:44 +0000 Subject: [PATCH 2/2] Cleanup --- Cargo.lock | 12 +++++++ Cargo.toml | 1 + src/commands/update_version.rs | 31 ++++++++--------- src/github/github_client.rs | 54 +++++++++++++---------------- src/github/graphql/create_commit.rs | 16 +++++---- src/types/version.rs | 6 ++++ 6 files changed, 68 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ccaf88e..95bdddd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1191,6 +1191,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -2469,6 +2480,7 @@ dependencies = [ "crossterm 0.28.1", "cynic", "cynic-codegen", + "derive-new", "derive_more", "encoding_rs", "flate2", diff --git a/Cargo.toml b/Cargo.toml index 7ae6cd2a..9e273a68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,7 @@ const_format = { version = "0.2.34", features = ["derive"] } crc32fast = "1.4.2" crossterm = "0.28.1" cynic = { version = "3.9.1", features = ["http-reqwest"] } +derive-new = "0.7.0" derive_more = { version = "2.0.1", features = ["as_ref", "constructor", "debug", "deref", "deref_mut", "display", "from_str", "into_iterator"] } encoding_rs = "0.8.35" flate2 = "1.0.35" diff --git a/src/commands/update_version.rs b/src/commands/update_version.rs index d9557540..dafb6e23 100644 --- a/src/commands/update_version.rs +++ b/src/commands/update_version.rs @@ -6,7 +6,7 @@ use std::num::{NonZeroU32, NonZeroU8}; use anstream::println; use camino::Utf8PathBuf; use clap::Parser; -use color_eyre::eyre::Result; +use color_eyre::eyre::{bail, Result}; use indicatif::ProgressBar; use owo_colors::OwoColorize; use reqwest::Client; @@ -111,24 +111,23 @@ impl UpdateVersion { self.package_identifier ); - let mut replace = match self.replace.clone() { - Some(version) if version.to_string() == "latest" => Some(latest_version.clone()), - other => other, - }; + let replace_version = self + .replace + .as_ref() + .map(|version| { + version + .is_latest() + .then_some(latest_version) + .unwrap_or(version) + }) + .filter(|&version| version != &self.package_version); - if let Some(ref replace_version) = replace { - if !versions.iter().any(|v| v == replace_version) { - return Err(color_eyre::eyre::eyre!( - "Replacement version '{}' not found.", - replace_version - )); + if let Some(version) = replace_version { + if !versions.contains(version) { + bail!("Replacement version {version} does not exist in {WINGET_PKGS_FULL_NAME}") } } - if replace.as_ref() == Some(&self.package_version) { - replace = None; - } - if let Some(pull_request) = existing_pr.await? { if !self.dry_run && !prompt_existing_pull_request( @@ -272,7 +271,7 @@ impl UpdateVersion { .version(&self.package_version) .versions(&versions) .changes(changes) - .maybe_replace(replace) + .maybe_replace_version(replace_version) .maybe_issue_resolves(self.resolves) .maybe_created_with(self.created_with) .maybe_created_with_url(self.created_with_url) diff --git a/src/github/github_client.rs b/src/github/github_client.rs index 0f63c5b2..8b1f8be3 100644 --- a/src/github/github_client.rs +++ b/src/github/github_client.rs @@ -56,7 +56,7 @@ use crate::types::urls::publisher_url::PublisherUrl; use crate::types::urls::release_notes_url::ReleaseNotesUrl; use crate::types::urls::url::DecodedUrl; use crate::update_state::UpdateState; -use base64ct::Encoding; +use base64ct::{Base64, Encoding}; use bon::bon; use const_format::{formatcp, str_repeat}; use cynic::http::{CynicReqwestError, ReqwestExt}; @@ -734,17 +734,14 @@ impl GitHub { ) .await?; let commit_title = get_commit_title(identifier, version, &UpdateState::RemoveVersion); - let directory_content = self + let deletions = self .get_directory_content( fork_owner, &branch_name, &get_package_path(identifier, Some(version), None), ) .await? - .collect::>(); - let deletions = directory_content - .iter() - .map(|path| FileDeletion { path }) + .map(|path| FileDeletion::new(path)) .collect::>(); let _commit_url = self .create_commit() @@ -785,10 +782,10 @@ impl GitHub { version: &PackageVersion, versions: Option<&BTreeSet>, changes: Vec<(String, String)>, + replace_version: Option<&PackageVersion>, issue_resolves: Option>, created_with: Option, created_with_url: Option, - replace: Option, ) -> Result { let current_user = self.get_username(); let winget_pkgs = self.get_winget_pkgs().send().await?; @@ -800,37 +797,34 @@ impl GitHub { .await?; let commit_title = get_commit_title(identifier, version, &UpdateState::get(version, versions)); - let directory_content = self - .get_directory_content( - ¤t_user, - &branch_name, - &get_package_path(identifier, replace.as_ref(), None), - ) - .await? - .collect::>(); - let deletions = if replace.is_some() { - Some( - directory_content - .iter() - .map(|s| FileDeletion { path: s.as_str() }) - .collect::>(), - ) - } else { - None - }; - let changes = changes + let additions = changes .iter() - .map(|(path, content)| FileAddition { - contents: Base64String::new(base64ct::Base64::encode_string(content.as_bytes())), - path, + .map(|(path, content)| { + FileAddition::new( + Base64String::new(Base64::encode_string(content.as_bytes())), + path, + ) }) .collect::>(); + let mut deletions = None; + if replace_version.is_some() { + deletions = Some( + self.get_directory_content( + ¤t_user, + &branch_name, + &get_package_path(identifier, replace_version, None), + ) + .await? + .map(|path| FileDeletion::new(path)) + .collect::>(), + ) + } let _commit_url = self .create_commit() .branch_id(&pull_request_branch.id) .head_sha(pull_request_branch.target.map(|target| target.oid).unwrap()) .message(&commit_title) - .additions(changes) + .additions(additions) .maybe_deletions(deletions) .send() .await?; diff --git a/src/github/graphql/create_commit.rs b/src/github/graphql/create_commit.rs index eebff8da..41904e9c 100644 --- a/src/github/graphql/create_commit.rs +++ b/src/github/graphql/create_commit.rs @@ -1,5 +1,7 @@ use crate::github::graphql::github_schema::github_schema as schema; use crate::github::graphql::types::{Base64String, GitObjectId}; +use derive_new::new; +use std::borrow::Cow; use url::Url; #[derive(cynic::QueryVariables)] @@ -46,16 +48,18 @@ pub struct FileChanges<'a> { } /// -#[derive(cynic::InputObject)] -pub struct FileDeletion<'a> { - pub path: &'a str, +#[derive(cynic::InputObject, new)] +pub struct FileDeletion<'path> { + #[new(into)] + pub path: Cow<'path, str>, } /// -#[derive(cynic::InputObject)] -pub struct FileAddition<'a> { +#[derive(cynic::InputObject, new)] +pub struct FileAddition<'path> { pub contents: Base64String, - pub path: &'a str, + #[new(into)] + pub path: Cow<'path, str>, } /// diff --git a/src/types/version.rs b/src/types/version.rs index 5fca0cc3..4e361fa1 100644 --- a/src/types/version.rs +++ b/src/types/version.rs @@ -57,6 +57,12 @@ impl Version { pub fn as_str(&self) -> &str { &self.raw } + + pub fn is_latest(&self) -> bool { + const LATEST: &str = "latest"; + + self.raw.eq_ignore_ascii_case(LATEST) + } } impl PartialEq for Version {