pesde/src/cli/commands/patch.rs
daimond113 6856746ae2
refactor: crate optimizations
Replaces chrono with jiff (already used due to
gix). Switches from the async-io to the tokio
feature in keyring. Removes dependency on
serde-with. Optimizes release mode executable
size by using aborting panics.
2025-02-02 00:17:11 +01:00

87 lines
2.1 KiB
Rust

use std::sync::Arc;
use crate::cli::{
style::{CLI_STYLE, INFO_STYLE, WARN_PREFIX},
up_to_date_lockfile, VersionedPackageName,
};
use anyhow::Context;
use clap::Args;
use console::style;
use fs_err::tokio as fs;
use pesde::{
patches::setup_patches_repo,
source::{
refs::PackageRefs,
traits::{DownloadOptions, PackageRef, PackageSource},
},
Project, MANIFEST_FILE_NAME,
};
#[derive(Debug, Args)]
pub struct PatchCommand {
/// The package name to patch
#[arg(index = 1)]
package: VersionedPackageName,
}
impl PatchCommand {
pub async fn run(self, project: Project, reqwest: reqwest::Client) -> anyhow::Result<()> {
let graph = if let Some(lockfile) = up_to_date_lockfile(&project).await? {
lockfile.graph
} else {
anyhow::bail!("outdated lockfile, please run the install command first")
};
let id = self.package.get(&graph)?;
let node = graph.get(&id).context("package not found in graph")?;
if matches!(
node.pkg_ref,
PackageRefs::Workspace(_) | PackageRefs::Path(_)
) {
anyhow::bail!("cannot patch a workspace or a path package")
}
let source = node.pkg_ref.source();
let directory = project
.data_dir()
.join("patches")
.join(id.name().escaped())
.join(id.version_id().escaped())
.join(jiff::Timestamp::now().as_second().to_string());
fs::create_dir_all(&directory).await?;
source
.download(
&node.pkg_ref,
&DownloadOptions {
project: project.clone(),
reqwest,
reporter: Arc::new(()),
id: Arc::new(id),
},
)
.await?
.write_to(&directory, project.cas_dir(), false)
.await
.context("failed to write package contents")?;
setup_patches_repo(&directory)?;
println!(
r#"done! modify the files in the directory, then run {} {}{} to apply.
{WARN_PREFIX}: do not commit these changes
{}: the {MANIFEST_FILE_NAME} file will be ignored when patching"#,
CLI_STYLE.apply_to(concat!("`", env!("CARGO_BIN_NAME"), " patch-commit")),
style(format!("'{}'", directory.display())).cyan().bold(),
CLI_STYLE.apply_to("`"),
INFO_STYLE.apply_to("note")
);
open::that(directory)?;
Ok(())
}
}