Add capture-rev command

This commit is contained in:
Wildan M 2026-05-09 16:28:42 +07:00
parent 676f32572d
commit 8f5f71bc4f
No known key found for this signature in database
GPG Key ID: 01AC53185C679C79
3 changed files with 75 additions and 38 deletions

View File

@ -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

View File

@ -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=<cookbook_dir> the "recipes" folder, default to $PWD/recipes
--repo=<repo_dir> the "repo" folder, default to $PWD/repo
--sysroot=<sysroot_dir> 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 <cookbook_dir>
--category=<category> apply to all recipes in <cookbook_dir>/<category>
--filesystem=<filesystem> override recipes config using installer file
--repo-binary override recipes config to use repo_binary
--sysroot=<sysroot_dir> used in "push", the "root" dir, default to $PWD/sysroot
--set-rule=<rule> used in "change-rule", set wanted config rule
--rollback=<rev> 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<PathBuf>,
category: Option<PathBuf>,
filesystem: Option<redox_installer::Config>,
rollback: Option<String>,
set_rule: Option<String>,
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<String>) -> Result<(CliConfig, CliCommand, Vec<CookRecip
"--sysroot" => 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<String>) -> Result<(CliConfig, CliCommand, Vec<CookRecip
match arg.as_str() {
"--repo-binary" => 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<CookRecipe>, is_build_tree: bool, _config: &CliConf
Ok(())
}
fn handle_change_rule(recipes: &Vec<CookRecipe>, config: &CliConfig) -> Result<()> {
fn handle_change_rule(
recipes: &Vec<CookRecipe>,
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<CookRecipe>, _config: &CliConfig) -> Result<()> {
todo!()
}
//
// ------------- TUI SPECIFIC CODE -------------------
//

View File

@ -476,3 +476,15 @@ fn get_git_branch_name(local_branch_path: &str) -> Result<String> {
))?
.to_string())
}
pub fn get_git_commit_date(dir: &PathBuf) -> Result<String> {
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())
}