1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Install module for building package installation, removal, and update commands.
//!
//! This module builds commands — it **never executes them**. Every builder
//! returns a [`CommandSpec`] (program + argument vector) that callers can:
//!
//! - spawn directly via [`CommandSpec::to_command`] (no shell, no quoting bugs),
//! - render for display or terminals via [`CommandSpec::to_shell_string`],
//! - or simply print (a "dry run" is displaying the command instead of running it).
//!
//! Functionality:
//!
//! - **Command building** — pacman install/remove/update, AUR helper install
//! - **Batch planning** — split mixed target lists between pacman and an AUR helper
//! - **Detection** — find the preferred AUR helper (`paru` → `yay`) and privilege
//! tool (`doas` → `sudo`) on `PATH`
//! - **Shell safety** — strict package-name validation and POSIX quoting helpers
//!
//! # Features
//!
//! This module requires the `install` feature flag (which enables `deps` for
//! the shared `PackageRef`/`PackageSource` types):
//!
//! ```toml
//! [dependencies]
//! arch-toolkit = { version = "0.3", features = ["install"] }
//! ```
//!
//! # Examples
//!
//! ## Build and Display an Install Command
//!
//! ```
//! use arch_toolkit::install::build_pacman_install;
//! use arch_toolkit::types::install::InstallOptions;
//!
//! let spec = build_pacman_install(&["ripgrep", "fd"], &InstallOptions::default())?;
//! // Dry run: display instead of executing
//! println!("Would run: {}", spec.to_shell_string());
//! # Ok::<(), arch_toolkit::error::ArchToolkitError>(())
//! ```
//!
//! ## Detect Tools and Plan a Mixed Batch
//!
//! ```no_run
//! use arch_toolkit::install::{build_batch_install, detect_aur_helper, detect_privilege_tool};
//! use arch_toolkit::types::install::InstallOptions;
//! use arch_toolkit::{PackageRef, PackageSource};
//!
//! let targets = vec![
//! PackageRef::official("ripgrep", "14.0.0", "extra", "x86_64"),
//! PackageRef::aur("yay-bin", "12.0.0"),
//! ];
//! let plan = build_batch_install(
//! &targets,
//! detect_aur_helper(),
//! detect_privilege_tool(),
//! &InstallOptions::default(),
//! None::<&std::collections::HashSet<String>>,
//! )?;
//! for command in &plan.commands {
//! println!("{command}");
//! }
//! # Ok::<(), arch_toolkit::error::ArchToolkitError>(())
//! ```
//!
//! ## Remove Packages with Cascade Control
//!
//! ```
//! use arch_toolkit::install::{build_remove_command, with_privilege};
//! use arch_toolkit::types::install::{CascadeMode, PrivilegeTool};
//!
//! let spec = with_privilege(
//! PrivilegeTool::Sudo,
//! build_remove_command(&["old-package"], CascadeMode::CascadeWithConfigs, true)?,
//! );
//! assert_eq!(spec.to_shell_string(), "sudo pacman -Rns --noconfirm -- old-package");
//! # Ok::<(), arch_toolkit::error::ArchToolkitError>(())
//! ```
//!
//! ## Execute a Built Command (caller's decision)
//!
//! ```no_run
//! use arch_toolkit::install::build_update_command;
//!
//! let spec = build_update_command(None, true);
//! let status = spec.to_command().status()?;
//! println!("Update exited with: {status}");
//! # Ok::<(), std::io::Error>(())
//! ```
// Re-export types from types module
pub use crate;
// Re-export command builders
pub use ;
// Re-export batch planning
pub use ;
// Re-export detection
pub use ;
// Re-export shell utilities
pub use ;