wapm_cli/commands/
list.rs1use crate::config;
4use crate::data::lock::lockfile::{CommandMap, ModuleMap};
5use crate::dataflow::lockfile_packages::LockfileResult;
6use prettytable::{format, Table};
7use std::fmt::Write as _;
8use structopt::StructOpt;
9
10#[derive(StructOpt, Debug)]
11pub struct ListOpt {
12 #[structopt(short = "g", long = "global")]
14 global: bool,
15
16 #[structopt(short = "a", long = "all")]
18 all: bool,
19}
20
21pub fn list(options: ListOpt) -> anyhow::Result<()> {
22 let mut local = false;
23 let mut global = false;
24 match (options.global, options.all) {
25 (_, true) => {
26 local = true;
27 global = true;
28 }
29 (true, false) => {
30 global = true;
31 }
32 (false, false) => {
33 local = true;
34 }
35 }
36 let local_start_value = local;
37
38 let mut handle = String::new();
39 if local {
40 let cwd = crate::config::Config::get_current_dir()?;
41 match LockfileResult::find_in_directory(cwd) {
42 LockfileResult::Lockfile(lockfile) => {
43 let has_modules = !lockfile.modules.is_empty();
44 let has_commands = !lockfile.commands.is_empty();
45 local = has_modules | has_commands;
47 if has_modules {
48 writeln!(handle, "LOCAL PACKAGES:")?;
49 write!(handle, "{}", create_module_ascii_table(&lockfile.modules))?;
50 }
51 if has_modules && has_commands {
52 writeln!(handle)?;
53 }
54 if has_commands {
55 writeln!(handle, "LOCAL COMMANDS:")?;
56 write!(handle, "{}", create_command_ascii_table(&lockfile.commands))?;
57 }
58 }
59 LockfileResult::NoLockfile => {
60 if !global {
61 writeln!(handle, "No packages in current directory")?;
62 return Ok(());
63 }
64 local = false;
65 }
66 LockfileResult::LockfileError(e) => {
67 return Err(anyhow!(
68 "Failed to read lock file in current directory: {}",
69 e
70 ));
71 }
72 }
73 }
74
75 if local && global {
76 writeln!(handle)?;
77 }
78
79 if global {
80 let global_path = config::Config::get_globals_directory()?;
81 match LockfileResult::find_in_directory(global_path) {
82 LockfileResult::Lockfile(lockfile) => {
83 let has_modules = !lockfile.modules.is_empty();
84 let has_commands = !lockfile.commands.is_empty();
85 global = has_modules || has_commands;
87 if has_modules {
88 writeln!(handle, "GLOBAL PACKAGES:")?;
89 write!(handle, "{}", create_module_ascii_table(&lockfile.modules))?;
90 }
91 if has_modules && has_commands {
92 writeln!(handle)?;
93 }
94 if has_commands {
95 writeln!(handle, "GLOBAL COMMANDS:")?;
96 write!(handle, "{}", create_command_ascii_table(&lockfile.commands))?;
97 }
98 }
99 LockfileResult::NoLockfile => {
100 if !local_start_value {
101 writeln!(handle, "No global packages")?;
102 return Ok(());
103 }
104 global = false;
105 }
106 LockfileResult::LockfileError(e) => {
107 return Err(anyhow!(
108 "Failed to read lock file in current directory: {}",
109 e
110 ));
111 }
112 }
113 }
114
115 if handle.is_empty() {
116 debug_assert!(!global);
118 debug_assert!(!local);
119 println!("No packages found");
120 } else {
121 print!("{}", handle);
122 }
123 Ok(())
124}
125
126fn create_module_ascii_table(modules: &ModuleMap) -> String {
127 let mut table = Table::new();
128 table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
129 table.add_row(row!["PACKAGE", "VERSION", "MODULE", "ABI"]);
130 for (package_name, version_info) in modules.iter() {
131 for (version_number, module_info) in version_info.iter() {
132 for (module_name, module) in module_info.iter() {
133 table.add_row(row![package_name, version_number, module_name, module.abi,]);
134 }
135 }
136 }
137 format!("{}", table)
138}
139
140fn create_command_ascii_table(commands: &CommandMap) -> String {
141 let mut table = Table::new();
142 table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
143 table.add_row(row!["COMMAND", "PACKAGE", "VERSION"]);
144 for (command_name, command) in commands.iter() {
145 table.add_row(row![
146 command_name,
147 command.package_name,
148 command.package_version,
149 ]);
150 }
151 format!("{}", table)
152}