From 027c1549fcbfd42f7099cb09e6cc760259c44cbb Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Tue, 17 Feb 2026 10:52:36 -0600 Subject: [PATCH] recursive add and install --- add.ce | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- install.ce | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 170 insertions(+), 8 deletions(-) diff --git a/add.ce b/add.ce index 7a8a866d..28010596 100644 --- a/add.ce +++ b/add.ce @@ -3,6 +3,7 @@ // Usage: // cell add Add a dependency using default alias // cell add Add a dependency with custom alias +// cell add -r Recursively find and add all packages in directory // // This adds the dependency to cell.toml and installs it to the shop. @@ -17,6 +18,11 @@ var resolved = null var parts = null var cwd = null var build_target = null +var recursive = false +var locators = null +var added = 0 +var failed = 0 +var summary = null array(args, function(arg) { if (arg == '--help' || arg == '-h') { @@ -28,7 +34,10 @@ array(args, function(arg) { log.console(" cell add gitea.pockle.world/john/prosperon") log.console(" cell add gitea.pockle.world/john/cell-image image") log.console(" cell add ../local-package") + log.console(" cell add -r ../packages") $stop() + } else if (arg == '-r') { + recursive = true } else if (!starts_with(arg, '-')) { if (!locator) { locator = arg @@ -38,13 +47,13 @@ array(args, function(arg) { } }) -if (!locator) { +if (!locator && !recursive) { log.console("Usage: cell add [alias]") $stop() } // Resolve relative paths to absolute paths -if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator)) { +if (locator && (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator))) { resolved = fd.realpath(locator) if (resolved) { locator = resolved @@ -52,7 +61,7 @@ if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') } // Generate default alias from locator -if (!alias) { +if (!alias && locator) { // Use the last component of the locator as alias parts = array(locator, '/') alias = parts[length(parts) - 1] @@ -69,6 +78,80 @@ if (!fd.is_file(cwd + '/cell.toml')) { $stop() } +// Recursively find all cell packages in a directory +function find_packages(dir) { + var found = [] + var list = fd.readdir(dir) + if (!list) return found + if (fd.is_file(dir + '/cell.toml')) { + push(found, dir) + } + arrfor(list, function(item) { + if (item == '.' || item == '..' || item == '.cell' || item == '.git') return + var full = dir + '/' + item + var st = fd.stat(full) + var sub = null + if (st && st.isDirectory) { + sub = find_packages(full) + arrfor(sub, function(p) { + push(found, p) + }) + } + }) + return found +} + +// If -r flag, find all packages recursively and add each +if (recursive) { + if (!locator) { + locator = '.' + } + resolved = fd.realpath(locator) + if (!resolved || !fd.is_dir(resolved)) { + log.error(`${locator} is not a directory`) + $stop() + } + locators = find_packages(resolved) + if (length(locators) == 0) { + log.console("No packages found in " + resolved) + $stop() + } + log.console(`Found ${text(length(locators))} package(s) in ${resolved}`) + + arrfor(locators, function(loc) { + // Generate alias from directory name + var loc_parts = array(loc, '/') + var loc_alias = loc_parts[length(loc_parts) - 1] + + log.console(" Adding " + loc + " as '" + loc_alias + "'...") + var _add = function() { + pkg.add_dependency(null, loc, loc_alias) + shop.get(loc) + shop.extract(loc) + shop.build_package_scripts(loc) + var _build_c = function() { + build_target = build.detect_host_target() + build.build_dynamic(loc, build_target, 'release') + } disruption { + // Not all packages have C code + } + _build_c() + added++ + } disruption { + log.console(` Warning: Failed to add ${loc}`) + failed++ + } + _add() + }) + + summary = "Added " + text(added) + " package(s)." + if (failed > 0) { + summary += " Failed: " + text(failed) + "." + } + log.console(summary) + $stop() +} + log.console("Adding " + locator + " as '" + alias + "'...") // Add to local project's cell.toml diff --git a/install.ce b/install.ce index 01c98fd6..05fb3df5 100644 --- a/install.ce +++ b/install.ce @@ -8,6 +8,7 @@ // --target Build for target platform // --refresh Refresh floating refs before locking // --dry-run Show what would be installed +// -r Recursively find and install all packages in directory var shop = use('internal/shop') var build = use('build') @@ -21,6 +22,7 @@ if (length(args) < 1) { log.console(" --target Build for target platform") log.console(" --refresh Refresh floating refs before locking") log.console(" --dry-run Show what would be installed") + log.console(" -r Recursively find and install all packages in directory") $stop() } @@ -28,8 +30,10 @@ var locator = null var target_triple = null var refresh = false var dry_run = false +var recursive = false var i = 0 var resolved = null +var locators = null for (i = 0; i < length(args); i++) { if (args[i] == '--target' || args[i] == '-t') { @@ -43,6 +47,8 @@ for (i = 0; i < length(args); i++) { refresh = true } else if (args[i] == '--dry-run') { dry_run = true + } else if (args[i] == '-r') { + recursive = true } else if (args[i] == '--help' || args[i] == '-h') { log.console("Usage: cell install [options]") log.console("") @@ -52,38 +58,111 @@ for (i = 0; i < length(args); i++) { log.console(" --target Build for target platform") log.console(" --refresh Refresh floating refs before locking") log.console(" --dry-run Show what would be installed") + log.console(" -r Recursively find and install all packages in directory") $stop() } else if (!starts_with(args[i], '-')) { locator = args[i] } } -if (!locator) { +if (!locator && !recursive) { log.console("Usage: cell install ") $stop() } // Resolve relative paths to absolute paths // Local paths like '.' or '../foo' need to be converted to absolute paths -if (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator)) { +if (locator && (locator == '.' || starts_with(locator, './') || starts_with(locator, '../') || fd.is_dir(locator))) { resolved = fd.realpath(locator) if (resolved) { locator = resolved } } +// Recursively find all cell packages in a directory +function find_packages(dir) { + var found = [] + var list = fd.readdir(dir) + if (!list) return found + if (fd.is_file(dir + '/cell.toml')) { + push(found, dir) + } + arrfor(list, function(item) { + if (item == '.' || item == '..' || item == '.cell' || item == '.git') return + var full = dir + '/' + item + var st = fd.stat(full) + var sub = null + if (st && st.isDirectory) { + sub = find_packages(full) + arrfor(sub, function(p) { + push(found, p) + }) + } + }) + return found +} + +// If -r flag, find all packages recursively and install each +if (recursive) { + if (!locator) { + locator = '.' + } + resolved = fd.realpath(locator) + if (!resolved || !fd.is_dir(resolved)) { + log.error(`${locator} is not a directory`) + $stop() + } + locators = find_packages(resolved) + if (length(locators) == 0) { + log.console("No packages found in " + resolved) + $stop() + } + log.console(`Found ${text(length(locators))} package(s) in ${resolved}`) +} + // Default target if (!target_triple) { target_triple = build.detect_host_target() } -log.console("Installing " + locator + "...") - // Gather all packages that will be installed var packages_to_install = [] var skipped_packages = [] +var summary = null var visited = {} +// Recursive mode: install all found packages and exit +if (recursive) { + arrfor(locators, function(loc) { + log.console(" Installing " + loc + "...") + var _inst = function() { + shop.update(loc) + shop.extract(loc) + shop.build_package_scripts(loc) + var _build_c = function() { + build.build_dynamic(loc, target_triple, 'release') + } disruption { + // Not all packages have C code + } + _build_c() + push(packages_to_install, loc) + } disruption { + push(skipped_packages, loc) + log.console(` Warning: Failed to install ${loc}`) + } + _inst() + }) + + summary = "Installed " + text(length(packages_to_install)) + " package(s)." + if (length(skipped_packages) > 0) { + summary += " Failed: " + text(length(skipped_packages)) + "." + } + log.console(summary) + $stop() +} + +log.console("Installing " + locator + "...") + function gather_packages(pkg_locator) { var lock = null var update_result = null @@ -183,7 +262,7 @@ arrfor(packages_to_install, function(p) { install_package(p) }) -var summary = "Installed " + text(length(packages_to_install)) + " package(s)." +summary = "Installed " + text(length(packages_to_install)) + " package(s)." if (length(skipped_packages) > 0) { summary += " Skipped " + text(length(skipped_packages)) + " missing local path(s)." }