pacsea/install/
command.rs1use crate::state::{PackageItem, Source};
4
5use super::utils::shell_single_quote;
6
7#[must_use]
20pub fn aur_install_body(flags: &str, n: &str) -> String {
21 format!(
22 "(if command -v paru >/dev/null 2>&1; then \
23 paru {flags} {n}; \
24 elif command -v yay >/dev/null 2>&1; then \
25 yay {flags} {n}; \
26 else \
27 echo 'No AUR helper (paru/yay) found.'; \
28 fi)"
29 )
30}
31
32#[must_use]
46pub fn build_install_command(
47 item: &PackageItem,
48 password: Option<&str>,
49 dry_run: bool,
50) -> (String, bool) {
51 match &item.source {
52 Source::Official { .. } => {
53 let reinstall = crate::index::is_installed(&item.name);
54 let base_cmd = if reinstall {
55 format!("pacman -S --noconfirm {}", item.name)
56 } else {
57 format!("pacman -S --needed --noconfirm {}", item.name)
58 };
59 let hold_tail = "; echo; echo 'Finished.'; echo 'Press any key to close...'; read -rn1 -s _ || (echo; echo 'Press Ctrl+C to close'; sleep infinity)";
60 if dry_run {
61 let cmd = format!("sudo {base_cmd}{hold_tail}");
62 let quoted = shell_single_quote(&cmd);
63 let bash = format!("echo DRY RUN: {quoted}");
64 return (bash, true);
65 }
66 let pass = password.unwrap_or("");
67 if pass.is_empty() {
68 let bash = format!("sudo {base_cmd}{hold_tail}");
69 (bash, true)
70 } else {
71 let escaped = shell_single_quote(pass);
72 let pipe = format!("echo {escaped} | ");
73 let bash = format!("{pipe}sudo -S {base_cmd}{hold_tail}");
74 (bash, true)
75 }
76 }
77 Source::Aur => {
78 let hold_tail = "; echo; echo 'Press any key to close...'; read -rn1 -s _ || (echo; echo 'Press Ctrl+C to close'; sleep infinity)";
79 let reinstall = crate::index::is_installed(&item.name);
80 let flags = if reinstall {
81 "-S --noconfirm"
82 } else {
83 "-S --needed --noconfirm"
84 };
85 let aur_cmd = if dry_run {
86 let cmd = format!(
87 "paru {flags} {n} || yay {flags} {n}{hold}",
88 n = item.name,
89 hold = hold_tail,
90 flags = flags
91 );
92 let quoted = shell_single_quote(&cmd);
93 format!("echo DRY RUN: {quoted}")
94 } else {
95 format!(
96 "{body}{hold}",
97 body = aur_install_body(flags, &item.name),
98 hold = hold_tail
99 )
100 };
101 (aur_cmd, false)
102 }
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn install_build_install_command_official_variants() {
124 let pkg = PackageItem {
125 name: "ripgrep".into(),
126 version: "14".into(),
127 description: String::new(),
128 source: Source::Official {
129 repo: "extra".into(),
130 arch: "x86_64".into(),
131 },
132 popularity: None,
133 out_of_date: None,
134 orphaned: false,
135 };
136
137 let (cmd1, uses_sudo1) = build_install_command(&pkg, None, false);
138 assert!(uses_sudo1);
139 assert!(cmd1.contains("sudo pacman -S --needed --noconfirm ripgrep"));
140 assert!(cmd1.contains("Press any key to close"));
141
142 let (cmd2, uses_sudo2) = build_install_command(&pkg, Some("pa's"), false);
143 assert!(uses_sudo2);
144 assert!(cmd2.contains("echo "));
145 assert!(cmd2.contains("sudo -S pacman -S --needed --noconfirm ripgrep"));
146
147 let (cmd3, uses_sudo3) = build_install_command(&pkg, None, true);
148 assert!(uses_sudo3);
149 assert!(cmd3.starts_with("echo DRY RUN: '"));
151 assert!(cmd3.contains("sudo pacman -S --needed --noconfirm ripgrep"));
152 }
153
154 #[test]
155 fn install_build_install_command_aur_variants() {
167 let pkg = PackageItem {
168 name: "yay-bin".into(),
169 version: "1".into(),
170 description: String::new(),
171 source: Source::Aur,
172 popularity: None,
173 out_of_date: None,
174 orphaned: false,
175 };
176
177 let (cmd1, uses_sudo1) = build_install_command(&pkg, None, false);
178 assert!(!uses_sudo1);
179 assert!(cmd1.contains("command -v paru"));
180 assert!(cmd1.contains("paru -S --needed --noconfirm yay-bin"));
181 assert!(cmd1.contains("elif command -v yay"));
182 assert!(cmd1.contains("No AUR helper"));
183 assert!(cmd1.contains("Press any key to close"));
184
185 let (cmd2, uses_sudo2) = build_install_command(&pkg, None, true);
186 assert!(!uses_sudo2);
187 assert!(cmd2.starts_with("echo DRY RUN: '"));
189 assert!(cmd2.contains("paru -S --needed --noconfirm yay-bin"));
190 }
191}