do
if package_id.is_package_name then
# Ask a centralized server
- # TODO choose a future safe URL
# TODO customizable server list
# TODO parse ini file in memory
- var url = "https://xymus.net/nitpm/{package_id}.ini"
+ var url = "https://nitlanguage.org/catalog/p/{package_id}.ini"
var ini_path = "/tmp/{package_id}.ini"
if verbose then print "Looking for a package description at '{url}'"
super Command
redef fun name do return "uninstall"
- redef fun usage do return "nitpm uninstall <package>"
- redef fun description do return "Uninstall a package"
+ redef fun usage do return "nitpm uninstall [-f] <package0>[=version] [package1 ...]"
+ redef fun description do return "Uninstall packages"
redef fun apply(args)
do
- if args.length != 1 then
+ var opt_force = "-f"
+ var force = args.has(opt_force)
+ if force then args.remove(opt_force)
+
+ if args.is_empty then
print_local_help
exit 1
end
- var name = args.first
- var target_dir = nitpm_lib_dir / name
+ for name in args do
- if not target_dir.file_exists or not target_dir.to_path.is_dir then
- print_error "Package not found"
- exit 1
- end
+ var clean_nitpm_lib_dir = nitpm_lib_dir.simplify_path
+ var target_dir = clean_nitpm_lib_dir / name
- # Ask confirmation
- var response = prompt("Delete {target_dir.escape_to_sh}? [Y/n] ")
- var accept = response != null and
- (response.to_lower == "y" or response.to_lower == "yes" or response == "")
- if not accept then return
+ # Check validity of the package to delete
+ target_dir = target_dir.simplify_path
+ var within_dir = target_dir.has_prefix(clean_nitpm_lib_dir + "/") and
+ target_dir.length > clean_nitpm_lib_dir.length + 1
+ var valid_name = name.length > 0 and name.chars.first.is_lower
+ if not valid_name or not within_dir then
+ print_error "Package name '{name}' is invalid"
+ continue
+ end
- var cmd = "rm -rf {target_dir.escape_to_sh}"
- if verbose then print "+ {cmd}"
+ if not target_dir.file_exists or not target_dir.to_path.is_dir then
+ print_error "Package not found"
+ exit 1
+ end
- var proc = new Process("sh", "-c", cmd)
- proc.wait
+ # Ask confirmation
+ if not force then
+ var response = prompt("Delete {target_dir.escape_to_sh}? [Y/n] ")
+ var accept = response != null and
+ (response.to_lower == "y" or response.to_lower == "yes" or response == "")
+ if not accept then return
+ end
- if proc.status != 0 then
- print_error "Uninstall failed"
- exit 1
+ var cmd = "rm -rf {target_dir.escape_to_sh}"
+ if verbose then print "+ {cmd}"
+
+ var proc = new Process("sh", "-c", cmd)
+ proc.wait
+
+ if proc.status != 0 then
+ print_error "Uninstall failed"
+ exit 1
+ end
end
end
end
redef fun apply(args)
do
var files = nitpm_lib_dir.files
+ var name_to_desc = new Map[String, nullable String]
+ var max_name_len = 0
+
+ # Collect package info
for file in files do
var ini_path = nitpm_lib_dir / file / "package.ini"
if verbose then print "- Reading ini file at {ini_path}"
var ini = new ConfigTree(ini_path)
var tags = ini["package.tags"]
- if tags != null then
- print "{file.justify(15, 0.0)} {tags}"
- else
- print file
- end
+ name_to_desc[file] = tags
+ max_name_len = max_name_len.max(file.length)
+ end
+
+ # Sort in alphabetical order
+ var sorted_names = name_to_desc.keys.to_a
+ alpha_comparator.sort sorted_names
+
+ # Print with clear columns
+ for name in sorted_names do
+ var col0 = name.justify(max_name_len+1, 0.0)
+ var col1 = name_to_desc[name] or else ""
+ var line = col0 + col1
+ print line.trim
end
end
end
var opts = new OptionContext
# Help option
- var opt_help = new OptionBool("Show this help message", "--help", "-h")
+ var opt_help = new OptionBool("Show help message", "-h", "--help")
# Verbose mode option
- var opt_verbose = new OptionBool("Print more information", "--verbose", "-v")
+ var opt_verbose = new OptionBool("Print more information", "-v", "--verbose")
private fun verbose: Bool do return opt_verbose.value
# All command line actions, mapped to their short `name`