Migrate error type and drop anyhow

This commit is contained in:
Wildan M 2026-04-14 12:57:12 +07:00
parent 6d774c117a
commit 208878c1bf
No known key found for this signature in database
GPG Key ID: 01AC53185C679C79
9 changed files with 132 additions and 136 deletions

5
Cargo.lock generated
View File

@ -38,9 +38,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.100"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arg_parser"
@ -871,7 +871,6 @@ name = "redox_cookbook"
version = "0.1.0"
dependencies = [
"ansi-to-tui",
"anyhow",
"blake3",
"globset",
"ignore",

View File

@ -30,7 +30,6 @@ default = ["tui"]
tui = ["ratatui", "ansi-to-tui", "strip-ansi-escapes"]
[dependencies]
anyhow = "1"
blake3 = "1"
globset = "0.4"
libc = "0.2"

View File

@ -1,16 +1,15 @@
use ansi_to_tui::IntoText;
use anyhow::{Context, anyhow, bail};
use cookbook::config::{CookConfig, 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_target_dir, run_command};
use cookbook::cook::fs::{create_dir, create_target_dir, remove_all, run_command};
use cookbook::cook::ident;
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;
use cookbook::cook::tree::{self, WalkTreeEntry};
use cookbook::recipe::{CookRecipe, recipes_flatten_package_names, recipes_mark_as_deps};
use cookbook::{Error, staged_pkg};
use cookbook::{Error, Result, staged_pkg};
use pkg::{PackageName, PackageState};
use ratatui::Terminal;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
@ -122,9 +121,9 @@ impl CliCommand {
}
impl FromStr for CliCommand {
type Err = anyhow::Error;
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"fetch" => Ok(CliCommand::Fetch),
"cook" => Ok(CliCommand::Cook),
@ -135,7 +134,10 @@ impl FromStr for CliCommand {
"push-tree" => Ok(CliCommand::PushTree),
"cook-tree" => Ok(CliCommand::CookTree),
"find" => Ok(CliCommand::Find),
_ => Err(anyhow!("Unknown command '{}'\n{}\n", s, REPO_HELP_STR)),
_ => Err(Error::Other(format!(
"Unknown command '{}'\n{}\n",
s, REPO_HELP_STR
))),
}
}
}
@ -157,8 +159,8 @@ impl ToString for CliCommand {
}
impl CliConfig {
fn new() -> Result<Self, std::io::Error> {
let current_dir = env::current_dir()?;
fn new() -> Result<Self> {
let current_dir = env::current_dir().map_err(|e| Error::from_io_error(e, "Getting cwd"))?;
Ok(CliConfig {
//FIXME: This config is unused as redox-pkg harcoded this to $PWD/recipes
cookbook_dir: current_dir.join("recipes"),
@ -191,7 +193,7 @@ fn main() {
};
}
fn main_inner() -> anyhow::Result<()> {
fn main_inner() -> Result<()> {
let args: Vec<String> = env::args().skip(1).collect();
if args.is_empty() || args.contains(&"--help".to_string()) || args.contains(&"-h".to_string()) {
@ -212,7 +214,7 @@ fn main_inner() -> anyhow::Result<()> {
let _ = stderr().write(err.as_bytes());
let _ = stderr().write(b"\n\n");
print_failed(&command, &name);
return Err(anyhow!("Execution has failed"));
return Err(Error::from(format!("Execution has failed")));
}
Ok(app) => {
for (recipe, status) in app.recipes {
@ -228,7 +230,7 @@ fn main_inner() -> anyhow::Result<()> {
}
}
}
Err(e) => return Err(anyhow!(e)),
Err(e) => return Err(e),
}
return publish_packages(&recipes, &config.repo_dir);
}
@ -321,14 +323,10 @@ fn print_cached(command: &CliCommand, recipe: &PackageName) {
);
}
fn repo_inner(
config: &CliConfig,
command: &CliCommand,
recipe: &CookRecipe,
) -> Result<bool, anyhow::Error> {
fn repo_inner(config: &CliConfig, command: &CliCommand, recipe: &CookRecipe) -> Result<bool> {
Ok(match *command {
CliCommand::Fetch | CliCommand::Cook => {
let repo_inner_fn = move |logger: &PtyOut| -> Result<bool, anyhow::Error> {
let repo_inner_fn = move |logger: &PtyOut| -> Result<bool> {
let is_cook = *command == CliCommand::Cook;
let fetch_result = handle_fetch(recipe, config, is_cook, logger)?;
let cached = if is_cook {
@ -399,8 +397,12 @@ fn repo_inner(
})
}
fn publish_packages(recipe_names: &Vec<CookRecipe>, repo_path: &PathBuf) -> anyhow::Result<()> {
let repo_bin = env::current_exe()?.parent().unwrap().join("repo_builder");
fn publish_packages(recipe_names: &Vec<CookRecipe>, repo_path: &PathBuf) -> Result<()> {
let repo_bin = env::current_exe()
.map_err(|e| Error::from_io_error(e, "Getting exe path"))?
.parent()
.unwrap()
.join("repo_builder");
let mut command = Command::new(repo_bin);
command
.arg(repo_path)
@ -412,10 +414,10 @@ fn publish_packages(recipe_names: &Vec<CookRecipe>, repo_path: &PathBuf) -> anyh
}
}));
run_command(command, &None).map_err(|e| anyhow!(e))
run_command(command, &None)
}
fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<CookRecipe>)> {
fn parse_args(args: Vec<String>) -> Result<(CliConfig, CliCommand, Vec<CookRecipe>)> {
let mut config = CliConfig::new()?;
let mut command: Option<String> = None;
let mut recipe_names: Vec<PackageName> = Vec::new();
@ -431,7 +433,7 @@ fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<C
"--filesystem" => {
config.filesystem = Some({
let r = redox_installer::Config::from_file(&PathBuf::from(value));
r.context("Unable to read filesystem installer config")?
r.map_err(|e| Error::Other(e.to_string()))?
})
}
_ => {
@ -465,7 +467,7 @@ fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<C
command = Some(arg);
} else {
// Subsequent non-flag arguments are recipe names
recipe_names.push(arg.try_into().context("Invalid package name")?);
recipe_names.push(arg.try_into().map_err(Error::from)?);
}
}
@ -474,11 +476,13 @@ fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<C
config.category = Some(PathBuf::from("recipes").join(c));
}
if let Some(c) = config.logs_dir.as_mut() {
fs::create_dir_all(c.join(redoxer::target())).map_err(|e| anyhow!(e))?;
fs::create_dir_all(c.join(redoxer::host_target())).map_err(|e| anyhow!(e))?;
create_dir(&c.join(redoxer::target()))?;
create_dir(&c.join(redoxer::host_target()))?;
}
let command = command.ok_or(anyhow!("Error: No command specified."))?;
let Some(command) = command else {
return Err(Error::Other(format!("Error: No command specified.")));
};
let command: CliCommand = str::parse(&command)?;
if command.is_informational() {
// avoid extra data that clobber stdout
@ -490,18 +494,22 @@ fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<C
if recipe_names.is_empty() {
if config.all || config.category.is_some() {
if !recipe_names.is_empty() {
bail!("Do not specify recipe names when using the --all or --category flag.");
return Err(Error::Other(format!(
"Do not specify recipe names when using the --all or --category flag."
)));
}
if config.all && config.category.is_some() {
bail!("Do not specify both --all and --category flag.");
return Err(Error::Other(format!(
"Do not specify both --all and --category flag."
)));
}
if config.all && !command.is_cleaning() {
// because read_recipe is false by logic below
// some recipes on wip folders are invalid anyway
bail!(
return Err(Error::Other(format!(
"Refusing to run an unrealistic command to {} all recipes",
command.to_string()
);
)));
}
let all_recipes_path = match &config.category {
None => staged_pkg::list(""),
@ -526,9 +534,9 @@ fn parse_args(args: Vec<String>) -> anyhow::Result<(CliConfig, CliCommand, Vec<C
.filter_map(|k| PackageName::new(k.to_string()).ok())
.collect();
} else {
bail!(
return Err(Error::Other(format!(
"Error: No recipe names or filesystem config provided and --all flag was not used."
);
)));
}
}
}
@ -696,14 +704,11 @@ fn handle_fetch(
config: &CliConfig,
allow_offline: bool,
logger: &PtyOut,
) -> anyhow::Result<FetchResult> {
let source_dir = match config.cook.offline && allow_offline {
) -> Result<FetchResult> {
match config.cook.offline && allow_offline {
true => fetch_offline(&recipe, logger),
false => fetch(&recipe, !recipe.is_deps, logger),
}
.map_err(|e| anyhow!("failed to fetch: {}", e))?;
Ok(source_dir)
}
fn handle_cook(
@ -711,9 +716,9 @@ fn handle_cook(
config: &CliConfig,
source_dir: PathBuf,
logger: &PtyOut,
) -> anyhow::Result<bool> {
) -> Result<bool> {
let recipe_dir = &recipe.dir;
let target_dir = create_target_dir(recipe_dir, recipe.target).map_err(|e| anyhow!(e))?;
let target_dir = create_target_dir(recipe_dir, recipe.target)?;
let build_result = build(
recipe_dir,
&source_dir,
@ -721,11 +726,9 @@ fn handle_cook(
&recipe,
&config.cook,
logger,
)
.map_err(|err| anyhow!("failed to build: {}", err))?;
)?;
package(&recipe, &build_result, &config.cook, logger)
.map_err(|err| anyhow!("failed to package: {}", err))?;
package(&recipe, &build_result, &config.cook, logger)?;
if config.cook.clean_target || config.cook.write_filetree {
for stage_dir in &build_result.stage_dirs {
@ -733,12 +736,12 @@ fn handle_cook(
if config.cook.write_filetree {
let mut stage_files_buf = String::new();
tree::walk_file_tree(&stage_dir, "", &mut stage_files_buf)
.context("failed to walk stage files tree")?;
.map_err(|e| Error::from_io_error(e, "Walking files tree"))?;
fs::write(stage_dir.with_added_extension("files"), stage_files_buf)
.context("unable to write stage files")?;
.map_err(|e| Error::from_io_error(e, "Writing files tree"))?;
}
if config.cook.clean_target {
fs::remove_dir_all(&stage_dir).context("failed to remove stage dir")?;
remove_all(&stage_dir)?;
}
}
}
@ -756,30 +759,26 @@ fn handle_nonstop_fail(recipe: &CookRecipe) -> cookbook::Result<()> {
Ok(())
}
fn handle_clean(
recipe: &CookRecipe,
_config: &CliConfig,
command: &CliCommand,
) -> anyhow::Result<bool> {
fn handle_clean(recipe: &CookRecipe, _config: &CliConfig, command: &CliCommand) -> Result<bool> {
let mut dir = recipe.dir.join("target");
let mut cached = true;
if matches!(*command, CliCommand::CleanTarget) {
dir = dir.join(redoxer::target())
}
if dir.exists() {
fs::remove_dir_all(&dir).context(format!("failed to delete {}", dir.display()))?;
remove_all(&dir)?;
cached = false;
}
let dir = recipe.dir.join("source");
if dir.exists() && matches!(*command, CliCommand::Unfetch) {
fs::remove_dir_all(&dir).context(format!("failed to delete {}", dir.display()))?;
remove_all(&dir)?;
cached = false;
}
Ok(cached)
}
static PUSH_SYSROOT_DIR: OnceLock<PathBuf> = OnceLock::new();
fn handle_push(recipes: &Vec<CookRecipe>, config: &CliConfig) -> anyhow::Result<()> {
fn handle_push(recipes: &Vec<CookRecipe>, config: &CliConfig) -> Result<()> {
let recipe_map: HashMap<&PackageName, &CookRecipe> =
recipes.iter().map(|r| (&r.name, r)).collect();
let mut total_size: u64 = 0;
@ -791,23 +790,23 @@ fn handle_push(recipes: &Vec<CookRecipe>, config: &CliConfig) -> anyhow::Result<
_prefix: &str,
_is_last: bool,
entry: &WalkTreeEntry|
-> anyhow::Result<bool> {
-> Result<bool> {
let r = match entry {
WalkTreeEntry::Built(archive_path, _) => {
let install_path = PUSH_SYSROOT_DIR.get().unwrap();
let mut state =
PackageState::from_sysroot(install_path).map_err(|e| anyhow!("{e:?}"))?;
let r = package_handle_push(&mut state, archive_path, &install_path, false)
.map_err(|e| anyhow!("{e:?}"));
let mut state = PackageState::from_sysroot(install_path).map_err(Error::from)?;
let r = package_handle_push(&mut state, archive_path, &install_path, false);
if matches!(r, Ok(false)) {
state.to_sysroot(install_path)?;
state
.to_sysroot(install_path)
.map_err(|e| Error::from_io_error(e, "Extracting package"))?;
}
r
}
WalkTreeEntry::NotBuilt => Err(anyhow!(
WalkTreeEntry::NotBuilt => Err(Error::Other(format!(
"Package {} has not been built",
package_name.name()
)),
))),
WalkTreeEntry::Deduped | WalkTreeEntry::Missing => {
// does not matter
return Ok(false);
@ -863,11 +862,7 @@ fn handle_push(recipes: &Vec<CookRecipe>, config: &CliConfig) -> anyhow::Result<
Ok(())
}
fn handle_tree(
recipes: &Vec<CookRecipe>,
is_build_tree: bool,
_config: &CliConfig,
) -> anyhow::Result<()> {
fn handle_tree(recipes: &Vec<CookRecipe>, is_build_tree: bool, _config: &CliConfig) -> Result<()> {
let recipe_map: HashMap<&PackageName, &CookRecipe> =
recipes.iter().map(|r| (&r.name, r)).collect();
let mut total_size: u64 = 0;
@ -1051,13 +1046,13 @@ impl TuiApp {
(log_text, log_line)
}
pub fn write_log(&self, recipe_name: &PackageName, log_path: &PathBuf) -> anyhow::Result<()> {
pub fn write_log(&self, recipe_name: &PackageName, log_path: &PathBuf) -> Result<()> {
let (Some(logs), line) = self.get_recipe_log(recipe_name) else {
return Ok(());
};
let str = strip_ansi_escapes::strip_str(join_logs(logs, line));
if !str.trim_end().is_empty() {
fs::write(log_path, str)?;
fs::write(log_path, str).map_err(|e| Error::from_io_error(e, "Writing log"))?;
}
return Ok(());
}
@ -1162,7 +1157,7 @@ impl TuiApp {
}
}
fn run_tui_cook(config: CliConfig, recipes: Vec<CookRecipe>) -> Result<TuiApp, cookbook::Error> {
fn run_tui_cook(config: CliConfig, recipes: Vec<CookRecipe>) -> Result<TuiApp> {
let (work_tx, work_rx) = mpsc::channel::<(CookRecipe, FetchResult)>();
let (status_tx, status_rx) = mpsc::channel::<StatusUpdate>();

View File

@ -1,30 +1,16 @@
use cookbook::cook::ident::{get_ident, init_ident};
use cookbook::cook::{fetch, package as cook_package};
use cookbook::cook::{fetch, fs, package as cook_package};
use cookbook::recipe::CookRecipe;
use cookbook::web::{CliWebConfig, generate_web};
use cookbook::{WALK_DEPTH, staged_pkg};
use cookbook::{Error, Result, WALK_DEPTH, staged_pkg};
use pkg::PackageName;
use pkg::{Repository, SourceIdentifier};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use toml::Value;
fn is_newer(src: &Path, dst: &Path) -> bool {
match (fs::metadata(src), fs::metadata(dst)) {
(Ok(src_meta), Ok(dst_meta)) => match (src_meta.modified(), dst_meta.modified()) {
(Ok(src_time), Ok(dst_time)) => src_time > dst_time,
(Ok(_), Err(_)) => true,
_ => false,
},
(Ok(_), Err(_)) => true,
_ => false,
}
}
#[derive(Clone)]
struct CliConfig {
repo_dir: PathBuf,
@ -34,7 +20,7 @@ struct CliConfig {
}
impl CliConfig {
fn parse_args() -> Result<Self, std::io::Error> {
fn parse_args() -> Result<Self> {
let mut args = env::args().skip(1);
let repo_dir = PathBuf::from(
args.next()
@ -50,26 +36,29 @@ impl CliConfig {
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
fn main() -> Result<()> {
init_ident();
let conf = CliConfig::parse_args()?;
Ok(publish_packages(&conf)?)
}
// TODO: Make this callable from repo bin
fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
fn publish_packages(config: &CliConfig) -> Result<()> {
let repo_path = &config.repo_dir.join(redoxer::target());
if !repo_path.is_dir() {
fs::create_dir_all(repo_path)?;
fs::create_dir(repo_path)?;
}
// Don't publish host packages
let target_packages = &config
.recipe_list
.iter()
.map(PackageName::new)
.filter(|pkg| pkg.as_ref().is_ok_and(|p| !p.is_host()))
.collect::<Result<Vec<_>, _>>()?;
.filter_map(|n| match PackageName::new(n) {
Ok(p) if p.is_host() => None,
Ok(p) => Some(p),
Err(_) => None,
})
.collect::<Vec<_>>();
if target_packages.len() == 0 {
return Ok(());
@ -89,7 +78,7 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
if recipe_list.len() == 0 {
// Fail-Safe
anyhow::bail!("Zero packages are passing the build");
return Err(Error::Other(format!("Zero packages are passing the build")));
}
let mut appstream_sources: HashMap<String, PathBuf> = HashMap::new();
@ -116,17 +105,19 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
let pkgar_dst = repo_path.join(format!("{}.pkgar", recipe_name));
let toml_dst = repo_path.join(format!("{}.toml", recipe_name));
if !fs::exists(&toml_src)? {
if !toml_src.is_file() {
eprintln!("recipe {} is missing stage.toml", recipe_name);
continue;
}
if is_newer(&toml_src, &toml_dst) {
if fs::modified_is_newer(&toml_src, &toml_dst) {
eprintln!("\x1b[01;38;5;155mrepo - publishing {}\x1b[0m", recipe_name);
if fs::exists(&pkgar_src)? {
fs::copy(&pkgar_src, &pkgar_dst)?;
if pkgar_src.is_file() {
std::fs::copy(&pkgar_src, &pkgar_dst)
.map_err(|e| Error::from_io_error(e, "Copying file"))?;
}
fs::copy(&toml_src, &toml_dst)?;
std::fs::copy(&toml_src, &toml_dst)
.map_err(|e| Error::from_io_error(e, "Copying file"))?;
}
// TODO: Extract from pkgar instead to handle config.cook.clean_target == true
@ -147,8 +138,7 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
.join(&target)
.join("appstream");
fs::remove_dir_all(&appstream_root).ok();
fs::create_dir_all(&appstream_root)?;
fs::create_dir_clean(&appstream_root)?;
if !appstream_sources.is_empty() {
let mut compose_cmd = Command::new("appstreamcli");
@ -162,10 +152,12 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
compose_cmd.arg(source_path);
}
let exit_status = compose_cmd.status()?;
let exit_status = compose_cmd
.status()
.map_err(|e| Error::from_io_error(e, "Reading exit status"))?;
if exit_status.success() {
let appstream_pkg = repo_path.join("repo-appstream.pkgar");
fs::remove_file(&appstream_pkg).ok();
let _ = fs::remove_all(&appstream_pkg);
pkgar::create(
format!("{}/build/id_ed25519.toml", root),
&appstream_pkg,
@ -227,11 +219,10 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
// === 4. Read and update repo.toml ===
let repo_toml_path = repo_path.join("repo.toml");
if repo_toml_path.exists() {
let mut file = File::open(&repo_toml_path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let contents = fs::read_to_string(&repo_toml_path)?;
let parsed: Repository = toml::from_str(&contents)?;
let parsed: Repository = toml::from_str(&contents)
.map_err(|_| Error::Other(format!("Unable to deserialize repo.toml")))?;
for (k, v) in parsed.packages {
packages.insert(k, v);
}
@ -248,8 +239,10 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
}
}
for entry in fs::read_dir(&repo_path)? {
let entry = entry?;
for entry in
std::fs::read_dir(&repo_path).map_err(|e| Error::from_io_error(e, "Listing repo"))?
{
let entry = entry.map_err(|e| Error::from_io_error(e, "Reading repo entry"))?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) != Some("toml") {
@ -261,7 +254,8 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
}
let content = fs::read_to_string(&path)?;
let parsed: Value = toml::from_str(&content)?;
let parsed: Value = toml::from_str(&content)
.map_err(|_| Error::Other(format!("Unable to deserialize repo.toml")))?;
let empty_ver = Value::String("".to_string());
let version_str = parsed
@ -278,9 +272,7 @@ fn publish_packages(config: &CliConfig) -> anyhow::Result<()> {
outdated_packages,
};
let output = toml::to_string(&repository)?;
let mut output_file = File::create(&repo_toml_path)?;
output_file.write_all(output.as_bytes())?;
fs::serialize_and_write(&repo_toml_path, &repository)?;
if let Some(conf) = &config.web {
eprintln!("\x1b[01;38;5;155mrepo - generating web content\x1b[0m");

View File

@ -19,7 +19,7 @@ use std::{
time::SystemTime,
};
use crate::{is_redox, log_to_pty};
use crate::{Result, is_redox, log_to_pty};
fn auto_deps_from_dynamic_linking(
stage_dirs: &[PathBuf],
@ -155,7 +155,7 @@ fn auto_deps_from_dynamic_linking(
fn auto_deps_from_static_package_deps(
build_dep_pkgars: &BTreeSet<(PackageName, PathBuf)>,
dynamic_dep_pkgars: &BTreeSet<PackageName>,
) -> Result<BTreeSet<PackageName>, PackageError> {
) -> std::result::Result<BTreeSet<PackageName>, PackageError> {
let static_dep_pkgars: Vec<PackageName> = build_dep_pkgars
.iter()
.map(|x| x.0.clone())
@ -197,7 +197,7 @@ pub fn build(
cook_recipe: &CookRecipe,
cook_config: &CookConfig,
logger: &PtyOut,
) -> Result<BuildResult, String> {
) -> Result<BuildResult> {
let recipe = &cook_recipe.recipe;
let name = &cook_recipe.name;
let check_source = !cook_recipe.is_deps;
@ -565,7 +565,7 @@ fn build_deps_dir(
dep_pkgars: &BTreeSet<(PackageName, PathBuf)>,
source_modified: SystemTime,
deps_modified: SystemTime,
) -> Result<bool, String> {
) -> Result<bool> {
let deps_dir_tmp = deps_dir.with_added_extension("tmp");
if deps_dir.is_dir() {
let tags_dir = deps_dir.join(".tags");
@ -635,7 +635,7 @@ fn build_auto_deps(
cook_config: &CookConfig,
mut dep_pkgars: BTreeSet<(PackageName, PathBuf)>,
logger: &PtyOut,
) -> Result<BTreeSet<PackageName>, String> {
) -> Result<BTreeSet<PackageName>> {
if auto_deps_path.is_file() && !cached {
if cook_config.verbose {
log_to_pty!(logger, "DEBUG: updating {}", auto_deps_path.display());
@ -670,7 +670,7 @@ pub fn build_remote(
recipe: &Recipe,
target_dir: &Path,
cook_config: &CookConfig,
) -> Result<BuildResult, String> {
) -> Result<BuildResult> {
let source_toml = target_dir.join("source.toml");
let source_pubkey = "build/remotes/pub_key_static.redox-os.org.toml";

View File

@ -102,6 +102,18 @@ pub fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()>
.map_err(wrap_io_err!(link.as_ref(), "Creating symlink"))
}
pub fn modified_is_newer(src: &Path, dst: &Path) -> bool {
match (fs::metadata(src), fs::metadata(dst)) {
(Ok(src_meta), Ok(dst_meta)) => match (src_meta.modified(), dst_meta.modified()) {
(Ok(src_time), Ok(dst_time)) => src_time > dst_time,
(Ok(_), Err(_)) => true,
_ => false,
},
(Ok(_), Err(_)) => true,
_ => false,
}
}
fn modified_inner(path: &Path, metadata: fs::Metadata) -> Result<SystemTime> {
metadata
.modified()

View File

@ -8,7 +8,7 @@ use pkgar::ext::PackageSrcExt;
use pkgar_core::HeaderFlags;
use crate::{
Error,
Error, Result,
config::CookConfig,
cook::{cook_build::BuildResult, fetch, fs::*, pty::PtyOut},
log_to_pty,
@ -20,7 +20,7 @@ pub fn package(
build_result: &BuildResult,
cook_config: &CookConfig,
logger: &PtyOut,
) -> Result<(), String> {
) -> Result<()> {
let name = &recipe.name;
let target_dir = &recipe.target_dir();
let auto_deps = &build_result.auto_deps;
@ -128,7 +128,7 @@ pub fn package_toml(
package_suffix: Option<&OptionalPackageRecipe>,
mut package_deps: Vec<PackageName>,
auto_deps: &BTreeSet<PackageName>,
) -> Result<(), String> {
) -> Result<()> {
for dep in auto_deps.iter() {
if !package_deps.contains(dep) {
package_deps.push(dep.clone());

View File

@ -1,4 +1,3 @@
use anyhow::Context;
use pkg::{Package, PackageName};
use std::fmt::Write as _;
use std::{
@ -8,6 +7,7 @@ use std::{
};
use crate::recipe::CookRecipe;
use crate::{Result, wrap_other_err};
pub enum WalkTreeEntry<'a> {
Built(&'a PathBuf, u64),
@ -25,7 +25,7 @@ pub fn display_tree_entry(
visited: &mut HashSet<PackageName>,
total_size: &mut u64,
total_count: &mut u64,
) -> anyhow::Result<()> {
) -> Result<()> {
walk_tree_entry(
package_name,
recipe_map,
@ -48,8 +48,8 @@ pub fn walk_tree_entry(
visited: &mut HashSet<PackageName>,
total_size: &mut u64,
total_count: &mut u64,
op: fn(&PackageName, &str, bool, &WalkTreeEntry) -> anyhow::Result<bool>,
) -> anyhow::Result<()> {
op: fn(&PackageName, &str, bool, &WalkTreeEntry) -> Result<bool>,
) -> Result<()> {
let cook_recipe = match recipe_map.get(package_name) {
Some(r) => r,
None => {
@ -97,7 +97,7 @@ pub fn walk_tree_entry(
if let Ok(pkg_toml_str) = read_to_string(&pkg_toml) {
// more accurate with auto deps
pkg_meta = toml::from_str(&pkg_toml_str)
.context(format!("Unable to parse {}", pkg_toml.display()))?;
.map_err(|_| wrap_other_err!("Unable to parse {}", pkg_toml.display())())?;
all_deps_set.extend(pkg_meta.depends.iter());
}
}
@ -131,7 +131,7 @@ pub fn display_pkg_fn(
prefix: &str,
is_last: bool,
entry: &WalkTreeEntry,
) -> anyhow::Result<bool> {
) -> Result<bool> {
let size_str = match entry {
WalkTreeEntry::Built(_path_buf, size) => format!("[{}]", format_size(*size)),
WalkTreeEntry::NotBuilt => "(not built)".to_string(),

View File

@ -9,7 +9,7 @@ use pkg::{PackageError, PackageName};
use regex::Regex;
use serde::{Deserialize, Serialize};
use crate::{WALK_DEPTH, cook::package as cook_package, staged_pkg};
use crate::{WALK_DEPTH, bail_other_err, cook::package as cook_package, staged_pkg};
/// Specifies how to download the source for a recipe
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
@ -444,7 +444,7 @@ impl CookRecipe {
self.dir.join("target").join(self.target)
}
pub fn apply_filesystem_config(&mut self, rule: &str) -> Result<(), anyhow::Error> {
pub fn apply_filesystem_config(&mut self, rule: &str) -> crate::Result<()> {
match rule {
// build from source as usual
"source" => {}
@ -463,8 +463,7 @@ impl CookRecipe {
self.recipe.build.set_as_none();
}
rule => {
anyhow::bail!(
// Fail fast because we could risk losing local changes if "local" was typo'ed
bail_other_err!(
"Invalid pkg config {} = \"{}\"\nExpecting either 'source', 'local', 'binary' or 'ignore'",
self.name.as_str(),
rule