diff options
Diffstat (limited to '')
| -rw-r--r-- | pkgs/by-name/ro/rollup/package.unstable.nix | 3 | ||||
| -rw-r--r-- | pkgs/by-name/ro/rollup/src/main.rs | 107 |
2 files changed, 86 insertions, 24 deletions
diff --git a/pkgs/by-name/ro/rollup/package.unstable.nix b/pkgs/by-name/ro/rollup/package.unstable.nix index eabb701a..2fdc7f52 100644 --- a/pkgs/by-name/ro/rollup/package.unstable.nix +++ b/pkgs/by-name/ro/rollup/package.unstable.nix @@ -13,6 +13,7 @@ git, patchutils, makeWrapper, + mktemp, }: rustPlatform.buildRustPackage (finalAttrs: { pname = "rollup"; @@ -30,7 +31,7 @@ rustPlatform.buildRustPackage (finalAttrs: { postInstall = '' wrapProgram $out/bin/rollup \ - --set PATH ${lib.makeBinPath [git patchutils]} + --set PATH ${lib.makeBinPath [git patchutils mktemp]} ''; meta = { diff --git a/pkgs/by-name/ro/rollup/src/main.rs b/pkgs/by-name/ro/rollup/src/main.rs index 71a54049..cd205586 100644 --- a/pkgs/by-name/ro/rollup/src/main.rs +++ b/pkgs/by-name/ro/rollup/src/main.rs @@ -1,11 +1,12 @@ use std::{ + env::current_dir, io::Write, path::PathBuf, process::{Command, Stdio}, }; use anyhow::{Context, Result, bail}; -use clap::Parser; +use clap::{Parser, Subcommand}; use crate::parse::{FileDiff, Patch}; @@ -13,17 +14,33 @@ mod parse; #[derive(Parser)] struct Cli { - /// The file to pull the patch to rollup from. - patch_files: Vec<PathBuf>, + #[command(subcommand)] + subcommand: Cmd, +} + +#[derive(Subcommand)] +enum Cmd { + /// Apply patches to a rollup target. + Apply { + /// The files to pull the patches to rollup from. + patch_files: Vec<PathBuf>, + + /// Which repository to use as a target for the rollup + /// + /// The repository needs to be clean. + #[arg(short, long)] + to: PathBuf, - /// Which repository to use as a target for the rollup - /// - /// Needs to be clean. - #[arg(short, long)] - to: PathBuf, + /// Show debug information related to the parsing of patch files. + #[arg(short, long)] + debug_parse: bool, + }, - #[arg(short, long)] - debug: bool, + /// Create the patch files (based on the given tag) + Create { + #[arg(default_value = "CONFIG_APPLIED")] + tag: String, + }, } macro_rules! git { @@ -81,19 +98,63 @@ macro_rules! git { fn main() -> Result<()> { let args = Cli::parse(); + match args.subcommand { + Cmd::Apply { + patch_files, + to, + debug_parse, + } => apply_patches(patch_files, to, debug_parse)?, + Cmd::Create { tag } => create_patches(tag)?, + } + + Ok(()) +} + +fn create_patches(tag: String) -> Result<()> { + let current_dir = current_dir()?; + + let (stdout, _) = git!(in current_dir; "tag", "--contains", "HEAD", tag.as_str()); + if !stdout.is_empty() { + println!( + "There are no tags to generate. Tag {} already points to HEAD.", + tag + ); + return Ok(()); + } + + let mktemp = Command::new("mktemp") + .args(["-t", "rollup_patches_XXXXXX", "-d"]) + .output() + .context("Failed to run `mktemp -t rollup_patches_XXXXXX -d`")?; + if !mktemp.status.success() { + bail!("Failed to generate temp-directory for generated patches."); + } + + let tempdir = PathBuf::from(String::from_utf8(mktemp.stdout).unwrap().trim()); + + git!(in current_dir; "format-patch", format!("{}..", tag).as_str(), "-o", tempdir.display().to_string().as_str()); + git!(in current_dir; "tag", "--delete", tag.as_str()); + git!(in current_dir; "tag", "--annotate", tag.as_str(), "-m", ""); + + println!("Patches have been generated here: `{}`", tempdir.display()); + + Ok(()) +} + +fn apply_patches(patch_files: Vec<PathBuf>, to: PathBuf, debug_parse: bool) -> Result<()> { let mut patches = vec![]; - for file in &args.patch_files { - patches.push(parse::parse_file(file, args.debug)?); + for file in &patch_files { + patches.push(parse::parse_file(file, debug_parse)?); } eprintln!("Successfully parsed all {} patch files.", patches.len()); { - let (stdout, _) = git!(in args.to; "status", "--porcelain"); + let (stdout, _) = git!(in to; "status", "--porcelain"); if !stdout.is_empty() { bail!( "`--to` (`{}`) workspace is dirty, refusing to continue.", - args.to.display() + to.display() ); } } @@ -102,21 +163,21 @@ fn main() -> Result<()> { eprintln!( "Applying {}. patch: `{}`... ", idx + 1, - args.patch_files[idx].display() + patch_files[idx].display() ); let mut final_diffs = vec![]; for file_diff in &patch.files { match file_diff { FileDiff::Add { path, .. } => { - if args.to.join(path).exists() { + if to.join(path).exists() { bail!("A file was added, that already existed. This should be impossible.") } final_diffs.push(file_diff.to_owned()); // eprintln!(" > Keeping add of `{}`", path.display()); } FileDiff::Remove { path, .. } => { - if args.to.join(path).exists() { + if to.join(path).exists() { final_diffs.push(file_diff.to_owned()); // eprintln!(" > Keeping remove of `{}`", path.display()); } else { @@ -128,8 +189,8 @@ fn main() -> Result<()> { } FileDiff::RenameNoChange { from, to, .. } | FileDiff::RenameWithChange { from, to, .. } => { - if args.to.join(from).exists() { - if args.to.join(to).exists() { + if to.join(from).exists() { + if to.join(to).exists() { bail!( "A rename (`{}` -> `{}`) tried to rename a path to an already existing path. This should be impossible.", from.display(), @@ -147,7 +208,7 @@ fn main() -> Result<()> { } } FileDiff::Change { path, .. } => { - if args.to.join(path).exists() { + if to.join(path).exists() { final_diffs.push(file_diff.to_owned()); } else { eprintln!( @@ -169,9 +230,9 @@ fn main() -> Result<()> { ..patch.to_owned() }; - git!(@set_stdin_to filtered_patch; in args.to; "apply", "-", "--whitespace=nowarn"); - git!(in args.to; "add", "."); - git!(@set_stdin_to filtered_patch.commit_message; in args.to; "commit", "--file=-", format!("--date={}", filtered_patch.date).as_str(), "--quiet"); + git!(@set_stdin_to filtered_patch; in to; "apply", "-", "--whitespace=nowarn"); + git!(in to; "add", "."); + git!(@set_stdin_to filtered_patch.commit_message; in to; "commit", "--file=-", format!("--date={}", filtered_patch.date).as_str(), "--quiet"); } Ok(()) |
