From 8f5f71bc4f645c2b30cfd78a4e809edd5343dace Mon Sep 17 00:00:00 2001 From: Wildan M Date: Sat, 9 May 2026 16:28:42 +0700 Subject: [PATCH] Add capture-rev command --- mk/repo.mk | 9 ++++- src/bin/repo.rs | 92 +++++++++++++++++++++++++++++-------------------- src/cook/fs.rs | 12 +++++++ 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/mk/repo.mk b/mk/repo.mk index 7a2a9522..f89687b4 100644 --- a/mk/repo.mk +++ b/mk/repo.mk @@ -281,7 +281,7 @@ cc.%: $(FSTOOLS_TAG) FORCE ifeq ($(PODMAN_BUILD),1) $(PODMAN_RUN) make $@ else - $(REPO_BIN) change-rule --set-rule= $(foreach f,$(subst $(comma), ,$*),$(f)) --with-package-deps + $(REPO_BIN) change-rule --unset $(foreach f,$(subst $(comma), ,$*),$(f)) --with-package-deps endif # Set recipe rule to "binary" then invoke clean and rebuild @@ -294,6 +294,13 @@ scr.%: $(FSTOOLS_TAG) FORCE $(MAKE) sc.$* $(MAKE) r.$*,--with-package-deps +repo-lock: +ifeq ($(PODMAN_BUILD),1) + $(PODMAN_RUN) make $@ +else + $(REPO_BIN) capture-rev $(COOKBOOK_OPTS) --with-package-deps +endif + export DEBUG_BIN?= # Debug a statically linked program with gdbgui, for example: debug.drivers-initfs DEBUG_BIN=pcid diff --git a/src/bin/repo.rs b/src/bin/repo.rs index e8a85a94..51dcb625 100644 --- a/src/bin/repo.rs +++ b/src/bin/repo.rs @@ -2,7 +2,9 @@ use ansi_to_tui::IntoText; use cookbook::config::{CookConfig, CookLockOpt, get_config, init_config}; use cookbook::cook::cook_build::{build, get_stage_dirs, remove_stage_dir}; use cookbook::cook::fetch::{FetchResult, fetch, fetch_offline}; -use cookbook::cook::fs::{create_dir, create_target_dir, remove_all, run_command}; +use cookbook::cook::fs::{ + create_dir, create_target_dir, get_git_commit_date, get_git_head_rev, remove_all, run_command, +}; use cookbook::cook::package::{package, package_handle_push}; use cookbook::cook::pty::{PtyOut, UnixSlavePty, flush_pty, setup_pty, write_to_pty}; use cookbook::cook::script::KILL_ALL_PID; @@ -58,15 +60,15 @@ const REPO_HELP_STR: &str = r#" common flags: --cookbook= the "recipes" folder, default to $PWD/recipes --repo= the "repo" folder, default to $PWD/repo - --sysroot= the "root" folder used for "push" command - For Redox, defaults to "/", else default to $PWD/sysroot --with-package-deps include package deps (always implied in push command) --all apply to all recipes in --category= apply to all recipes in / --filesystem= override recipes config using installer file --repo-binary override recipes config to use repo_binary + --sysroot= used in "push", the "root" dir, default to $PWD/sysroot --set-rule= used in "change-rule", set wanted config rule - --rollback= used in "capture-rev", rollback to a commit instead + --rollback used in "capture-rev", allow git to rollback + --unset used in "capture-rev" and "change-rule", unset locks cook env and their defaults: CI= set to any value to disable TUI @@ -91,8 +93,9 @@ struct CliConfig { logs_dir: Option, category: Option, filesystem: Option, - rollback: Option, set_rule: Option, + unset: bool, + with_rollback: bool, with_package_deps: bool, all: bool, cook: CookConfig, @@ -187,16 +190,13 @@ impl CliConfig { None }, category: None, - sysroot_dir: if cfg!(target_os = "redox") { - PathBuf::from("/") - } else { - current_dir.join("sysroot") - }, + sysroot_dir: current_dir.join("sysroot"), with_package_deps: false, cook: get_config().cook.clone(), all: false, + unset: false, filesystem: None, - rollback: None, + with_rollback: false, set_rule: None, }) } @@ -262,11 +262,8 @@ fn main_inner() -> Result<()> { if command == CliCommand::Push { return handle_push(&recipes, &config); } - if command == CliCommand::ChangeRule { - return handle_change_rule(&recipes, &config); - } - if command == CliCommand::CaptureRev { - return handle_capture_rev(&recipes, &config); + if matches!(command, CliCommand::ChangeRule | CliCommand::CaptureRev) { + return handle_change_rule(&recipes, &config, &command); } let verbose = config.cook.verbose; @@ -454,7 +451,6 @@ fn parse_args(args: Vec) -> Result<(CliConfig, CliCommand, Vec config.sysroot_dir = PathBuf::from(value), "--category" => config.category = Some(PathBuf::from(value)), "--set-rule" => config.set_rule = Some(value.into()), - "--rollback" => config.rollback = Some(value.into()), "--filesystem" => { config.filesystem = Some({ let r = redox_installer::Config::from_file(&PathBuf::from(value)); @@ -470,6 +466,8 @@ fn parse_args(args: Vec) -> Result<(CliConfig, CliCommand, Vec override_filesystem_repo_binary = true, "--with-package-deps" => config.with_package_deps = true, + "--rollback" => config.with_rollback = true, + "--unset" => config.unset = true, "--all" => config.all = true, _ => bail_options_err!("Error: Unknown flag: {}", arg), } @@ -968,53 +966,73 @@ fn handle_tree(recipes: &Vec, is_build_tree: bool, _config: &CliConf Ok(()) } -fn handle_change_rule(recipes: &Vec, config: &CliConfig) -> Result<()> { +fn handle_change_rule( + recipes: &Vec, + config: &CliConfig, + command: &CliCommand, +) -> Result<()> { let mut lock = get_config().recipe_lock.clone(); - let is_pruning = config.set_rule.as_ref().is_some_and(|s| s.is_empty()); + let _cookbook_date = get_git_commit_date(&PathBuf::from("."))?; + let is_change_rule = matches!(command, CliCommand::ChangeRule); + let is_capture_rev = matches!(command, CliCommand::CaptureRev); for recipe in recipes { - if recipe.name.is_host() { + if is_change_rule && recipe.name.is_host() { // host packages will always be "source" so it's pointless to change their rule continue; } + if is_capture_rev && !matches!(recipe.recipe.source, Some(SourceRecipe::Git { .. })) { + continue; + } let recipe_name = recipe.name.without_prefix(); let mut recipe_lock = lock.get(recipe_name).cloned().unwrap_or_default(); - let cached = if is_pruning { - recipe_lock.fsrule.take().is_none() - } else { - let new_rule = config - .set_rule - .as_ref() - .cloned() - .unwrap_or_else(|| recipe.rule.clone()); + let cached = if is_change_rule { + if config.unset { + recipe_lock.fsrule.take().is_none() + } else { + let new_rule = config + .set_rule + .as_ref() + .cloned() + .unwrap_or_else(|| recipe.rule.clone()); - let old_rule = recipe_lock.fsrule.replace(new_rule.clone()); - old_rule == Some(new_rule) + let old_rule = recipe_lock.fsrule.replace(new_rule.clone()); + old_rule == Some(new_rule) + } + } else if is_capture_rev { + if config.unset { + recipe_lock.gitrev.take().is_none() + } else { + if config.with_rollback { + todo!(); + } + let (rev, _) = get_git_head_rev(&recipe.dir.join("source"))?; + let old_rev = recipe_lock.gitrev.replace(rev.clone()); + old_rev == Some(rev) + } + } else { + unreachable!() }; if recipe_lock.is_empty() { lock.remove(recipe_name); } else { lock.insert(recipe_name.to_string(), recipe_lock); } - let clean_cached = if !cached { + let clean_cached = if !cached && is_change_rule { handle_clean(recipe, config, &CliCommand::Clean)? } else { true }; if cached && clean_cached { - print_cached(&CliCommand::ChangeRule, &recipe.name); + print_cached(command, &recipe.name); } else { - print_success(&CliCommand::ChangeRule, &recipe.name); + print_success(command, &recipe.name); } } CookLockOpt { recipes: lock }.save(); Ok(()) } -fn handle_capture_rev(_recipes: &Vec, _config: &CliConfig) -> Result<()> { - todo!() -} - // // ------------- TUI SPECIFIC CODE ------------------- // diff --git a/src/cook/fs.rs b/src/cook/fs.rs index d0711686..c24efa2a 100644 --- a/src/cook/fs.rs +++ b/src/cook/fs.rs @@ -476,3 +476,15 @@ fn get_git_branch_name(local_branch_path: &str) -> Result { ))? .to_string()) } + +pub fn get_git_commit_date(dir: &PathBuf) -> Result { + let mut git = process::Command::new("git"); + git.args(["log", "-1", "--date=iso-strict-local", "--format=%ad"]); + git.env("TZ", "UTC"); + git.current_dir(dir); + git.stdout(Stdio::piped()); + + git.output() + .map_err(wrap_io_err!("Executing git")) + .map(|s| String::from_utf8_lossy(&s.stdout).to_string()) +}