better commands
This commit is contained in:
17
add.ce
17
add.ce
@@ -1,17 +1,26 @@
|
||||
// cell get <locator> [alias] - Add and install a package with its dependencies
|
||||
// cell add <locator> [alias] - Add and install a package with its dependencies
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var fd = use('fd')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell get <locator> [alias]")
|
||||
log.console("Usage: cell add <locator> [alias]")
|
||||
log.console("Examples:")
|
||||
log.console(" cell get gitea.pockle.world/john/prosperon@main")
|
||||
log.console(" cell get github.com/user/repo@v1.0.0 myalias")
|
||||
log.console(" cell add gitea.pockle.world/john/prosperon@main")
|
||||
log.console(" cell add github.com/user/repo@v1.0.0 myalias")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
var locator = args[0]
|
||||
|
||||
// Resolve relative paths to absolute paths
|
||||
if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || fd.is_dir(locator)) {
|
||||
var resolved = fd.realpath(locator)
|
||||
if (resolved) {
|
||||
locator = resolved
|
||||
}
|
||||
}
|
||||
var alias = args.length > 1 ? args[1] : null
|
||||
|
||||
shop.get(locator, alias)
|
||||
|
||||
122
clone.ce
Normal file
122
clone.ce
Normal file
@@ -0,0 +1,122 @@
|
||||
// cell clone <origin> <path>
|
||||
// Clones a cell package <origin> to the local <path>, and links it.
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var link = use('link')
|
||||
var fd = use('fd')
|
||||
var http = use('http')
|
||||
var miniz = use('miniz')
|
||||
|
||||
if (args.length < 2) {
|
||||
log.console("Usage: cell clone <origin> <path>")
|
||||
log.console("Clones a cell package to a local path and links it.")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
var origin = args[0]
|
||||
var target_path = args[1]
|
||||
|
||||
// Resolve target path to absolute
|
||||
if (target_path == '.' || target_path.startsWith('./') || target_path.startsWith('../')) {
|
||||
var resolved = fd.realpath(target_path)
|
||||
if (resolved) {
|
||||
target_path = resolved
|
||||
} else {
|
||||
// Path doesn't exist yet, resolve relative to cwd
|
||||
var cwd = fd.realpath('.')
|
||||
if (target_path == '.') {
|
||||
target_path = cwd
|
||||
} else if (target_path.startsWith('./')) {
|
||||
target_path = cwd + target_path.substring(1)
|
||||
} else if (target_path.startsWith('../')) {
|
||||
// Go up one directory from cwd
|
||||
var parent = cwd.substring(0, cwd.lastIndexOf('/'))
|
||||
target_path = parent + target_path.substring(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if target already exists
|
||||
if (fd.is_dir(target_path)) {
|
||||
log.console("Error: " + target_path + " already exists")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
log.console("Cloning " + origin + " to " + target_path + "...")
|
||||
|
||||
// Get the latest commit
|
||||
var info = shop.resolve_package_info(origin)
|
||||
if (!info || info == 'local') {
|
||||
log.console("Error: " + origin + " is not a remote package")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
// Update to get the commit hash
|
||||
var update_result = shop.update(origin)
|
||||
if (!update_result) {
|
||||
log.console("Error: Could not fetch " + origin)
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch and extract to the target path
|
||||
var lock = shop.load_lock()
|
||||
var entry = lock[origin]
|
||||
if (!entry || !entry.commit) {
|
||||
log.console("Error: No commit found for " + origin)
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
var download_url = shop.get_download_url(origin, entry.commit)
|
||||
log.console("Downloading from " + download_url)
|
||||
|
||||
try {
|
||||
var zip_blob = http.fetch(download_url)
|
||||
|
||||
// Extract zip to target path
|
||||
var zip = miniz.read(zip_blob)
|
||||
if (!zip) {
|
||||
log.console("Error: Failed to read zip archive")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
// Create target directory
|
||||
fd.mkdir(target_path)
|
||||
|
||||
var count = zip.count()
|
||||
for (var i = 0; i < count; i++) {
|
||||
if (zip.is_directory(i)) continue
|
||||
var filename = zip.get_filename(i)
|
||||
var parts = filename.split('/')
|
||||
if (parts.length <= 1) continue
|
||||
|
||||
// Skip the first directory (repo-commit prefix)
|
||||
parts.shift()
|
||||
var rel_path = parts.join('/')
|
||||
var full_path = target_path + '/' + rel_path
|
||||
var dir_path = full_path.substring(0, full_path.lastIndexOf('/'))
|
||||
|
||||
// Ensure directory exists
|
||||
if (!fd.is_dir(dir_path)) {
|
||||
fd.mkdir(dir_path)
|
||||
}
|
||||
fd.slurpwrite(full_path, zip.slurp(filename))
|
||||
}
|
||||
|
||||
log.console("Extracted to " + target_path)
|
||||
|
||||
// Link the origin to the cloned path
|
||||
link.add(origin, target_path, shop)
|
||||
log.console("Linked " + origin + " -> " + target_path)
|
||||
|
||||
} catch (e) {
|
||||
log.console("Error: " + e.message)
|
||||
if (e.stack) log.console(e.stack)
|
||||
}
|
||||
|
||||
$stop()
|
||||
54
install.ce
54
install.ce
@@ -3,6 +3,7 @@
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var build = use('build')
|
||||
var fd = use('fd')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell install <locator>")
|
||||
@@ -12,21 +13,50 @@ if (args.length < 1) {
|
||||
|
||||
var locator = args[0]
|
||||
|
||||
// Resolve relative paths to absolute paths
|
||||
// Local paths like '.' or '../foo' need to be converted to absolute paths
|
||||
if (locator == '.' || locator.startsWith('./') || locator.startsWith('../') || fd.is_dir(locator)) {
|
||||
var resolved = fd.realpath(locator)
|
||||
if (resolved) {
|
||||
locator = resolved
|
||||
}
|
||||
}
|
||||
|
||||
log.console("Installing " + locator + "...")
|
||||
if (!shop.update(locator)) {
|
||||
log.console("Failed to install " + locator)
|
||||
$stop()
|
||||
return
|
||||
|
||||
var pkg = use('package')
|
||||
|
||||
// Recursive install function that handles dependencies
|
||||
function install_package(pkg_locator, visited) {
|
||||
if (visited[pkg_locator]) return
|
||||
visited[pkg_locator] = true
|
||||
|
||||
// First, add to lock.toml
|
||||
shop.update(pkg_locator)
|
||||
|
||||
// Extract/symlink the package so we can read its cell.toml
|
||||
shop.extract(pkg_locator)
|
||||
|
||||
// Now get direct dependencies and install them first
|
||||
try {
|
||||
var deps = pkg.dependencies(pkg_locator)
|
||||
if (deps) {
|
||||
for (var alias in deps) {
|
||||
var dep_locator = deps[alias]
|
||||
log.console("Installing dependency " + dep_locator)
|
||||
install_package(dep_locator, visited)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Package might not have dependencies or cell.toml issue
|
||||
log.console("Warning: Could not read dependencies for " + pkg_locator + ": " + e.message)
|
||||
}
|
||||
|
||||
// Build the package after all dependencies are installed
|
||||
build.build_package(pkg_locator)
|
||||
}
|
||||
|
||||
var deps = shop.list_packages(locator)
|
||||
for (var dep of deps) {
|
||||
log.console("Installing dependency " + dep)
|
||||
shop.update(dep)
|
||||
build.build_package(dep)
|
||||
}
|
||||
|
||||
build.build_package(locator)
|
||||
install_package(locator, {})
|
||||
log.console("Installed " + locator)
|
||||
|
||||
$stop()
|
||||
|
||||
@@ -224,6 +224,10 @@ function get_canonical_package(alias, package_context) {
|
||||
// guaranteed to be validated
|
||||
function safe_package_path(pkg)
|
||||
{
|
||||
// For absolute paths, replace / with _ to create a valid directory name
|
||||
// Also replace @ with _
|
||||
if (pkg && pkg.startsWith('/'))
|
||||
return pkg.replaceAll('/', '_').replaceAll('@', '_')
|
||||
return pkg.replaceAll('@', '_')
|
||||
}
|
||||
|
||||
@@ -459,7 +463,15 @@ function resolve_locator(path, ctx)
|
||||
}
|
||||
|
||||
// check in ctx package
|
||||
var ctx_path = get_packages_dir() + '/' + safe_package_path(ctx) + '/' + path
|
||||
// If ctx is an absolute path (starts with /), use it directly
|
||||
// Otherwise, look it up in the packages directory
|
||||
var ctx_dir
|
||||
if (ctx.startsWith('/')) {
|
||||
ctx_dir = ctx
|
||||
} else {
|
||||
ctx_dir = get_packages_dir() + '/' + safe_package_path(ctx)
|
||||
}
|
||||
var ctx_path = ctx_dir + '/' + path
|
||||
|
||||
if (fd.is_file(ctx_path)) {
|
||||
var fn = resolve_mod_fn(ctx_path, ctx)
|
||||
@@ -818,7 +830,7 @@ function get_cache_path(pkg, commit) {
|
||||
|
||||
function get_package_abs_dir(package)
|
||||
{
|
||||
return get_packages_dir() + '/' + package
|
||||
return get_packages_dir() + '/' + safe_package_path(package)
|
||||
}
|
||||
|
||||
// Fetch the latest commit hash from remote for a package
|
||||
@@ -1195,4 +1207,29 @@ Shop.audit_packages = function() {
|
||||
return bad
|
||||
}
|
||||
|
||||
// Parse a package locator and return info about it
|
||||
// Returns { path: canonical_path, name: package_name, type: 'local'|'gitea'|null }
|
||||
Shop.parse_package = function(locator) {
|
||||
if (!locator) return null
|
||||
|
||||
// Strip version suffix if present
|
||||
var clean = locator
|
||||
if (locator.includes('@')) {
|
||||
clean = locator.split('@')[0]
|
||||
}
|
||||
|
||||
var info = Shop.resolve_package_info(clean)
|
||||
if (!info) return null
|
||||
|
||||
// Extract package name (last component of path)
|
||||
var parts = clean.split('/')
|
||||
var name = parts[parts.length - 1]
|
||||
|
||||
return {
|
||||
path: clean,
|
||||
name: name,
|
||||
type: info
|
||||
}
|
||||
}
|
||||
|
||||
return Shop
|
||||
5
link.cm
5
link.cm
@@ -20,11 +20,14 @@ function get_packages_dir() {
|
||||
|
||||
// return the safe path for the package
|
||||
function safe_package_path(pkg) {
|
||||
// For absolute paths, replace / with _ to create a valid directory name
|
||||
if (pkg && pkg.startsWith('/'))
|
||||
return pkg.replaceAll('/', '_').replaceAll('@', '_')
|
||||
return pkg.replaceAll('@', '_')
|
||||
}
|
||||
|
||||
function get_package_abs_dir(package) {
|
||||
return get_packages_dir() + '/' + package
|
||||
return get_packages_dir() + '/' + safe_package_path(package)
|
||||
}
|
||||
|
||||
function ensure_dir(path) {
|
||||
|
||||
19
package.cm
19
package.cm
@@ -4,9 +4,26 @@ var fd = use('fd')
|
||||
var toml = use('toml')
|
||||
var os = use('os')
|
||||
|
||||
// Convert package name to a safe directory name
|
||||
// For absolute paths (local packages), replace / with _
|
||||
// For remote packages, keep slashes as they use nested directories
|
||||
function safe_package_path(pkg) {
|
||||
if (!pkg) return pkg
|
||||
if (pkg.startsWith('/'))
|
||||
return pkg.replaceAll('/', '_').replaceAll('@', '_')
|
||||
return pkg.replaceAll('@', '_')
|
||||
}
|
||||
|
||||
function get_path(name)
|
||||
{
|
||||
return os.global_shop_path + '/packages/' + name
|
||||
// If name is null, return the current project directory
|
||||
if (!name)
|
||||
return fd.realpath('.')
|
||||
// If name is already an absolute path, use it directly
|
||||
if (name.startsWith('/'))
|
||||
return name
|
||||
// Remote packages use nested directories, so don't transform slashes
|
||||
return os.global_shop_path + '/packages/' + name.replaceAll('@', '_')
|
||||
}
|
||||
|
||||
package.load_config = function(name)
|
||||
|
||||
13
remove.ce
13
remove.ce
@@ -1,6 +1,7 @@
|
||||
// cell remove <alias|path> - Remove a package from dependencies or shop
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var fd = use('fd')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell remove <alias|path>")
|
||||
@@ -8,6 +9,16 @@ if (args.length < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
shop.remove(args[0])
|
||||
var pkg = args[0]
|
||||
|
||||
// Resolve relative paths to absolute paths
|
||||
if (pkg == '.' || pkg.startsWith('./') || pkg.startsWith('../') || fd.is_dir(pkg)) {
|
||||
var resolved = fd.realpath(pkg)
|
||||
if (resolved) {
|
||||
pkg = resolved
|
||||
}
|
||||
}
|
||||
|
||||
shop.remove(pkg)
|
||||
|
||||
$stop()
|
||||
|
||||
81
search.ce
Normal file
81
search.ce
Normal file
@@ -0,0 +1,81 @@
|
||||
// cell search <query>
|
||||
// Searches for packages matching <query>, or actors or modules within them.
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var pkg = use('package')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell search <query>")
|
||||
log.console("Searches for packages, actors, or modules matching the query.")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
var query = args[0].toLowerCase()
|
||||
var found_packages = []
|
||||
var found_modules = []
|
||||
var found_actors = []
|
||||
|
||||
// Search through all installed packages
|
||||
var packages = shop.list_packages()
|
||||
|
||||
for (var package_name of packages) {
|
||||
// Check if package name matches
|
||||
if (package_name.toLowerCase().includes(query)) {
|
||||
found_packages.push(package_name)
|
||||
}
|
||||
|
||||
// Search modules and actors within the package
|
||||
try {
|
||||
var modules = pkg.list_modules(package_name)
|
||||
for (var mod of modules) {
|
||||
if (mod.toLowerCase().includes(query)) {
|
||||
found_modules.push(package_name + ':' + mod)
|
||||
}
|
||||
}
|
||||
|
||||
var actors = pkg.list_programs(package_name)
|
||||
for (var actor of actors) {
|
||||
if (actor.toLowerCase().includes(query)) {
|
||||
found_actors.push(package_name + ':' + actor)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Skip packages that can't be read
|
||||
}
|
||||
}
|
||||
|
||||
// Print results
|
||||
var total = found_packages.length + found_modules.length + found_actors.length
|
||||
|
||||
if (total == 0) {
|
||||
log.console("No results found for '" + query + "'")
|
||||
} else {
|
||||
log.console("Found " + text(total) + " result(s) for '" + query + "':")
|
||||
log.console("")
|
||||
|
||||
if (found_packages.length > 0) {
|
||||
log.console("Packages:")
|
||||
for (var p of found_packages) {
|
||||
log.console(" " + p)
|
||||
}
|
||||
log.console("")
|
||||
}
|
||||
|
||||
if (found_modules.length > 0) {
|
||||
log.console("Modules:")
|
||||
for (var m of found_modules) {
|
||||
log.console(" " + m)
|
||||
}
|
||||
log.console("")
|
||||
}
|
||||
|
||||
if (found_actors.length > 0) {
|
||||
log.console("Actors:")
|
||||
for (var a of found_actors) {
|
||||
log.console(" " + a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stop()
|
||||
33
unlink.ce
Normal file
33
unlink.ce
Normal file
@@ -0,0 +1,33 @@
|
||||
// cell unlink <origin>
|
||||
// Unlinks <origin> from its <target> from a previous link.
|
||||
|
||||
var link = use('link')
|
||||
var shop = use('internal/shop')
|
||||
|
||||
if (args.length < 1) {
|
||||
log.console("Usage: cell unlink <origin>")
|
||||
log.console("Removes a link and restores the original package.")
|
||||
$stop()
|
||||
return
|
||||
}
|
||||
|
||||
var origin = args[0]
|
||||
|
||||
if (link.remove(origin)) {
|
||||
log.console("Removed link for " + origin)
|
||||
|
||||
// Try to restore the original package
|
||||
log.console("Restoring " + origin + "...")
|
||||
try {
|
||||
shop.fetch(origin)
|
||||
shop.extract(origin)
|
||||
log.console("Restored " + origin)
|
||||
} catch (e) {
|
||||
log.console("Could not restore: " + e.message)
|
||||
log.console("Run 'cell update " + origin + "' to restore")
|
||||
}
|
||||
} else {
|
||||
log.console("No link found for " + origin)
|
||||
}
|
||||
|
||||
$stop()
|
||||
19
update.ce
19
update.ce
@@ -9,6 +9,7 @@
|
||||
// cell update <package> - Update a specific package
|
||||
|
||||
var shop = use('internal/shop')
|
||||
var fd = use('fd')
|
||||
|
||||
var target_pkg = null
|
||||
|
||||
@@ -26,6 +27,13 @@ for (var i = 0; i < args.length; i++) {
|
||||
$stop()
|
||||
} else if (!args[i].startsWith('-')) {
|
||||
target_pkg = args[i]
|
||||
// Resolve relative paths to absolute paths
|
||||
if (target_pkg == '.' || target_pkg.startsWith('./') || target_pkg.startsWith('../') || fd.is_dir(target_pkg)) {
|
||||
var resolved = fd.realpath(target_pkg)
|
||||
if (resolved) {
|
||||
target_pkg = resolved
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +45,16 @@ function update_and_fetch(pkg)
|
||||
|
||||
var new_entry = shop.update(pkg)
|
||||
|
||||
if (new_entry && new_entry.commit) {
|
||||
log.console(" " + pkg + " " + old_commit.substring(0, 8) + " -> " + new_entry.commit.substring(0, 8))
|
||||
if (new_entry) {
|
||||
if (new_entry.commit) {
|
||||
var old_str = old_commit ? old_commit.substring(0, 8) : "(new)"
|
||||
log.console(" " + pkg + " " + old_str + " -> " + new_entry.commit.substring(0, 8))
|
||||
shop.fetch(pkg)
|
||||
} else {
|
||||
// Local package - just ensure symlink is correct
|
||||
log.console(" " + pkg + " (local)")
|
||||
}
|
||||
shop.extract(pkg)
|
||||
shop.build_package_scripts(pkg)
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user