// cell clean [] - Remove cached material to force refetch/rebuild // // Usage: // cell clean Clean build outputs for current directory package // cell clean . Clean build outputs for current directory package // cell clean Clean build outputs for specific package // cell clean shop Clean entire shop // cell clean world Clean all world packages // // Options: // --build Remove build outputs only (default) // --fetch Remove fetched sources only // --all Remove both build outputs and fetched sources // --deep Apply to full dependency closure // --dry-run Show what would be deleted var shop = use('internal/shop') var pkg = use('package') var fd = use('fd') var scope = null var clean_build = false var clean_fetch = false var deep = false var dry_run = false for (var i = 0; i < length(args); i++) { if (args[i] == '--build') { clean_build = true } else if (args[i] == '--fetch') { clean_fetch = true } else if (args[i] == '--all') { clean_build = true clean_fetch = true } else if (args[i] == '--deep') { deep = true } else if (args[i] == '--dry-run') { dry_run = true } else if (args[i] == '--help' || args[i] == '-h') { log.console("Usage: cell clean [] [options]") log.console("") log.console("Remove cached material to force refetch/rebuild.") log.console("") log.console("Scopes:") log.console(" Clean specific package") log.console(" shop Clean entire shop") log.console(" world Clean all world packages") log.console("") log.console("Options:") log.console(" --build Remove build outputs only (default)") log.console(" --fetch Remove fetched sources only") log.console(" --all Remove both build outputs and fetched sources") log.console(" --deep Apply to full dependency closure") log.console(" --dry-run Show what would be deleted") $stop() } else if (!starts_with(args[i], '-')) { scope = args[i] } } // Default to --build if nothing specified if (!clean_build && !clean_fetch) { clean_build = true } // Default scope to current directory if (!scope) { scope = '.' } // Resolve local paths for single package scope var is_shop_scope = (scope == 'shop') var is_world_scope = (scope == 'world') if (!is_shop_scope && !is_world_scope) { if (scope == '.' || starts_with(scope, './') || starts_with(scope, '../') || fd.is_dir(scope)) { var resolved = fd.realpath(scope) if (resolved) { scope = resolved } } } var files_to_delete = [] var dirs_to_delete = [] // Gather packages to clean var packages_to_clean = [] if (is_shop_scope) { packages_to_clean = shop.list_packages() } else if (is_world_scope) { // For now, world is the same as shop packages_to_clean = shop.list_packages() } else { // Single package push(packages_to_clean, scope) if (deep) { try { var deps = pkg.gather_dependencies(scope) arrfor(deps, function(dep) { push(packages_to_clean, dep) }) } catch (e) { // Skip if can't read dependencies } } } // Gather files to clean var lib_dir = shop.get_lib_dir() var build_dir = shop.get_build_dir() var packages_dir = replace(shop.get_package_dir(''), /\/$/, '') // Get base packages dir if (clean_build) { if (is_shop_scope) { // Clean entire build and lib directories if (fd.is_dir(build_dir)) { push(dirs_to_delete, build_dir) } if (fd.is_dir(lib_dir)) { push(dirs_to_delete, lib_dir) } } else { // Clean specific package libraries arrfor(packages_to_clean, function(p) { if (p == 'core') return var lib_name = shop.lib_name_for_package(p) var dylib_ext = '.dylib' var lib_path = lib_dir + '/' + lib_name + dylib_ext if (fd.is_file(lib_path)) { push(files_to_delete, lib_path) } // Also check for .so and .dll var so_path = lib_dir + '/' + lib_name + '.so' var dll_path = lib_dir + '/' + lib_name + '.dll' if (fd.is_file(so_path)) { push(files_to_delete, so_path) } if (fd.is_file(dll_path)) { push(files_to_delete, dll_path) } }) } } if (clean_fetch) { if (is_shop_scope) { // Clean entire packages directory (dangerous!) if (fd.is_dir(packages_dir)) { push(dirs_to_delete, packages_dir) } } else { // Clean specific package directories arrfor(packages_to_clean, function(p) { if (p == 'core') return var pkg_dir = shop.get_package_dir(p) if (fd.is_dir(pkg_dir) || fd.is_link(pkg_dir)) { push(dirs_to_delete, pkg_dir) } }) } } // Execute or report if (dry_run) { log.console("Would delete:") if (length(files_to_delete) == 0 && length(dirs_to_delete) == 0) { log.console(" (nothing to clean)") } else { arrfor(files_to_delete, function(f) { log.console(" [file] " + f) }) arrfor(dirs_to_delete, function(d) { log.console(" [dir] " + d) }) } } else { var deleted_count = 0 arrfor(files_to_delete, function(f) { try { fd.unlink(f) log.console("Deleted: " + f) deleted_count++ } catch (e) { log.error("Failed to delete " + f + ": " + e) } }) arrfor(dirs_to_delete, function(d) { try { if (fd.is_link(d)) { fd.unlink(d) } else { fd.rmdir(d, 1) // recursive } log.console("Deleted: " + d) deleted_count++ } catch (e) { log.error("Failed to delete " + d + ": " + e) } }) if (deleted_count == 0) { log.console("Nothing to clean.") } else { log.console("") log.console("Clean complete: " + text(deleted_count) + " item(s) deleted.") } } $stop()