Skip to main content

zoi_cli/cmd/install/
args.rs

1use clap::Args;
2use zoi_common::Runnable;
3
4use crate::cli::InstallScope;
5use crate::pkg::plugin::PluginManager;
6
7/// Arguments for the `install` command.
8#[derive(Args, Debug, Clone)]
9pub struct InstallArgs {
10    /// The package source identifier(s).
11    #[arg(
12        value_name = "ALL_SOURCES",
13        help = "Package identifier (e.g. @repo/name, #git@repo/name, path, or \
14                URL)"
15    )]
16    pub sources: Vec<String>,
17
18    /// Install from a git repository (e.g. 'zillowe/hello',
19    /// 'gh:zillowe/hello')
20    #[arg(long, value_name = "REPO", conflicts_with = "sources")]
21    pub repo: Option<String>,
22
23    /// Force re-installation even if the package is already installed.
24    /// Cached archives are discarded and re-downloaded.
25    #[arg(long)]
26    pub force: bool,
27
28    /// Accept all optional dependencies
29    #[arg(long)]
30    pub all_optional: bool,
31
32    /// The scope to install the package to
33    #[arg(long, value_enum, conflicts_with_all = &["local", "global"])]
34    pub scope: Option<InstallScope>,
35
36    /// Install packages to the current project (alias for --scope=project)
37    #[arg(long, conflicts_with = "global")]
38    pub local: bool,
39
40    /// Install packages globally for the current user (alias for --scope=user)
41    #[arg(long)]
42    pub global: bool,
43
44    /// Save the package to the project's zoi.lua
45    #[arg(long, conflicts_with = "deps_only")]
46    pub save: bool,
47
48    /// Install only the dependencies of the given packages, not the packages
49    /// themselves
50    #[arg(long, conflicts_with_all = &["save", "build_deps_only"])]
51    pub deps_only: bool,
52
53    /// Install only the build dependencies of the given packages
54    #[arg(long, conflicts_with_all = &["save", "deps_only"])]
55    pub build_deps_only: bool,
56
57    /// The type of package to build if building from source (e.g. 'source',
58    /// 'pre-compiled').
59    #[arg(long)]
60    pub r#type: Option<String>,
61
62    /// Do not actually perform the installation, just show what would be done
63    #[arg(long)]
64    pub dry_run: bool,
65
66    /// Force building from source even if a pre-compiled archive is available
67    /// in the registry
68    #[arg(long, short = 'b')]
69    pub build: bool,
70
71    /// Enforce zoi.lock exactly (project install only, no lockfile updates)
72    #[arg(long)]
73    pub frozen: bool,
74
75    /// Explain dependency selection and install decisions
76    #[arg(long)]
77    pub explain: bool,
78
79    /// Emit machine-readable install plan JSON
80    #[arg(long, requires = "dry_run")]
81    pub plan_json: bool,
82
83    /// Retry failed downloads this many times (minimum 1)
84    #[arg(long, default_value_t = 3)]
85    pub retry: u32,
86
87    /// Show additional install details (package origins, preflight info)
88    #[arg(long, short)]
89    pub verbose: bool,
90
91    /// Use PURL (Package URL) specification for resolving packages
92    #[arg(long)]
93    pub purl: bool
94}
95
96impl Runnable for InstallArgs {
97    fn run(&self, yes: bool) -> anyhow::Result<()> {
98        let plugin_manager = PluginManager::new()?;
99
100        super::run(
101            &self.sources,
102            self.repo.clone(),
103            self.force,
104            self.all_optional,
105            yes,
106            self.scope,
107            self.local,
108            self.global,
109            self.save,
110            self.deps_only,
111            self.build_deps_only,
112            self.r#type.as_deref(),
113            self.dry_run,
114            Some(&plugin_manager),
115            self.build,
116            self.frozen,
117            self.explain,
118            self.plan_json,
119            self.retry,
120            self.verbose,
121            self.purl,
122            None
123        )
124    }
125}