warg_cli/commands/
config.rs1use super::CommonOptions;
2use anyhow::{bail, Context, Result};
3use clap::Args;
4use std::path::PathBuf;
5use warg_client::{keyring::Keyring, Config, RegistryUrl};
6
7#[derive(Args)]
9pub struct ConfigCommand {
10 #[clap(flatten)]
12 pub common: CommonOptions,
13
14 #[clap(long, value_name = "REGISTRIES")]
16 pub registries_dir: Option<PathBuf>,
17
18 #[clap(long, value_name = "CONTENT")]
20 pub content_dir: Option<PathBuf>,
21
22 #[clap(long)]
24 pub ignore_federation_hints: Option<bool>,
25
26 #[clap(long)]
28 pub disable_auto_accept_federation_hints: Option<bool>,
29
30 #[clap(long)]
33 pub disable_auto_package_init: Option<bool>,
34
35 #[clap(long)]
37 pub overwrite: bool,
38
39 #[clap(value_name = "PATH")]
43 pub path: Option<PathBuf>,
44
45 #[clap(long, value_name = "NAMESPACE_PATH")]
47 pub namespace_path: Option<PathBuf>,
48
49 #[clap(long, value_name = "KEYRING_BACKEND", value_parser = keyring_backend_parser, long_help = keyring_backend_help())]
51 pub keyring_backend: Option<String>,
52}
53
54impl ConfigCommand {
55 pub async fn exec(self) -> Result<()> {
57 let path = self
58 .path
59 .map(Ok)
60 .unwrap_or_else(Config::default_config_path)?;
61 let cwd = std::env::current_dir().context("failed to determine current directory")?;
62
63 if self.overwrite && path.is_file() {
64 println!(
65 "Overwriting configuration file: `{path}`",
66 path = path.display()
67 );
68 }
69
70 let mut changing_home_registry = false;
71
72 let config = if self.overwrite {
73 let home_url = self
74 .common
75 .registry
76 .as_ref()
77 .map(RegistryUrl::new)
78 .transpose()?
79 .map(|u| u.to_string())
80 .ok_or(anyhow::anyhow!(
81 "Please configure your home registry: warg config --registry <registry-url>"
82 ))?;
83
84 changing_home_registry = true;
85
86 Config {
87 home_url: Some(home_url),
88 registries_dir: self.registries_dir.map(|p| cwd.join(p)),
89 content_dir: self.content_dir.map(|p| cwd.join(p)),
90 namespace_map_path: self.namespace_path.map(|p| cwd.join(p)),
91 keys: self.common.read_config()?.keys,
92 keyring_auth: false,
93 ignore_federation_hints: self.ignore_federation_hints.unwrap_or_default(),
94 disable_auto_accept_federation_hints: self
95 .disable_auto_accept_federation_hints
96 .unwrap_or_default(),
97 disable_auto_package_init: self.disable_auto_package_init.unwrap_or_default(),
98 disable_interactive: false,
99 keyring_backend: self.keyring_backend,
100 }
101 } else {
102 let mut config = self.common.read_config()?;
103 if self.common.registry.is_some() {
104 let home_url = self
105 .common
106 .registry
107 .as_ref()
108 .map(RegistryUrl::new)
109 .transpose()?
110 .map(|u| u.to_string());
111 if home_url != config.home_url {
112 changing_home_registry = true;
113 config.home_url = home_url;
114 }
115 }
116 if config.home_url.is_none() {
117 bail!("Please configure your home registry: warg config --registry <registry-url>");
118 }
119 if self.registries_dir.is_some() {
120 config.registries_dir = self.registries_dir.map(|p| cwd.join(p));
121 }
122 if self.content_dir.is_some() {
123 config.content_dir = self.content_dir.map(|p| cwd.join(p));
124 }
125 if self.namespace_path.is_some() {
126 config.namespace_map_path = self.namespace_path.map(|p| cwd.join(p));
127 }
128 if let Some(ignore_federation_hints) = self.ignore_federation_hints {
129 config.ignore_federation_hints = ignore_federation_hints;
130 }
131 if let Some(disable_auto_accept_federation_hints) =
132 self.disable_auto_accept_federation_hints
133 {
134 config.disable_auto_accept_federation_hints = disable_auto_accept_federation_hints;
135 }
136 if let Some(disable_auto_package_init) = self.disable_auto_package_init {
137 config.disable_auto_package_init = disable_auto_package_init;
138 }
139 if self.keyring_backend.is_some() {
140 config.keyring_backend = self.keyring_backend;
141 }
142
143 config
144 };
145
146 config.write_to_file(&path)?;
152
153 if changing_home_registry {
155 let client = self.common.create_client(&config).await?;
156 client.reset_namespaces().await?;
157 client.reset_registry().await?;
158 }
159
160 println!("Set configuration file `{path}`", path = path.display(),);
161
162 Ok(())
163 }
164}
165
166pub(crate) fn keyring_backend_parser(s: &str) -> Result<String, String> {
167 if Keyring::SUPPORTED_BACKENDS.contains(&s) {
168 Ok(s.to_string())
169 } else {
170 Err(format!("`{s}` is not a supported keyring backend."))
171 }
172}
173
174pub(crate) fn keyring_backend_help() -> clap::builder::StyledStr {
175 use std::fmt::Write as _;
176
177 let mut help = String::new();
178
179 writeln!(
180 &mut help,
181 "The backend to use for keyring access. The following options are supported:\n"
182 )
183 .unwrap();
184 for backend in Keyring::SUPPORTED_BACKENDS {
185 writeln!(
186 &mut help,
187 "{:16} {}",
188 backend,
189 Keyring::describe_backend(backend)
190 )
191 .unwrap();
192 }
193 writeln!(
194 &mut help,
195 "\nThe default is `{}`.",
196 Keyring::DEFAULT_BACKEND
197 )
198 .unwrap();
199
200 help.into()
201}