diff --git a/repo.sh b/repo.sh index 80adec4ef..a478cce0b 100755 --- a/repo.sh +++ b/repo.sh @@ -93,6 +93,16 @@ mkdir -p "$REPO" declare -A APPSTREAM_SOURCES +# Currently, we only support runtime dependencies for recipes in the new TOML +# format. Runtime dependencies include both `[package.dependencies]` and +# [`package.shared_deps`]. +# +# The following adds the package dependencies of the recipes to the repo as +# well. +# +# TODO(?): All of this script can be moved into `cook.rs`. +recipes="$recipes $(target/release/pkg_deps $toml_recipes)" + for recipe in $recipes do recipe_path=`target/release/find_recipe $recipe` @@ -107,9 +117,6 @@ do cp -v "${COOKBOOK_STAGE}.toml" "$REPO/$recipe.toml" fi - #TODO: PUBLISH DEPENDENCIES (RECURSIVELY) - #grep '^depends = ' "$REPO/$recipe.toml | cut -d '[' -f2 | cut -d ']' -f1 | tr -d ',' - if [ -e "${COOKBOOK_STAGE}/usr/share/metainfo" ] then APPSTREAM_SOURCES["$recipe"]="${COOKBOOK_STAGE}" diff --git a/src/bin/cook.rs b/src/bin/cook.rs index 21fc13b8f..e78834434 100644 --- a/src/bin/cook.rs +++ b/src/bin/cook.rs @@ -1,4 +1,5 @@ use cookbook::blake3::blake3_progress; +use cookbook::package::StageToml; use cookbook::recipe::{BuildKind, CookRecipe, PackageRecipe, Recipe, SourceRecipe}; use cookbook::recipe_find::recipe_find; use std::{ @@ -552,11 +553,7 @@ fn auto_deps(stage_dir: &Path, dep_pkgars: &BTreeSet<(String, PathBuf)>) -> BTre let mut missing = needed.clone(); // relibc and friends will always be installed - for preinstalled in &[ - "libc.so.6", - "libgcc_s.so.1", - "libstdc++.so.6", - ] { + for preinstalled in &["libc.so.6", "libgcc_s.so.1", "libstdc++.so.6"] { missing.remove(*preinstalled); } @@ -979,14 +976,6 @@ fn package( ) .map_err(|err| format!("failed to create pkgar archive: {:?}", err))?; - //TODO: share struct with pkgutils? - #[derive(serde::Serialize)] - struct StageToml { - name: String, - version: String, - target: String, - depends: Vec, - } let mut depends = package.dependencies.clone(); for dep in auto_deps.iter() { if !depends.contains(dep) { diff --git a/src/bin/pkg_deps.rs b/src/bin/pkg_deps.rs new file mode 100644 index 000000000..2265cdfd8 --- /dev/null +++ b/src/bin/pkg_deps.rs @@ -0,0 +1,20 @@ +use cookbook::package::StageToml; +use std::{env::args, process::ExitCode}; + +/// Same as `cookbook/src/bin/cook.rs`. +const DEP_DEPTH: usize = 16; + +fn usage() { + eprintln!("Usage: pkg_deps [package1 package2 ...]"); +} + +fn main() -> ExitCode { + let names = args().skip(1).collect::>(); + let packages = StageToml::new_recursive(&names, DEP_DEPTH).expect("package not found"); + + for package in packages { + println!("{}", package.name); + } + + ExitCode::SUCCESS +} diff --git a/src/lib.rs b/src/lib.rs index 29b678062..78e3b9a11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod blake3; +pub mod package; pub mod recipe; pub mod recipe_find; diff --git a/src/package.rs b/src/package.rs new file mode 100644 index 000000000..15d1815fb --- /dev/null +++ b/src/package.rs @@ -0,0 +1,77 @@ +use std::{env, fs, path::Path}; + +use crate::recipe_find::recipe_find; + +//TODO: share struct with pkgutils? +#[derive(PartialEq, serde::Deserialize, serde::Serialize)] +pub struct StageToml { + pub name: String, + pub version: String, + pub target: String, + pub depends: Vec, +} + +impl StageToml { + pub fn new(name: String) -> Result { + //TODO: sanitize recipe name? + let dir = recipe_find(&name, Path::new("recipes"))?; + if dir.is_none() { + return Err(format!("failed to find recipe directory '{}'", name)); + } + let dir = dir.unwrap(); + let target = + env::var("TARGET").map_err(|err| format!("failed to read TARGET: {:?}", err))?; + + let file = dir.join("target").join(target).join("stage.toml"); + if !file.is_file() { + return Err(format!("failed to find package file '{}'", file.display())); + } + + let toml = fs::read_to_string(&file).map_err(|err| { + format!( + "failed to read package file '{}': {}\n{:#?}", + file.display(), + err, + err + ) + })?; + + toml::from_str(&toml).map_err(|err| { + format!( + "failed to parse package file '{}': {}\n{:#?}", + file.display(), + err, + err + ) + }) + } + + pub fn new_recursive(names: &[String], recursion: usize) -> Result, String> { + if recursion == 0 { + return Err(format!( + "recursion limit while processing build dependencies: {:#?}", + names + )); + } + + let mut packages = Vec::new(); + for name in names { + let package = Self::new(name.clone())?; + + let dependencies = Self::new_recursive(&package.depends, recursion - 1) + .map_err(|err| format!("{}: failed on loading dependencies:\n{}", name, err))?; + + for dependency in dependencies { + if !packages.contains(&dependency) { + packages.push(dependency); + } + } + + if !packages.contains(&package) { + packages.push(package); + } + } + + Ok(packages) + } +}