diff options
Diffstat (limited to '')
| -rw-r--r-- | pkgs/by-name/ro/rollup/src/main.rs | 90 |
1 files changed, 83 insertions, 7 deletions
diff --git a/pkgs/by-name/ro/rollup/src/main.rs b/pkgs/by-name/ro/rollup/src/main.rs index cd205586..ed4e29b4 100644 --- a/pkgs/by-name/ro/rollup/src/main.rs +++ b/pkgs/by-name/ro/rollup/src/main.rs @@ -1,7 +1,8 @@ use std::{ env::current_dir, + fs, io::Write, - path::PathBuf, + path::{Path, PathBuf}, process::{Command, Stdio}, }; @@ -38,9 +39,27 @@ enum Cmd { /// Create the patch files (based on the given tag) Create { + /// Which tag to use to mark the already applied patches. #[arg(default_value = "CONFIG_APPLIED")] tag: String, }, + + /// First create the patches, and then automatically apply them. + CreateApply { + /// Which tag to use to mark the already applied patches. + #[arg(default_value = "CONFIG_APPLIED")] + tag: String, + + /// Which repository to use as a target for the rollup + /// + /// The repository 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, + }, } macro_rules! git { @@ -59,7 +78,11 @@ macro_rules! git { }; (@_handle_status $output:expr; $($args:expr),*) => {{ if !$output.status.success() { - bail!("{} failed!", git!(@_fmt_cmd $($args),*)) + bail!( + "{} failed!\n\nStderr was:\n {}", + git!(@_fmt_cmd $($args),*), + String::from_utf8($output.stderr).unwrap() + ) } if !$output.stderr.is_empty() { let stderr = String::from_utf8($output.stderr).expect("git should always produce utf8"); @@ -103,14 +126,44 @@ fn main() -> Result<()> { patch_files, to, debug_parse, - } => apply_patches(patch_files, to, debug_parse)?, - Cmd::Create { tag } => create_patches(tag)?, + } => { + check_to(&to)?; + apply_patches(patch_files, to, debug_parse)? + } + Cmd::Create { tag } => { + create_patches(tag)?; + } + Cmd::CreateApply { + tag, + to, + debug_parse, + } => { + check_to(&to)?; + + let Some(patches_directory) = create_patches(tag)? else { + return Ok(()); + }; + let patch_files = { + let iter = fs::read_dir(patches_directory)?; + let mut output = vec![]; + for entry in iter { + let entry = entry?; + if !entry.file_type()?.is_file() { + unreachable!("Should not be able to get non-files in patches directory"); + } + output.push(entry.path()); + } + output.sort(); + output + }; + apply_patches(patch_files, to, debug_parse)?; + } } Ok(()) } -fn create_patches(tag: String) -> Result<()> { +fn create_patches(tag: String) -> Result<Option<PathBuf>> { let current_dir = current_dir()?; let (stdout, _) = git!(in current_dir; "tag", "--contains", "HEAD", tag.as_str()); @@ -119,7 +172,7 @@ fn create_patches(tag: String) -> Result<()> { "There are no tags to generate. Tag {} already points to HEAD.", tag ); - return Ok(()); + return Ok(None); } let mktemp = Command::new("mktemp") @@ -138,7 +191,7 @@ fn create_patches(tag: String) -> Result<()> { println!("Patches have been generated here: `{}`", tempdir.display()); - Ok(()) + Ok(Some(tempdir)) } fn apply_patches(patch_files: Vec<PathBuf>, to: PathBuf, debug_parse: bool) -> Result<()> { @@ -237,3 +290,26 @@ fn apply_patches(patch_files: Vec<PathBuf>, to: PathBuf, debug_parse: bool) -> R Ok(()) } + +fn check_to(to: &Path) -> Result<()> { + let to = to.join(".git"); + + // NOTE: We cannot just try to stat() the path, because landlock might be in use and does not + // currently deny that (tracked in: https://github.com/landlock-lsm/linux/issues/52) <2026-11-09> + // So we instead try to list it. + let is_listable = { + let dir_entries = fs::read_dir(&to).with_context(|| { + format!( + "Failed check regarding `--to` directory (`{}`) readability. Are you in a sandbox?", + to.display() + ) + })?; + dir_entries.count() > 0 + }; + + if !is_listable { + bail!("To directory (`{}`) is not readable", to.display()); + } + + Ok(()) +} |
