This commit is contained in:
2026-01-09 07:36:48 -06:00
parent d044bde4f9
commit e04b15973a
3 changed files with 108 additions and 9 deletions

View File

@@ -79,12 +79,20 @@ log.console("Installing " + locator + "...")
// Gather all packages that will be installed
var packages_to_install = []
var skipped_packages = []
var visited = {}
function gather_packages(pkg_locator) {
if (visited[pkg_locator]) return
visited[pkg_locator] = true
// Check if this is a local path that doesn't exist
if (pkg_locator.startsWith('/') && !fd.is_dir(pkg_locator)) {
skipped_packages.push(pkg_locator)
log.console(" Skipping missing local package: " + pkg_locator)
return
}
packages_to_install.push(pkg_locator)
// Try to read dependencies
@@ -123,6 +131,13 @@ if (dry_run) {
var exists = lock[p] != null
log.console(" " + p + (exists ? " (already installed)" : ""))
}
if (skipped_packages.length > 0) {
log.console("")
log.console("Would skip (missing local paths):")
for (var p of skipped_packages) {
log.console(" " + p)
}
}
$stop()
}
@@ -150,6 +165,10 @@ for (var p of packages_to_install) {
install_package(p)
}
log.console("Installed " + text(packages_to_install.length) + " package(s).")
var summary = "Installed " + text(packages_to_install.length) + " package(s)."
if (skipped_packages.length > 0) {
summary += " Skipped " + text(skipped_packages.length) + " missing local path(s)."
}
log.console(summary)
$stop()

View File

@@ -161,6 +161,13 @@ function abs_path_to_package(package_dir)
if (package_dir.startsWith(packages_prefix))
return package_dir.substring(packages_prefix.length)
// Check if this local path is the target of a link
// If so, return the canonical package name (link origin) instead
var link_origin = link.get_origin(package_dir)
if (link_origin) {
return link_origin
}
// in this case, the dir is the package
if (package_in_shop(package_dir))
return package_dir
@@ -987,6 +994,11 @@ Shop.update = function(pkg) {
log.console(`checking ${pkg}`)
if (info == 'local') {
// Check if local path exists
if (!fd.is_dir(pkg)) {
log.console(` Local path does not exist: ${pkg}`)
return null
}
// Local packages always get a lock entry
var new_entry = {
type: 'local',

84
link.cm
View File

@@ -90,7 +90,7 @@ Link.add = function(canonical, target, shop) {
if (!lock[canonical]) {
throw new Error('Package ' + canonical + ' is not installed. Install it first with: cell get ' + canonical)
}
// Validate target is a valid package
if (target.startsWith('/')) {
// Local path - must have cell.toml
@@ -101,14 +101,44 @@ Link.add = function(canonical, target, shop) {
// Remote package target - ensure it's installed
shop.get(target)
}
var links = Link.load()
links[canonical] = target
Link.save(links)
// Create the symlink immediately
Link.sync_one(canonical, target, shop)
// Install dependencies of the linked package
// Read the target's cell.toml to find its dependencies
var target_path = target.startsWith('/') ? target : get_package_abs_dir(target)
var toml_path = target_path + '/cell.toml'
if (fd.is_file(toml_path)) {
try {
var content = text(fd.slurp(toml_path))
var cfg = toml.decode(content)
if (cfg.dependencies) {
for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist
if (dep_locator.startsWith('/') && !fd.is_dir(dep_locator)) {
log.console(" Skipping missing local dependency: " + dep_locator)
continue
}
// Install the dependency if not already in shop
try {
shop.get(dep_locator)
shop.extract(dep_locator)
} catch (e) {
log.console(" Warning: Could not install dependency " + dep_locator + ": " + e.message)
}
}
}
} catch (e) {
log.console(" Warning: Could not read dependencies from " + toml_path)
}
}
log.console("Linked " + canonical + " -> " + target)
return true
}
@@ -177,12 +207,12 @@ Link.sync_one = function(canonical, target, shop) {
return true
}
// Sync all links - ensure all symlinks are in place
// Sync all links - ensure all symlinks are in place and dependencies are installed
Link.sync_all = function(shop) {
var links = Link.load()
var count = 0
var errors = []
for (var canonical in links) {
var target = links[canonical]
try {
@@ -196,14 +226,40 @@ Link.sync_all = function(shop) {
errors.push(canonical + ': target ' + link_target + ' is not a valid package')
continue
}
Link.sync_one(canonical, target, shop)
// Install dependencies of the linked package
var toml_path = link_target + '/cell.toml'
try {
var content = text(fd.slurp(toml_path))
var cfg = toml.decode(content)
if (cfg.dependencies) {
for (var alias in cfg.dependencies) {
var dep_locator = cfg.dependencies[alias]
// Skip local dependencies that don't exist
if (dep_locator.startsWith('/') && !fd.is_dir(dep_locator)) {
continue
}
// Install the dependency if not already in shop
try {
shop.get(dep_locator)
shop.extract(dep_locator)
} catch (e) {
// Silently continue - dependency may already be installed
}
}
}
} catch (e) {
// Could not read dependencies - continue anyway
}
count++
} catch (e) {
errors.push(canonical + ': ' + e.message)
}
}
return { synced: count, errors: errors }
}
@@ -219,4 +275,16 @@ Link.get_target = function(canonical) {
return links[canonical] || null
}
// Get the canonical package name that links to this target (reverse lookup)
// Returns null if no package links to this target
Link.get_origin = function(target) {
var links = Link.load()
for (var origin in links) {
if (links[origin] == target) {
return origin
}
}
return null
}
return Link