var shop = use('internal/shop') var pkg = use('package') if (!args || length(args) < 1) { log.console("Usage: cell why ") $stop() } 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_deps(current_pkg, stack) { var deps = pkg.dependencies(current_pkg) var aliases = sort(array(deps)) var i = 0 var alias = null var locator = null var parsed = null var canon = null var locator_clean = null var match = false var node = null var new_stack = null var cycle = false var j = 0 for (i = 0; i < length(aliases); i++) { alias = aliases[i] locator = deps[alias] parsed = shop.parse_package(locator) if (!parsed) continue canon = parsed.path 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) match = (alias == target) || (parsed.name == target) || (canon == target) || (canon == target_clean) || (locator == target) || (locator_clean == target) node = { alias: alias, pkg: canon, locator: locator } 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) cycle = false for (j = 0; j < length(stack); j++) { if (stack[j].pkg == canon) { cycle = true break } } if (!cycle) { search_deps(canon, new_stack) } } } function print_stack(stack) { // Calculate max width for alignment if needed, but simple tree is fine var output = "project" var i = 0 var node = null var indent = null var j = 0 var info = null log.console(output) for (i = 0; i < length(stack); i++) { node = stack[i] indent = "" for (j = 0; j <= i; j++) indent += " " 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_deps(null, []) if (!found) { log.console("Package '" + target + "' not found in dependency tree.") } $stop()