cli_xtask/config/
dist_target.rs

1use cargo_metadata::{Package, Target};
2use eyre::eyre;
3
4use crate::Result;
5
6/// Configures and constructs [`DistTargetConfig`].
7///
8/// This struct is build from
9/// [`DistPackageConfigBuilder`](super::DistPackageConfigBuilder).
10#[derive(Debug)]
11pub struct DistTargetConfigBuilder<'a> {
12    name: String,
13    metadata: &'a Target,
14    command: Option<clap::Command>,
15    #[cfg(feature = "subcommand-dist-build-bin")]
16    cargo_build_options: Vec<String>,
17}
18
19impl<'a> DistTargetConfigBuilder<'a> {
20    pub(crate) fn from_metadata(target: &'a Target) -> Self {
21        Self {
22            name: target.name.clone(),
23            metadata: target,
24            command: None,
25            #[cfg(feature = "subcommand-dist-build-bin")]
26            cargo_build_options: vec![],
27        }
28    }
29
30    pub(crate) fn target_by_name(package: &'a Package, name: &str, kind: &str) -> Result<Self> {
31        let target = package
32            .targets
33            .iter()
34            .find(|t| t.name == name && t.kind.iter().any(|k| k == &kind.into()))
35            .ok_or_else(|| eyre!("command not found: {name}, {kind}"))?;
36        Ok(Self {
37            name: name.to_string(),
38            metadata: target,
39            command: None,
40            #[cfg(feature = "subcommand-dist-build-bin")]
41            cargo_build_options: vec![],
42        })
43    }
44
45    /// Set the command line interface definition for the target.
46    pub fn command(mut self, command: clap::Command) -> Self {
47        self.command = Some(command);
48        self
49    }
50
51    /// Adds cargo build options to be used when building the target.
52    #[cfg(feature = "subcommand-dist-build-bin")]
53    #[cfg_attr(docsrs, doc(cfg(feature = "subcommand-dist-build-bin")))]
54    pub fn cargo_build_options(
55        mut self,
56        options: impl IntoIterator<Item = impl Into<String>>,
57    ) -> Self {
58        self.cargo_build_options
59            .extend(options.into_iter().map(Into::into));
60        self
61    }
62
63    /// Builds a [`DistTargetConfig`] from the current configuration.
64    ///
65    /// # Errors
66    ///
67    /// Returns an error if the [`DistTargetConfig`] cannot be built.
68    pub fn build(self) -> Result<DistTargetConfig<'a>> {
69        Ok(DistTargetConfig {
70            name: self.name,
71            metadata: self.metadata,
72            command: self.command,
73            #[cfg(feature = "subcommand-dist-build-bin")]
74            cargo_build_options: self.cargo_build_options,
75        })
76    }
77}
78
79/// Configuration for the distribution of the target.
80#[derive(Debug)]
81pub struct DistTargetConfig<'a> {
82    name: String,
83    metadata: &'a Target,
84    command: Option<clap::Command>,
85    #[cfg(feature = "subcommand-dist-build-bin")]
86    cargo_build_options: Vec<String>,
87}
88
89impl DistTargetConfig<'_> {
90    /// Return the name of the target.
91    pub fn name(&self) -> &str {
92        &self.name
93    }
94
95    /// Returns the metadata of the target.
96    pub fn metadata(&self) -> &Target {
97        self.metadata
98    }
99
100    /// Returns the command line interface definition for the target.
101    pub fn command(&self) -> Option<&clap::Command> {
102        self.command.as_ref()
103    }
104
105    /// Returns the cargo build options to be used when building the target.
106    #[cfg(feature = "subcommand-dist-build-bin")]
107    #[cfg_attr(docsrs, doc(cfg(feature = "subcommand-dist-build-bin")))]
108    pub fn cargo_build_options(&self) -> &[String] {
109        &self.cargo_build_options
110    }
111}