package resolution
This commit is contained in:
@@ -1224,7 +1224,18 @@ if (prog_info) {
|
||||
}
|
||||
|
||||
$_.clock(_ => {
|
||||
var file_info = shop.file_info ? shop.file_info(prog_path) : null
|
||||
var _file_info_ok = false
|
||||
var file_info = null
|
||||
var _try_fi = function() {
|
||||
file_info = shop.file_info ? shop.file_info(prog_path) : null
|
||||
_file_info_ok = true
|
||||
} disruption {}
|
||||
_try_fi()
|
||||
if (!_file_info_ok || !file_info)
|
||||
file_info = {path: prog_path, is_module: false, is_actor: true, package: null, name: prog}
|
||||
// If the unified resolver found the package, use that as the authoritative source
|
||||
if (prog_info && prog_info.pkg)
|
||||
file_info.package = prog_info.pkg
|
||||
var inject = shop.script_inject_for ? shop.script_inject_for(file_info) : []
|
||||
|
||||
// Build env with runtime functions + capability injections
|
||||
@@ -1278,10 +1289,22 @@ $_.clock(_ => {
|
||||
|
||||
env.use = function(path) {
|
||||
var ck = 'core/' + path
|
||||
var _use_core_result = null
|
||||
var _use_core_ok = false
|
||||
if (use_cache[ck]) return use_cache[ck]
|
||||
var core_mod = use_core(path)
|
||||
if (core_mod) return core_mod
|
||||
return shop.use(path, pkg)
|
||||
var _try_core = function() {
|
||||
_use_core_result = use_core(path)
|
||||
_use_core_ok = true
|
||||
} disruption {}
|
||||
_try_core()
|
||||
if (_use_core_ok && _use_core_result) return _use_core_result
|
||||
var _shop_use = function() {
|
||||
return shop.use(path, pkg)
|
||||
} disruption {
|
||||
log.error(`use('${path}') failed (package: ${pkg})`)
|
||||
disrupt
|
||||
}
|
||||
return _shop_use()
|
||||
}
|
||||
env.args = _cell.args.arg
|
||||
env.log = log
|
||||
|
||||
@@ -137,9 +137,6 @@ function split_explicit_package_import(path)
|
||||
|
||||
if (package_in_shop(pkg_candidate))
|
||||
return {package: pkg_candidate, path: mod_path}
|
||||
|
||||
if (Shop.resolve_package_info(pkg_candidate))
|
||||
return {package: pkg_candidate, path: mod_path}
|
||||
}
|
||||
|
||||
return null
|
||||
@@ -158,6 +155,8 @@ function abs_path_to_package(package_dir)
|
||||
}
|
||||
|
||||
var packages_prefix = get_packages_dir() + '/'
|
||||
var packages_prefix_abs = fd.realpath(get_packages_dir())
|
||||
if (packages_prefix_abs) packages_prefix_abs = packages_prefix_abs + '/'
|
||||
var core_dir = packages_prefix + core_package
|
||||
|
||||
// Check if this is the core package directory (or its symlink target)
|
||||
@@ -176,6 +175,10 @@ function abs_path_to_package(package_dir)
|
||||
if (starts_with(package_dir, packages_prefix))
|
||||
return text(package_dir, length(packages_prefix))
|
||||
|
||||
// Also try absolute path comparison (package_dir may be absolute, packages_prefix relative)
|
||||
if (packages_prefix_abs && starts_with(package_dir, packages_prefix_abs))
|
||||
return text(package_dir, length(packages_prefix_abs))
|
||||
|
||||
// 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)
|
||||
@@ -344,9 +347,11 @@ function get_policy() {
|
||||
|
||||
// Get information about how to resolve a package
|
||||
// Local packages always start with /
|
||||
// Remote packages must be exactly host/owner/repo (3 components)
|
||||
Shop.resolve_package_info = function(pkg) {
|
||||
if (starts_with(pkg, '/')) return 'local'
|
||||
if (search(pkg, 'gitea') != null) return 'gitea'
|
||||
var parts = array(pkg, '/')
|
||||
if (length(parts) == 3 && search(parts[0], 'gitea') != null) return 'gitea'
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1349,25 +1354,78 @@ Shop.resolve_program = function(prog, package_context) {
|
||||
})
|
||||
|
||||
// If not in lock, check if this looks like a fetchable package
|
||||
if (!best_pkg) {
|
||||
for (i = length(parts) - 1; i >= 1; i--) {
|
||||
candidate = text(array(parts, 0, i), '/')
|
||||
pkg_info = Shop.resolve_package_info(candidate)
|
||||
if (pkg_info && pkg_info != 'local') {
|
||||
best_pkg = candidate
|
||||
best_remainder = text(array(parts, i), '/')
|
||||
break
|
||||
}
|
||||
// For gitea-style URLs, the package root is host/owner/repo (3 components)
|
||||
if (!best_pkg && length(parts) > 3) {
|
||||
candidate = text(array(parts, 0, 3), '/')
|
||||
pkg_info = Shop.resolve_package_info(candidate)
|
||||
if (pkg_info && pkg_info != 'local') {
|
||||
best_pkg = candidate
|
||||
best_remainder = text(array(parts, 3), '/')
|
||||
}
|
||||
}
|
||||
|
||||
if (best_pkg && best_remainder) {
|
||||
log.console('fetching ' + best_pkg + '...')
|
||||
_auto = function() {
|
||||
// Install the package itself first
|
||||
Shop.update(best_pkg)
|
||||
Shop.fetch(best_pkg)
|
||||
Shop.extract(best_pkg)
|
||||
// Install dependencies iteratively (each dep must be extracted before reading its deps)
|
||||
var all_deps = {}
|
||||
var queue = [best_pkg]
|
||||
var qi = 0
|
||||
var current = null
|
||||
var direct_deps = null
|
||||
var dep_locator = null
|
||||
var dep_dir = null
|
||||
var build_mod = null
|
||||
var target = null
|
||||
var _build_c = null
|
||||
var _read_deps = null
|
||||
while (qi < length(queue)) {
|
||||
current = queue[qi]
|
||||
qi = qi + 1
|
||||
_read_deps = function() {
|
||||
direct_deps = pkg_tools.dependencies(current)
|
||||
} disruption {
|
||||
direct_deps = null
|
||||
}
|
||||
_read_deps()
|
||||
if (direct_deps) {
|
||||
arrfor(array(direct_deps), function(alias) {
|
||||
dep_locator = direct_deps[alias]
|
||||
if (!all_deps[dep_locator]) {
|
||||
all_deps[dep_locator] = true
|
||||
dep_dir = pkg_tools.get_dir(dep_locator)
|
||||
if (!fd.is_dir(dep_dir)) {
|
||||
log.console(' installing dependency: ' + dep_locator)
|
||||
Shop.update(dep_locator)
|
||||
Shop.fetch(dep_locator)
|
||||
Shop.extract(dep_locator)
|
||||
}
|
||||
push(queue, dep_locator)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// Build scripts for all packages
|
||||
Shop.build_package_scripts(best_pkg)
|
||||
arrfor(array(all_deps), function(dep) {
|
||||
Shop.build_package_scripts(dep)
|
||||
})
|
||||
// Build C modules
|
||||
build_mod = use_cache['core/build']
|
||||
if (build_mod) {
|
||||
_build_c = function() {
|
||||
target = build_mod.detect_host_target()
|
||||
arrfor(array(all_deps), function(dep) {
|
||||
build_mod.build_dynamic(dep, target, 'release')
|
||||
})
|
||||
build_mod.build_dynamic(best_pkg, target, 'release')
|
||||
} disruption {}
|
||||
_build_c()
|
||||
}
|
||||
} disruption {
|
||||
return null
|
||||
}
|
||||
@@ -1600,10 +1658,16 @@ function get_package_zip(pkg)
|
||||
// Update: Check for new version, update lock, fetch and extract
|
||||
// Returns the new lock entry if updated, null if already up to date or failed
|
||||
Shop.update = function(pkg) {
|
||||
Shop.verify_package_name(pkg)
|
||||
var lock = Shop.load_lock()
|
||||
var lock_entry = lock[pkg]
|
||||
var info = Shop.resolve_package_info(pkg)
|
||||
|
||||
if (!info) {
|
||||
log.error("Not a valid package locator: " + pkg)
|
||||
return null
|
||||
}
|
||||
|
||||
log.shop(`checking ${pkg}`)
|
||||
|
||||
var new_entry = null
|
||||
|
||||
Reference in New Issue
Block a user