Files
cell/why.ce
2026-01-18 10:35:05 -06:00

108 lines
2.9 KiB
Plaintext

var shop = use('internal/shop')
var pkg = use('package')
if (!args || length(args) < 1) {
log.console("Usage: cell why <package>")
$stop()
return
}
var target = args[0]
log.console("Searching for '" + target + "'...")
var target_clean = target
if (starts_with(target_clean, '/')) target_clean = text(target_clean, 1)
var found = false
// DFS to find paths
// current_pkg: canonical path of current package (null for root)
// stack: array of {alias, pkg} leading to current_pkg
function search(current_pkg, stack) {
var deps = pkg.dependencies(current_pkg)
// Sort for consistent output
var aliases = sort(array(deps))
for (var i = 0; i < length(aliases); i++) {
var alias = aliases[i]
var locator = deps[alias]
var parsed = shop.parse_package(locator)
if (!parsed) continue
var canon = parsed.path
var locator_clean = locator
if (search(locator, '@') != null) locator_clean = array(locator, '@')[0]
// Check if match
// 1. Alias matches
// 2. Package name matches
// 3. Canonical path matches (exact or clean)
// 4. Locator matches (exact or clean)
var match = (alias == target) ||
(parsed.name == target) ||
(canon == target) ||
(canon == target_clean) ||
(locator == target) ||
(locator_clean == target)
var node = { alias: alias, pkg: canon, locator: locator }
var new_stack = stack.concat([node])
if (match) {
found = true
print_stack(new_stack)
// Don't recurse if we found the target in this branch
continue
}
// Recurse if not seen in current stack (cycle detection)
var cycle = false
for (var j = 0; j < length(stack); j++) {
if (stack[j].pkg == canon) {
cycle = true
break
}
}
if (!cycle) {
search(canon, new_stack)
}
}
}
function print_stack(stack) {
// Calculate max width for alignment if needed, but simple tree is fine
var output = "project"
log.console(output)
for (var i = 0; i < length(stack); i++) {
var node = stack[i]
var indent = ""
for (var j = 0; j <= i; j++) indent += " "
var info = node.locator
if (node.alias != parsed_name(node.locator)) {
// info += " (aliased as " + node.alias + ")"
}
log.console(indent + "-> " + node.alias + " (" + info + ")")
}
log.console("")
}
function parsed_name(locator) {
var parsed = shop.parse_package(locator)
return parsed ? parsed.name : ""
}
search(null, [])
if (!found) {
log.console("Package '" + target + "' not found in dependency tree.")
}
$stop()