warg_cli/
commands.rs

1//! Commands for the `warg` tool.
2
3use anyhow::Result;
4use clap::Args;
5use std::path::PathBuf;
6use warg_client::keyring::Keyring;
7use warg_client::storage::RegistryDomain;
8use warg_client::{ClientError, Config, FileSystemClient, StorageLockResult};
9use warg_crypto::signing::PrivateKey;
10
11mod bundle;
12mod clear;
13mod config;
14mod dependencies;
15mod download;
16mod info;
17mod key;
18mod lock;
19mod login;
20mod logout;
21mod publish;
22mod reset;
23mod update;
24
25pub use self::bundle::*;
26pub use self::clear::*;
27pub use self::config::*;
28pub use self::dependencies::*;
29pub use self::download::*;
30pub use self::info::*;
31pub use self::key::*;
32pub use self::lock::*;
33pub use self::login::*;
34pub use self::logout::*;
35pub use self::publish::*;
36pub use self::reset::*;
37pub use self::update::*;
38
39/// Common options for commands.
40#[derive(Args)]
41pub struct CommonOptions {
42    /// The URL of the registry to use.
43    #[clap(long, value_name = "URL")]
44    pub registry: Option<String>,
45    /// The path to the client configuration file to use.
46    ///
47    /// If not specified, the following locations are searched in order: `./warg-config.json`, `<system-config-dir>/warg/config.json`.
48    ///
49    /// If no configuration file is found, a default configuration is used.
50    #[clap(long, value_name = "CONFIG")]
51    pub config: Option<PathBuf>,
52}
53
54impl CommonOptions {
55    /// Reads the client configuration.
56    ///
57    /// If a client configuration was not specified, a default configuration is returned.
58    pub fn read_config(&self) -> Result<Config> {
59        Ok(self
60            .config
61            .as_ref()
62            .map_or_else(Config::from_default_file, |p| {
63                Config::from_file(p).map(Some)
64            })?
65            .unwrap_or_default())
66    }
67
68    /// Creates the warg client to use.
69    pub async fn create_client(&self, config: &Config) -> Result<FileSystemClient, ClientError> {
70        let client =
71            match FileSystemClient::try_new_with_config(self.registry.as_deref(), config, None)
72                .await?
73            {
74                StorageLockResult::Acquired(client) => Ok(client),
75                StorageLockResult::NotAcquired(path) => {
76                    println!(
77                        "blocking on lock for directory `{path}`...",
78                        path = path.display()
79                    );
80
81                    FileSystemClient::new_with_config(self.registry.as_deref(), config, None).await
82                }
83            }?;
84        Ok(client)
85    }
86
87    /// Gets the signing key for the given registry URL.
88    pub async fn signing_key(
89        &self,
90        registry_domain: Option<&RegistryDomain>,
91    ) -> Result<PrivateKey> {
92        let config = self.read_config()?;
93        let key = Keyring::from_config(&config)?.get_signing_key(
94            registry_domain.map(|domain| domain.to_string()).as_deref(),
95            &config.keys,
96            config.home_url.as_deref(),
97        )?;
98        Ok(key)
99    }
100}