mirror of
https://gitlab.redox-os.org/redox-os/redox.git
synced 2026-06-17 15:34:18 +08:00
Merge branch 'change-rule' into 'master'
Implement cookbook lock and change-rule command Closes #1801 See merge request redox-os/redox!2120
This commit is contained in:
commit
953993ac05
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@
|
||||
/repo
|
||||
/web
|
||||
/cookbook.toml
|
||||
/cookbook.lock
|
||||
source
|
||||
source.tmp
|
||||
source-new
|
||||
|
||||
34
mk/repo.mk
34
mk/repo.mk
@ -260,6 +260,40 @@ ucri.%: $(FSTOOLS_TAG) FORCE
|
||||
$(MAKE) i.$*
|
||||
endif
|
||||
|
||||
# Set recipe rule to "binary" then invoke clean
|
||||
bc.%: $(FSTOOLS_TAG) FORCE
|
||||
ifeq ($(PODMAN_BUILD),1)
|
||||
$(PODMAN_RUN) make $@
|
||||
else
|
||||
$(REPO_BIN) change-rule --set-rule=binary $(foreach f,$(subst $(comma), ,$*),$(f))
|
||||
endif
|
||||
|
||||
# Set recipe rule to "source" then invoke clean
|
||||
sc.%: $(FSTOOLS_TAG) FORCE
|
||||
ifeq ($(PODMAN_BUILD),1)
|
||||
$(PODMAN_RUN) make $@
|
||||
else
|
||||
$(REPO_BIN) change-rule --set-rule=source $(foreach f,$(subst $(comma), ,$*),$(f))
|
||||
endif
|
||||
|
||||
# Reset recipe rule then invoke clean
|
||||
cc.%: $(FSTOOLS_TAG) FORCE
|
||||
ifeq ($(PODMAN_BUILD),1)
|
||||
$(PODMAN_RUN) make $@
|
||||
else
|
||||
$(REPO_BIN) change-rule --set-rule= $(foreach f,$(subst $(comma), ,$*),$(f))
|
||||
endif
|
||||
|
||||
# Set recipe rule to "binary" then invoke clean and rebuild
|
||||
bcr.%: $(FSTOOLS_TAG) FORCE
|
||||
$(MAKE) bc.$*
|
||||
$(MAKE) r.$*
|
||||
|
||||
# Set recipe rule to "source" then invoke clean and rebuild
|
||||
scr.%: $(FSTOOLS_TAG) FORCE
|
||||
$(MAKE) sc.$*
|
||||
$(MAKE) r.$*
|
||||
|
||||
export DEBUG_BIN?=
|
||||
|
||||
# Debug a statically linked program with gdbgui, for example: debug.drivers-initfs DEBUG_BIN=pcid
|
||||
|
||||
107
src/bin/repo.rs
107
src/bin/repo.rs
@ -1,5 +1,5 @@
|
||||
use ansi_to_tui::IntoText;
|
||||
use cookbook::config::{CookConfig, get_config, init_config};
|
||||
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};
|
||||
@ -8,7 +8,9 @@ use cookbook::cook::pty::{PtyOut, UnixSlavePty, flush_pty, setup_pty, write_to_p
|
||||
use cookbook::cook::script::KILL_ALL_PID;
|
||||
use cookbook::cook::tree::{self, WalkTreeEntry};
|
||||
use cookbook::cook::{fetch_repo, ident};
|
||||
use cookbook::recipe::{CookRecipe, recipes_flatten_package_names, recipes_mark_as_deps};
|
||||
use cookbook::recipe::{
|
||||
CookRecipe, SourceRecipe, recipes_flatten_package_names, recipes_mark_as_deps,
|
||||
};
|
||||
use cookbook::{Error, Result, staged_pkg};
|
||||
use pkg::{PackageName, PackageState};
|
||||
use ratatui::Terminal;
|
||||
@ -50,7 +52,9 @@ const REPO_HELP_STR: &str = r#"
|
||||
find find path of recipe packages
|
||||
cook-tree show tree of recipe build
|
||||
push-tree show tree of recipe packages
|
||||
|
||||
capture-rev write lock to git recipes
|
||||
change-rule override rule to recipes
|
||||
|
||||
common flags:
|
||||
--cookbook=<cookbook_dir> the "recipes" folder, default to $PWD/recipes
|
||||
--repo=<repo_dir> the "repo" folder, default to $PWD/repo
|
||||
@ -61,6 +65,8 @@ const REPO_HELP_STR: &str = r#"
|
||||
--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
|
||||
--set-rule=<rule> used in "change-rule", set wanted config rule
|
||||
--rollback=<rev> used in "capture-rev", rollback to a commit instead
|
||||
|
||||
cook env and their defaults:
|
||||
CI= set to any value to disable TUI
|
||||
@ -85,6 +91,8 @@ struct CliConfig {
|
||||
logs_dir: Option<PathBuf>,
|
||||
category: Option<PathBuf>,
|
||||
filesystem: Option<redox_installer::Config>,
|
||||
rollback: Option<String>,
|
||||
set_rule: Option<String>,
|
||||
with_package_deps: bool,
|
||||
all: bool,
|
||||
cook: CookConfig,
|
||||
@ -101,6 +109,8 @@ enum CliCommand {
|
||||
Push,
|
||||
PushTree,
|
||||
Find,
|
||||
CaptureRev,
|
||||
ChangeRule,
|
||||
}
|
||||
|
||||
impl CliCommand {
|
||||
@ -108,7 +118,11 @@ impl CliCommand {
|
||||
*self == CliCommand::PushTree || *self == CliCommand::CookTree || *self == CliCommand::Find
|
||||
}
|
||||
pub fn is_building(&self) -> bool {
|
||||
*self == CliCommand::Fetch || *self == CliCommand::Cook || *self == CliCommand::CookTree
|
||||
*self == CliCommand::Fetch
|
||||
|| *self == CliCommand::Cook
|
||||
|| *self == CliCommand::CookTree
|
||||
|| *self == CliCommand::CaptureRev
|
||||
|| *self == CliCommand::ChangeRule
|
||||
}
|
||||
pub fn is_pushing(&self) -> bool {
|
||||
*self == CliCommand::Push || *self == CliCommand::PushTree
|
||||
@ -134,6 +148,8 @@ impl FromStr for CliCommand {
|
||||
"push-tree" => Ok(CliCommand::PushTree),
|
||||
"cook-tree" => Ok(CliCommand::CookTree),
|
||||
"find" => Ok(CliCommand::Find),
|
||||
"capture-rev" => Ok(CliCommand::CaptureRev),
|
||||
"change-rule" => Ok(CliCommand::ChangeRule),
|
||||
_ => bail_options_err!("Unknown command {:?}", s),
|
||||
}
|
||||
}
|
||||
@ -151,6 +167,8 @@ impl ToString for CliCommand {
|
||||
CliCommand::PushTree => "push-tree".to_string(),
|
||||
CliCommand::CookTree => "cook-tree".to_string(),
|
||||
CliCommand::Find => "find".to_string(),
|
||||
CliCommand::CaptureRev => "capture-rev".to_string(),
|
||||
CliCommand::ChangeRule => "change-rule".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,6 +196,8 @@ impl CliConfig {
|
||||
cook: get_config().cook.clone(),
|
||||
all: false,
|
||||
filesystem: None,
|
||||
rollback: None,
|
||||
set_rule: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -242,6 +262,12 @@ 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);
|
||||
}
|
||||
|
||||
let verbose = config.cook.verbose;
|
||||
for recipe in &recipes {
|
||||
@ -386,13 +412,11 @@ fn repo_inner(config: &CliConfig, command: &CliCommand, recipe: &CookRecipe) ->
|
||||
CliCommand::Unfetch | CliCommand::Clean | CliCommand::CleanTarget => {
|
||||
handle_clean(recipe, config, command)?
|
||||
}
|
||||
CliCommand::Push => unreachable!(),
|
||||
CliCommand::PushTree => unreachable!(),
|
||||
CliCommand::CookTree => unreachable!(),
|
||||
CliCommand::Find => {
|
||||
println!("{}", recipe.dir.display());
|
||||
false
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -429,6 +453,8 @@ fn parse_args(args: Vec<String>) -> Result<(CliConfig, CliCommand, Vec<CookRecip
|
||||
"--repo" => config.repo_dir = PathBuf::from(value),
|
||||
"--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));
|
||||
@ -679,6 +705,31 @@ fn parse_args(args: Vec<String>) -> Result<(CliConfig, CliCommand, Vec<CookRecip
|
||||
}
|
||||
};
|
||||
|
||||
if !get_config().recipe_lock.is_empty() {
|
||||
let lock = &get_config().recipe_lock;
|
||||
for recipe in recipes.iter_mut() {
|
||||
if let Some(lock_recipe) = lock.get(recipe.name.as_str()) {
|
||||
if let Some(rule) = &lock_recipe.fsrule {
|
||||
recipe.rule = rule.into();
|
||||
recipe.reload_recipe()?;
|
||||
}
|
||||
if let Some(gitrev) = &lock_recipe.gitrev {
|
||||
if let Some(SourceRecipe::Git { rev, branch, .. }) = &mut recipe.recipe.source {
|
||||
*rev = Some(gitrev.clone());
|
||||
*branch = None;
|
||||
} else {
|
||||
println!(
|
||||
"DEBUG: Recipe {:?} contains into git rev but recipe source is not git",
|
||||
recipe.name.as_str()
|
||||
);
|
||||
}
|
||||
recipe.rule = "source".into();
|
||||
recipe.reload_recipe()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if command.is_building() && recipes.iter().any(|r| r.rule == "binary") {
|
||||
let (_, repository) = fetch_repo::get_binary_repo();
|
||||
for recipe in recipes.iter_mut() {
|
||||
@ -917,6 +968,48 @@ fn handle_tree(recipes: &Vec<CookRecipe>, is_build_tree: bool, _config: &CliConf
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_change_rule(recipes: &Vec<CookRecipe>, config: &CliConfig) -> Result<()> {
|
||||
let mut lock = get_config().recipe_lock.clone();
|
||||
let is_pruning = config.set_rule.as_ref().is_some_and(|s| s.is_empty());
|
||||
for recipe in recipes {
|
||||
let mut recipe_lock = lock.get(recipe.name.as_str()).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 old_rule = recipe_lock.fsrule.replace(new_rule.clone());
|
||||
old_rule == Some(new_rule)
|
||||
};
|
||||
if recipe_lock.is_empty() {
|
||||
lock.remove(recipe.name.as_str());
|
||||
} else {
|
||||
lock.insert(recipe.name.to_string(), recipe_lock);
|
||||
}
|
||||
let clean_cached = if !cached {
|
||||
handle_clean(recipe, config, &CliCommand::Clean)?
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if cached && clean_cached {
|
||||
print_cached(&CliCommand::ChangeRule, &recipe.name);
|
||||
} else {
|
||||
print_success(&CliCommand::ChangeRule, &recipe.name);
|
||||
}
|
||||
}
|
||||
CookLockOpt { recipes: lock }.save();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_capture_rev(_recipes: &Vec<CookRecipe>, _config: &CliConfig) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
//
|
||||
// ------------- TUI SPECIFIC CODE -------------------
|
||||
//
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
use std::{collections::HashMap, env, fs, str::FromStr, sync::OnceLock};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
env, fs,
|
||||
str::FromStr,
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq)]
|
||||
#[serde(default)]
|
||||
pub struct CookConfigOpt {
|
||||
/// whether to run offline
|
||||
@ -34,7 +39,7 @@ pub struct CookConfigOpt {
|
||||
pub write_filetree: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub struct CookConfig {
|
||||
pub offline: bool,
|
||||
pub jobs: usize,
|
||||
@ -67,7 +72,37 @@ impl From<CookConfigOpt> for CookConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct CookLockOpt {
|
||||
pub recipes: BTreeMap<String, RecipeLock>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct RecipeLock {
|
||||
pub fsrule: Option<String>,
|
||||
pub gitrev: Option<String>,
|
||||
}
|
||||
|
||||
impl RecipeLock {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.fsrule.is_none() && self.gitrev.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
const COOKBOOK_LOCK_HEADER: &str = r#"# This file is generated automatically.
|
||||
# All configuration here overrides anything from recipes or config directory.
|
||||
"#;
|
||||
|
||||
impl CookLockOpt {
|
||||
pub fn save(&self) {
|
||||
let str = toml::to_string(&self).unwrap();
|
||||
fs::write("cookbook.lock", format!("{COOKBOOK_LOCK_HEADER}\n{str}")).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, PartialEq)]
|
||||
#[serde(default)]
|
||||
pub struct CookbookConfig {
|
||||
#[serde(rename = "cook")]
|
||||
@ -75,6 +110,7 @@ pub struct CookbookConfig {
|
||||
#[serde(skip)]
|
||||
pub cook: CookConfig,
|
||||
pub mirrors: HashMap<String, String>,
|
||||
pub recipe_lock: BTreeMap<String, RecipeLock>,
|
||||
}
|
||||
|
||||
static CONFIG: OnceLock<CookbookConfig> = OnceLock::new();
|
||||
@ -145,6 +181,19 @@ pub fn init_config() {
|
||||
|
||||
config.cook = CookConfig::from(config.cook_opt.clone());
|
||||
|
||||
let lock: CookLockOpt = if fs::exists("cookbook.lock").unwrap_or(false) {
|
||||
let toml_content = fs::read_to_string("cookbook.lock")
|
||||
.map_err(|e| format!("Unable to read lock: {:?}", e))
|
||||
.unwrap();
|
||||
toml::from_str(&toml_content)
|
||||
.map_err(|e| format!("Unable to parse lock (plz delete manually): {:?}", e))
|
||||
.unwrap()
|
||||
} else {
|
||||
CookLockOpt::default()
|
||||
};
|
||||
|
||||
config.recipe_lock = lock.recipes;
|
||||
|
||||
CONFIG.set(config).expect("config is initialized twice");
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user