diff --git a/clean.sh b/clean.sh index c1ed4cf24..e26dba32a 100755 --- a/clean.sh +++ b/clean.sh @@ -5,30 +5,15 @@ source config.sh if [ $# = 0 ] then - recipes="$(target/release/list_recipes)" + recipes="$(target/release/list_recipes --short)" else recipes="$@" fi -for recipe in $recipes +for recipe_name in $recipes do - if (echo "$recipe" | grep '.*/.*' >/dev/null); then - recipe_name=$(basename "$recipe") - recipe_path="$recipe" - else - recipe_name="$recipe" - recipe_path=`target/release/find_recipe $recipe` - fi + recipe_path=`target/release/find_recipe $recipe_name` echo -e "\033[01;38;5;215mcook - clean $recipe_name\033[0m" - - if [ -d "$ROOT/$recipe_path" ] - then - COOKBOOK_RECIPE="${ROOT}/$recipe_path" - TARGET_DIR="${ROOT}/$recipe_path/target/${TARGET}" - - rm -rf "${TARGET_DIR}" - else - echo "clean.sh: recipe '$recipe_name' not found" >&2 - fi + rm -rf "${ROOT}/$recipe_path/target/${TARGET}" done diff --git a/config.sh b/config.sh index f3a3b2de4..71131eb89 100755 --- a/config.sh +++ b/config.sh @@ -14,7 +14,6 @@ fi # Automatic variables ROOT="$(cd `dirname "$0"` && pwd)" -REPO="$ROOT/repo/$TARGET" export PATH="${ROOT}/bin:$PATH" export AR="${HOST}-gcc-ar" @@ -43,26 +42,11 @@ export PKG_CONFIG_FOR_BUILD="pkg-config" if [[ "$OSTYPE" == "darwin"* ]] || [[ "$OSTYPE" == "FreeBSD" ]]; then # GNU find FIND="gfind"; - - # GNU stat from Homebrew or MacPorts - if [ ! -z "$(which brew)" ]; then - STAT="$(brew --prefix)/opt/coreutils/libexec/gnubin/stat"; - elif [ ! -z "$(which port)" ]; then - # TODO: find a programatic way of asking MacPorts for it's root dir. - STAT="/opt/local/opt/coreutils/libexec/gnubin/stat"; - elif [ ! -z "$(which pkg)" ]; then - STAT="gnustat" - else - echo "Please install either Homebrew or MacPorts and run the boostrap script." - exit 1 - fi else - FIND="find" - STAT="stat"; + FIND="find"; fi export FIND -export STAT if [ ! "$(uname -s)" = "Redox" ] then diff --git a/fetch.sh b/fetch.sh index a3bc69c76..2a1e87a99 100755 --- a/fetch.sh +++ b/fetch.sh @@ -3,34 +3,4 @@ set -e source config.sh -recipes="" -for arg in "${@:1}" -do - if [ "$arg" == "--nonstop" ] - then - set +e - elif [ "$arg" == "--offline" ] - then - export COOKBOOK_OFFLINE="1" - else - recipes+=" $arg" - fi -done - -if [ "$recipes" == "" ] -then - recipes="$(target/release/list_recipes)" -fi - -for recipe_path in $recipes -do - if (echo "$recipe_path" | grep '.*/.*' >/dev/null); then - recipe_name=$(basename "$recipe_path") - recipe_path="$recipe_path" - else - recipe_name="$recipe_path" - recipe_path=`target/release/find_recipe $recipe_name` - fi - - target/release/cook --fetch-only "$recipe_name" -done +target/release/cook --fetch-only ${@:1} diff --git a/repo.sh b/repo.sh index 8869c0e7b..f24580057 100755 --- a/repo.sh +++ b/repo.sh @@ -12,50 +12,23 @@ do if [ "$arg" == "--appstream" ] then APPSTREAM="1" - elif [ "$arg" == "--debug" ] - then - DEBUG=--debug elif [ "$arg" == "--with-package-deps" ] then - COOK_OPT=--with-package-deps + COOK_OPT+=" --with-package-deps" elif [ "$arg" == "--nonstop" ] then - set +e + COOK_OPT+=" --nonstop" elif [ "$arg" == "--offline" ] then - export COOKBOOK_OFFLINE="1" + COOK_OPT+=" --offline" else recipes+=" $arg" fi done -if [ "$recipes" == "" ] -then - recipes="$(target/release/list_recipes)" -fi +target/release/cook $COOK_OPT $recipes -for recipe in $recipes -do - recipe_path=`target/release/find_recipe $recipe` - COOKBOOK_RECIPE="$recipe_path" - TARGET_DIR="${COOKBOOK_RECIPE}/target/${TARGET}" - COOKBOOK_BUILD="${TARGET_DIR}/build" - COOKBOOK_STAGE="${TARGET_DIR}/stage" - COOKBOOK_SOURCE="${COOKBOOK_RECIPE}/source" - COOKBOOK_SYSROOT="${TARGET_DIR}/sysroot" +repo="$ROOT/repo/$TARGET" +mkdir -p "$repo" - target/release/cook $COOK_OPT "$recipe" -done - -mkdir -p "$REPO" - -declare -A APPSTREAM_SOURCES - -# Runtime dependencies include both `[package.dependencies]` and dynamically -# linked packages discovered by auto_deps. -# -# The following adds the package dependencies of the recipes to the repo as -# well. -recipes="$recipes $(target/release/pkg_deps $recipes)" - -target/release/repo_builder "$REPO" $recipes +target/release/repo_builder "$repo" $recipes diff --git a/src/bin/cook.rs b/src/bin/cook.rs index ca2e4484b..7b3f291ab 100644 --- a/src/bin/cook.rs +++ b/src/bin/cook.rs @@ -928,7 +928,7 @@ EOF -Wno-dev \ "${COOKBOOK_CMAKE_FLAGS[@]}" \ "$@" - + "${COOKBOOK_NINJA}" -j"${COOKBOOK_MAKE_JOBS}" DESTDIR="${COOKBOOK_STAGE}" "${COOKBOOK_NINJA}" install -j"${COOKBOOK_MAKE_JOBS}" } @@ -996,7 +996,7 @@ function cookbook_meson { let post_script = r#"# Common post script # Strip binaries -for dir in "${COOKBOOK_STAGE}/bin" "${COOKBOOK_STAGE}/usr/bin" +for dir in "${COOKBOOK_STAGE}/bin" "${COOKBOOK_STAGE}/usr/bin" do if [ -d "${dir}" ] && [ -z "${COOKBOOK_NOSTRIP}" ] then @@ -1005,7 +1005,7 @@ do done # Remove libtool files -for dir in "${COOKBOOK_STAGE}/lib" "${COOKBOOK_STAGE}/usr/lib" +for dir in "${COOKBOOK_STAGE}/lib" "${COOKBOOK_STAGE}/usr/lib" do if [ -d "${dir}" ] then @@ -1237,12 +1237,12 @@ fn cook( name: &PackageName, recipe: &Recipe, fetch_only: bool, + is_offline: bool, ) -> Result<(), String> { if recipe.build.kind == BuildKind::None { return cook_meta(recipe_dir, name, recipe, fetch_only); } - let is_offline = env::var("COOKBOOK_OFFLINE").unwrap_or("".to_string()) == "1"; let source_dir = match is_offline { true => fetch_offline(recipe_dir, &recipe.source), false => fetch(recipe_dir, &recipe.source), @@ -1282,6 +1282,8 @@ fn main() { let mut fetch_only = false; let mut with_package_deps = false; let mut quiet = false; + let mut nonstop = false; + let mut is_offline = false; let mut recipe_names = Vec::new(); for arg in env::args().skip(1) { match arg.as_str() { @@ -1290,6 +1292,8 @@ fn main() { "--with-package-deps" if matching => with_package_deps = true, "--fetch-only" if matching => fetch_only = true, "-q" | "--quiet" if matching => quiet = true, + "--nonstop" => nonstop = true, + "--offline" => is_offline = true, _ => recipe_names.push(arg.try_into().expect("Invalid package name")), } } @@ -1344,7 +1348,13 @@ fn main() { } Ok(()) } else { - cook(&recipe.dir, &recipe.name, &recipe.recipe, fetch_only) + cook( + &recipe.dir, + &recipe.name, + &recipe.recipe, + fetch_only, + is_offline, + ) }; match res { @@ -1370,7 +1380,9 @@ fn main() { style::Reset, err, ); - process::exit(1); + if !nonstop { + process::exit(1); + } } } } diff --git a/src/bin/pkg_deps.rs b/src/bin/pkg_deps.rs deleted file mode 100644 index 4fddb79d9..000000000 --- a/src/bin/pkg_deps.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::env::args; - -use pkg::{ - package::{Package, PackageError}, - PackageName, -}; - -use cookbook::WALK_DEPTH; - -fn main() -> Result<(), PackageError> { - let names: Vec = args() - .skip(1) - .map(PackageName::new) - .collect::>()?; - - let packages = Package::new_recursive(&names, WALK_DEPTH)?; - for package in packages { - println!("{}", package.name); - } - - Ok(()) -} diff --git a/src/bin/repo_builder.rs b/src/bin/repo_builder.rs index 6a7a8a35d..d903bfd13 100644 --- a/src/bin/repo_builder.rs +++ b/src/bin/repo_builder.rs @@ -1,164 +1,177 @@ -use pkg::recipes; -use std::collections::{BTreeMap, 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, - } -} - -fn main() -> Result<(), Box> { - let mut args = env::args().skip(1); - let repo_dir = args - .next() - .expect("Usage: repo_builder ..."); - let recipe_list: Vec = args.collect(); - let repo_path = Path::new(&repo_dir); - - let mut appstream_sources: HashMap = HashMap::new(); - let mut packages: BTreeMap = BTreeMap::new(); - - // === 1. Push recipes in list === - for recipe in &recipe_list { - let Some(recipe_path) = recipes::find(recipe) else { - eprintln!("recipe {} not found", recipe); - continue; - }; - - let cookbook_recipe = Path::new(&recipe_path); - let target = env::var("TARGET").unwrap_or_else(|_| "x86_64-unknown-linux-gnu".into()); - let stage_dir = cookbook_recipe.join("target").join(&target).join("stage"); - - let pkgar_src = stage_dir.with_extension("pkgar"); - let pkgar_dst = repo_path.join(format!("{}.pkgar", recipe)); - let toml_src = stage_dir.with_extension("toml"); - let toml_dst = repo_path.join(format!("{}.toml", recipe)); - - if is_newer(&toml_src, &toml_dst) { - eprintln!("\x1b[01;38;5;155mrepo - publishing {}\x1b[0m", recipe); - if fs::exists(&pkgar_src)? { - fs::copy(&pkgar_src, &pkgar_dst)?; - } - fs::copy(&toml_src, &toml_dst)?; - } - - if stage_dir.join("usr/share/metainfo").exists() { - appstream_sources.insert(recipe.clone(), stage_dir.clone()); - } - } - - // === 2. Optional AppStream generation === - if env::var("APPSTREAM").ok().as_deref() == Some("1") { - eprintln!("\x1b[01;38;5;155mrepo - generating appstream data\x1b[0m"); - - let root = env::var("ROOT").unwrap_or_else(|_| ".".into()); - let target = env::var("TARGET").unwrap_or_else(|_| "x86_64-unknown-linux-gnu".into()); - let appstream_root = Path::new(&root) - .join("build") - .join(&target) - .join("appstream"); - let appstream_pkg = repo_path.join("appstream.pkgar"); - - fs::remove_dir_all(&appstream_root).ok(); - fs::remove_file(&appstream_pkg).ok(); - fs::create_dir_all(&appstream_root)?; - - if !appstream_sources.is_empty() { - let mut compose_cmd = Command::new("appstreamcli"); - compose_cmd - .arg("compose") - .arg("--origin=pkgar") - .arg(format!("--result-root={}", appstream_root.display())); - - for (_recipe, source_path) in &appstream_sources { - compose_cmd.arg(source_path); - } - - compose_cmd - .status()? - .success() - .then_some(()) - .ok_or("appstreamcli failed")?; - - Command::new("pkgar") - .arg("create") - .arg("--archive") - .arg(&appstream_pkg) - .arg("--skey") - .arg(format!("{}/build/id_ed25519.toml", root)) - .arg(&appstream_root) - .status()? - .success() - .then_some(()) - .ok_or("pkgar create failed")?; - } - } - - eprintln!("\x1b[01;38;5;155mrepo - generating repo.toml\x1b[0m"); - - // === 3. 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 parsed: Value = toml::from_str(&contents)?; - if let Some(pkg_table) = parsed.get("packages").and_then(|v| v.as_table()) { - for (k, v) in pkg_table { - if let Some(s) = v.as_str() { - packages.insert(k.clone(), format!("\"{}\"", s)); - } else { - packages.insert(k.clone(), v.to_string()); - } - } - } - } - - for entry in fs::read_dir(&repo_path)? { - let entry = entry?; - let path = entry.path(); - - if path.extension().and_then(|s| s.to_str()) != Some("toml") { - continue; - } - - if path.file_stem().and_then(|s| s.to_str()) == Some("repo") { - continue; - } - - let content = fs::read_to_string(&path)?; - let parsed: Value = toml::from_str(&content)?; - - if let Some(version_val) = parsed.get("version") { - let version_str = version_val.to_string(); // includes quotes - let package_name = path.file_stem().unwrap().to_string_lossy().to_string(); - packages.insert(package_name, version_str); - } else { - eprintln!("Warning: no [version] found in {:?}", path); - } - } - - // FIXME: Use proper TOML serializer - let mut output = String::from("[packages]\n"); - for (name, version) in &packages { - output.push_str(&format!("{name} = {version}\n")); - } - - let mut output_file = File::create(&repo_toml_path)?; - output_file.write_all(output.as_bytes())?; - - Ok(()) -} +use cookbook::WALK_DEPTH; +use pkg::{recipes, Package, PackageName}; +use std::collections::{BTreeMap, 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, + } +} + +fn main() -> Result<(), Box> { + let mut args = env::args().skip(1); + let repo_dir = args + .next() + .expect("Usage: repo_builder ..."); + let repo_path = Path::new(&repo_dir); + + // Runtime dependencies include both `[package.dependencies]` and dynamically + // linked packages discovered by auto_deps. + // + // The following adds the package dependencies of the recipes to the repo as + // well. + let recipe_list = Package::new_recursive( + &args.map(PackageName::new).collect::, _>>()?, + WALK_DEPTH, + )? + .into_iter() + .map(|pkg| pkg.name.as_str().to_owned()) + .collect::>(); + + let mut appstream_sources: HashMap = HashMap::new(); + let mut packages: BTreeMap = BTreeMap::new(); + + // === 1. Push recipes in list === + for recipe in &recipe_list { + let Some(recipe_path) = recipes::find(recipe) else { + eprintln!("recipe {} not found", recipe); + continue; + }; + + let cookbook_recipe = Path::new(&recipe_path); + let target = env::var("TARGET").unwrap_or_else(|_| "x86_64-unknown-linux-gnu".into()); + let stage_dir = cookbook_recipe.join("target").join(&target).join("stage"); + + let pkgar_src = stage_dir.with_extension("pkgar"); + let pkgar_dst = repo_path.join(format!("{}.pkgar", recipe)); + let toml_src = stage_dir.with_extension("toml"); + let toml_dst = repo_path.join(format!("{}.toml", recipe)); + + if is_newer(&toml_src, &toml_dst) { + eprintln!("\x1b[01;38;5;155mrepo - publishing {}\x1b[0m", recipe); + if fs::exists(&pkgar_src)? { + fs::copy(&pkgar_src, &pkgar_dst)?; + } + fs::copy(&toml_src, &toml_dst)?; + } + + if stage_dir.join("usr/share/metainfo").exists() { + appstream_sources.insert(recipe.clone(), stage_dir.clone()); + } + } + + // === 2. Optional AppStream generation === + if env::var("APPSTREAM").ok().as_deref() == Some("1") { + eprintln!("\x1b[01;38;5;155mrepo - generating appstream data\x1b[0m"); + + let root = env::var("ROOT").unwrap_or_else(|_| ".".into()); + let target = env::var("TARGET").unwrap_or_else(|_| "x86_64-unknown-linux-gnu".into()); + let appstream_root = Path::new(&root) + .join("build") + .join(&target) + .join("appstream"); + let appstream_pkg = repo_path.join("appstream.pkgar"); + + fs::remove_dir_all(&appstream_root).ok(); + fs::remove_file(&appstream_pkg).ok(); + fs::create_dir_all(&appstream_root)?; + + if !appstream_sources.is_empty() { + let mut compose_cmd = Command::new("appstreamcli"); + compose_cmd + .arg("compose") + .arg("--origin=pkgar") + .arg(format!("--result-root={}", appstream_root.display())); + + for (_recipe, source_path) in &appstream_sources { + compose_cmd.arg(source_path); + } + + compose_cmd + .status()? + .success() + .then_some(()) + .ok_or("appstreamcli failed")?; + + Command::new("pkgar") + .arg("create") + .arg("--archive") + .arg(&appstream_pkg) + .arg("--skey") + .arg(format!("{}/build/id_ed25519.toml", root)) + .arg(&appstream_root) + .status()? + .success() + .then_some(()) + .ok_or("pkgar create failed")?; + } + } + + eprintln!("\x1b[01;38;5;155mrepo - generating repo.toml\x1b[0m"); + + // === 3. 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 parsed: Value = toml::from_str(&contents)?; + if let Some(pkg_table) = parsed.get("packages").and_then(|v| v.as_table()) { + for (k, v) in pkg_table { + if let Some(s) = v.as_str() { + packages.insert(k.clone(), format!("\"{}\"", s)); + } else { + packages.insert(k.clone(), v.to_string()); + } + } + } + } + + for entry in fs::read_dir(&repo_path)? { + let entry = entry?; + let path = entry.path(); + + if path.extension().and_then(|s| s.to_str()) != Some("toml") { + continue; + } + + if path.file_stem().and_then(|s| s.to_str()) == Some("repo") { + continue; + } + + let content = fs::read_to_string(&path)?; + let parsed: Value = toml::from_str(&content)?; + + if let Some(version_val) = parsed.get("version") { + let version_str = version_val.to_string(); // includes quotes + let package_name = path.file_stem().unwrap().to_string_lossy().to_string(); + packages.insert(package_name, version_str); + } else { + eprintln!("Warning: no [version] found in {:?}", path); + } + } + + // FIXME: Use proper TOML serializer + let mut output = String::from("[packages]\n"); + for (name, version) in &packages { + output.push_str(&format!("{name} = {version}\n")); + } + + let mut output_file = File::create(&repo_toml_path)?; + output_file.write_all(output.as_bytes())?; + + Ok(()) +} diff --git a/unfetch.sh b/unfetch.sh index d8016a05f..6763ff824 100755 --- a/unfetch.sh +++ b/unfetch.sh @@ -5,21 +5,16 @@ source config.sh if [ $# = 0 ] then - recipes="$(target/release/list_recipes)" + recipes="$(target/release/list_recipes --short)" else recipes="$@" fi -for recipe in $recipes +for recipe_name in $recipes do - if (echo "$recipe" | grep '.*/.*' >/dev/null); then - recipe_name=$(basename "$recipe") - recipe_path="$recipe" - else - recipe_name="$recipe" - recipe_path=`target/release/find_recipe $recipe` - fi + recipe_path=`target/release/find_recipe $recipe_name` + echo -e "\033[01;38;5;215mcook - unfetch $recipe_name\033[0m" rm -rfv "$recipe_path"/source "$recipe_path"/source.tar done