|
1 | | -use clap::{Arg, ArgAction, Command}; |
| 1 | +use clap::{arg, command, ArgAction}; |
| 2 | + |
| 3 | +use regex::Regex; |
2 | 4 | use serde_json::Value; |
3 | 5 | use std::fs; |
4 | | -use std::io::{BufRead, BufReader}; |
5 | 6 | use std::path::Path; |
6 | 7 | use subprocess::Exec; |
7 | | -// ni |
8 | | -// nr |
9 | | -// nlx |
10 | | -// nu |
11 | | -// nun |
12 | | -// nci |
13 | 8 |
|
14 | 9 | fn main() { |
| 10 | + let m: clap::ArgMatches = command!("n") |
| 11 | + .subcommands([ |
| 12 | + command!("add") |
| 13 | + .about("Add new packages to dependencies") |
| 14 | + .args([ |
| 15 | + arg!(<package> "Package name"), |
| 16 | + arg!(-'S' --"save" "Save installed packages to a package.json file as dependencies.") |
| 17 | + .required(false), |
| 18 | + arg!(-'D' --"save-dev" "Package will appear in your devDependencies.") |
| 19 | + .required(false), |
| 20 | + arg!(-'O' --"save-optional" "Install the specified packages as optionalDependencies.") |
| 21 | + .required(false) |
| 22 | + .action(ArgAction::SetTrue), |
| 23 | + arg!(-'g' --"global" "Install a package globally.") |
| 24 | + .required(false) |
| 25 | + .action(ArgAction::SetTrue) |
| 26 | + ]), |
| 27 | + command!("install") |
| 28 | + .about("Used to install all dependencies for a project.") |
| 29 | + .alias("i"), |
| 30 | + command!("clean-install") |
| 31 | + .about("Like npm ci") |
| 32 | + .alias("ci"), |
| 33 | + ]) |
| 34 | + .get_matches(); |
| 35 | + |
15 | 36 | let pkg_manager = read_package_manager().unwrap(); |
16 | 37 |
|
17 | 38 | if let [p, v] = &pkg_manager[..2] { |
18 | | - println!("π Package manage tool is {} , the version is {}", p, v); |
19 | | - let matches = Command::new("n") |
20 | | - .subcommand( |
21 | | - Command::new("i").about("Install operations").arg( |
22 | | - Arg::new("package") |
23 | | - .required(false) |
24 | | - .action(ArgAction::Append), |
25 | | - ), |
26 | | - ) |
27 | | - .subcommand(Command::new("ci")) |
28 | | - .subcommand( |
29 | | - Command::new("r") |
30 | | - .about("Running script") |
31 | | - .arg(Arg::new("script").required(true)), |
32 | | - ) |
33 | | - .subcommand( |
34 | | - Command::new("x") |
35 | | - .about("Operation X") |
36 | | - .arg(Arg::new("package").required(true).action(ArgAction::Append)), |
37 | | - ) |
38 | | - .get_matches(); |
39 | | - |
40 | | - // Then you can check which subcommand was used |
41 | | - match matches.subcommand() { |
42 | | - Some(("i", i_matches)) => { |
43 | | - if let Some(package) = i_matches.get_one::<String>("package") { |
44 | | - run_install_command(p, vec!["install", package]) |
| 39 | + println!( |
| 40 | + "π₯³ The current package manager being used is : '{}@{}' ", |
| 41 | + p, v |
| 42 | + ); |
| 43 | + match m.subcommand() { |
| 44 | + Some(("add", add_matches)) => { |
| 45 | + let package = add_matches.get_one::<String>("package").unwrap(); |
| 46 | + let save = add_matches.get_flag("save"); |
| 47 | + let save_dev = add_matches.get_flag("save-dev"); |
| 48 | + let save_optional = add_matches.get_flag("save-optional"); |
| 49 | + let global = add_matches.get_flag("global"); |
| 50 | + if save { |
| 51 | + run_shell(format!("{} add --save {}", p, package)) |
| 52 | + } else if save_dev { |
| 53 | + run_shell(format!("{} add --save-dev {}", p, package)); |
| 54 | + } else if save_optional { |
| 55 | + run_shell(format!("{} add --save-optional {}", p, package)) |
| 56 | + } else if global { |
| 57 | + match p.as_str() { |
| 58 | + "yarn" => run_shell(format!("yarn global add {}", package)), |
| 59 | + _ => run_shell(format!("{} add --global {}", p, package)), |
| 60 | + } |
45 | 61 | } else { |
46 | | - run_install_command(p, vec!["install"]) |
| 62 | + run_shell(format!("{} add {}", p, package)); |
47 | 63 | } |
48 | 64 | } |
49 | | - Some(("ci", _ci_matches)) => match p.as_str() { |
50 | | - "npm" => { |
51 | | - run_install_command(p, vec!["ci"]); |
52 | | - } |
53 | | - "pnpm" => { |
54 | | - run_install_command(p, vec!["install", "--frozen-lockfile"]); |
55 | | - } |
56 | | - "yarn" => { |
57 | | - run_install_command(p, vec!["install", "--frozen-lockfile"]); |
58 | | - } |
59 | | - _ => {} |
| 65 | + Some(("install", _install_matches)) => run_shell(format!("{} install", p)), |
| 66 | + Some(("clean-install", _clean_install_matches)) => match p.as_str() { |
| 67 | + "npm" => run_shell(format!("npm ci")), |
| 68 | + _ => run_shell(format!("{} install --frozen-lockfile", p)), |
60 | 69 | }, |
61 | | - Some(("r", r_matches)) => match r_matches.get_one::<String>("script") { |
62 | | - Some(script) => { |
63 | | - run_install_command(p, vec![script]); |
64 | | - } |
65 | | - None => { |
66 | | - panic!("π’") |
67 | | - } |
68 | | - }, |
69 | | - Some(("x", x_matches)) => { |
70 | | - if let Some(_package) = x_matches.get_many::<String>("package") { |
71 | | - // println!("{}", package.map(|s| s.as_str())); |
72 | | - match p.as_str() { |
73 | | - "npm" => { |
74 | | - // run_install_command(&"npx".to_string(), vec![package]); |
75 | | - } |
76 | | - "pnpm" => { |
77 | | - // run_install_command(&"pnpx".to_string(), vec![package]); |
78 | | - } |
79 | | - "yarn" => { |
80 | | - // run_install_command(&"yarn".to_string(), vec![package]); |
81 | | - } |
82 | | - _ => {} |
83 | | - } |
84 | | - } |
| 70 | + _ => { |
| 71 | + println!("π Sorry, the command you entered is currently not supported.") |
85 | 72 | } |
86 | | - None => (), |
87 | | - _ => unreachable!(), |
88 | 73 | } |
89 | 74 | } |
90 | 75 | } |
91 | 76 |
|
92 | 77 | pub fn read_package_manager() -> Result<Vec<String>, &'static str> { |
93 | 78 | let path = Path::new("./package.json"); |
94 | 79 | if path.exists() { |
95 | | - if let Ok(contents) = fs::read_to_string(path) { |
96 | | - let parsed: Value = serde_json::from_str(&contents).unwrap(); |
97 | | - match parsed["packageManager"].as_str() { |
98 | | - Some(manager) => { |
99 | | - let vec: Vec<String> = manager.split('@').map(|s| s.to_string()).collect(); |
100 | | - |
101 | | - return Ok(vec); |
102 | | - } |
103 | | - None => { |
| 80 | + let contents = fs::read_to_string(path).unwrap(); |
| 81 | + let parsed: Value = serde_json::from_str(&contents).unwrap(); |
| 82 | + match parsed["packageManager"].as_str() { |
| 83 | + Some(manager) => { |
| 84 | + let re = Regex::new(r"(npm|pnpm|yarn)@(.*)").unwrap(); |
| 85 | + if let Some(caps) = re.captures(manager) { |
| 86 | + return Ok(vec![caps[1].to_string(), caps[2].to_string()]); |
| 87 | + } else { |
104 | 88 | return Err( |
105 | | - "π’ Sorry, you must to be configure packageManager in package.json file ", |
106 | | - ) |
| 89 | + "π’ PackageManager parsing failed, possibly due to incorrect format. ", |
| 90 | + ); |
107 | 91 | } |
108 | 92 | } |
109 | | - } else { |
110 | | - return Err("π’ Failure to read package.json "); |
| 93 | + None => { |
| 94 | + return Err( |
| 95 | + "π’ Sorry, you must to be configure packageManager in package.json file ", |
| 96 | + ) |
| 97 | + } |
111 | 98 | } |
112 | 99 | } |
113 | | - Err("π Could not found package.json") |
| 100 | + return Err("π Could not found package.json"); |
114 | 101 | } |
115 | 102 |
|
116 | | -pub fn run_install_command(package_manager: &String, cmd_arg: Vec<&str>) { |
117 | | - let mut cmd = Exec::cmd(package_manager).stdout(subprocess::Redirection::Pipe); |
118 | | - for arg in cmd_arg { |
119 | | - cmd = cmd.arg(arg); |
120 | | - } |
121 | | - let mut popen = cmd.popen().unwrap(); |
122 | | - let stdout = popen.stdout.take().unwrap(); |
123 | | - let reader = BufReader::new(stdout); |
124 | | - for line in reader.lines() { |
125 | | - println!("{}", line.unwrap()); |
126 | | - } |
| 103 | +fn run_shell(cmd: String) { |
| 104 | + println!("π― The instruction to be executed is : '{}' ", cmd); |
| 105 | + Exec::cmd("sh").arg("-c").arg(cmd).popen().unwrap(); |
127 | 106 | } |
0 commit comments