alpm_buildinfo/
cli.rs

1use std::{
2    fmt::{Display, Formatter},
3    path::PathBuf,
4    str::FromStr,
5};
6
7use alpm_types::{
8    Architecture,
9    BuildDate,
10    BuildDirectory,
11    BuildEnvironmentOption,
12    BuildTool,
13    BuildToolVersion,
14    InstalledPackage,
15    Name,
16    PackageOption,
17    Packager,
18    StartDirectory,
19    Version,
20};
21use clap::{Args, Parser, Subcommand, ValueEnum};
22use strum::Display;
23
24use crate::{Error, schema::BuildInfoSchema};
25
26/// A type wrapping a PathBuf with a default value
27///
28/// This type is used in circumstances where an output file is required that defaults to
29/// ".BUILDINFO"
30#[derive(Clone, Debug)]
31pub struct OutputFile(pub PathBuf);
32
33impl Default for OutputFile {
34    fn default() -> Self {
35        OutputFile(PathBuf::from(".BUILDINFO"))
36    }
37}
38
39impl Display for OutputFile {
40    fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
41        write!(fmt, "{}", self.0.display())
42    }
43}
44
45impl FromStr for OutputFile {
46    type Err = Error;
47
48    fn from_str(s: &str) -> Result<Self, Self::Err> {
49        Ok(OutputFile(PathBuf::from(s)))
50    }
51}
52
53/// The command-line interface handling for `alpm-buildinfo`.
54#[derive(Clone, Debug, Parser)]
55#[command(about, author, name = "alpm-buildinfo", version)]
56pub struct Cli {
57    /// The `alpm-buildinfo` commands.
58    #[command(subcommand)]
59    pub command: Command,
60}
61
62/// The `alpm-buildinfo` commands.
63#[allow(clippy::large_enum_variant)]
64#[derive(Clone, Debug, Subcommand)]
65pub enum Command {
66    /// Create a BUILDINFO file according to a schema
67    ///
68    /// If the input can be validated according to the schema, the program exits with no output and
69    /// a return code of 0. If the input can not be validated according to the schema, an error
70    /// is emitted on stderr and the program exits with a non-zero exit code.
71    #[command()]
72    Create {
73        /// The `create` command.
74        #[command(subcommand)]
75        command: CreateCommand,
76    },
77
78    /// Validate a BUILDINFO file
79    ///
80    /// Validate a BUILDINFO file according to a schema.
81    /// If the file can be validated, the program exits with no output and a return code of 0.
82    /// If the file can not be validated, an error is emitted on stderr and the program exits with
83    /// a non-zero exit code.
84    #[command()]
85    Validate {
86        /// Arguments for the `validate` command.
87        #[command(flatten)]
88        args: ValidateArgs,
89    },
90
91    /// Parse a BUILDINFO file and output it in a different format
92    #[command()]
93    Format {
94        /// Arguments for the `format` command.
95        #[command(flatten)]
96        args: ValidateArgs,
97
98        /// Provide the output format
99        #[arg(
100            short,
101            long,
102            value_name = "OUTPUT_FORMAT",
103            default_value_t = OutputFormat::Json
104        )]
105        output_format: OutputFormat,
106
107        /// Pretty-print the output
108        #[arg(short, long)]
109        pretty: bool,
110    },
111}
112
113/// Arguments for validating and parsing a BUILDINFO file
114#[derive(Args, Clone, Debug)]
115pub struct ValidateArgs {
116    /// Provide the BUILDINFO schema version to use.
117    ///
118    /// If no schema version is provided, it will be deduced from the file itself.
119    #[arg(short, long, value_name = "VERSION")]
120    pub schema: Option<BuildInfoSchema>,
121    /// Provide the file to read
122    #[arg(value_name = "FILE")]
123    pub file: Option<PathBuf>,
124}
125
126/// Arguments for creating a BUILDINFO file according to the format version 1 schema
127///
128/// This struct is defined separately for reusing it for both v1 and v2 since they have
129/// an overlapping set of fields.
130#[derive(Args, Clone, Debug)]
131pub struct V1CreateArgs {
132    /// Provide a builddate
133    #[arg(env = "BUILDINFO_BUILDDATE", long, value_name = "BUILDDATE")]
134    pub builddate: BuildDate,
135    /// Provide a builddir
136    #[arg(env = "BUILDINFO_BUILDDIR", long, value_name = "BUILDDIR")]
137    pub builddir: BuildDirectory,
138    /// Provide one or more buildenv
139    #[arg(
140        env = "BUILDINFO_BUILDENV",
141        long,
142        value_delimiter = ' ',
143        value_name = "BUILDENV"
144    )]
145    pub buildenv: Vec<BuildEnvironmentOption>,
146    /// Provide one or more installed
147    #[arg(
148        env = "BUILDINFO_INSTALLED",
149        long,
150        value_delimiter = ' ',
151        value_name = "INSTALLED"
152    )]
153    pub installed: Vec<InstalledPackage>,
154    /// Provide one or more options
155    #[arg(
156        env = "BUILDINFO_OPTIONS",
157        long,
158        value_delimiter = ' ',
159        value_name = "OPTIONS"
160    )]
161    pub options: Vec<PackageOption>,
162    /// Provide a packager
163    #[arg(env = "BUILDINFO_PACKAGER", long, value_name = "PACKAGER")]
164    pub packager: Packager,
165    /// Provide a pkgarch
166    #[arg(env = "BUILDINFO_PKGARCH", long, value_name = "PKGARCH")]
167    pub pkgarch: Architecture,
168    /// Provide a pkgbase
169    #[arg(env = "BUILDINFO_PKGBASE", long, value_name = "PKGBASE")]
170    pub pkgbase: Name,
171    /// Provide a pkgbuild_sha256sum
172    #[arg(
173        env = "BUILDINFO_PKGBUILD_SHA256SUM",
174        long,
175        value_name = "PKGBUILD_SHA256SUM"
176    )]
177    pub pkgbuild_sha256sum: String,
178    /// Provide a pkgname
179    #[arg(env = "BUILDINFO_PKGNAME", long, value_name = "PKGNAME")]
180    pub pkgname: Name,
181    /// Provide a pkgver
182    #[arg(env = "BUILDINFO_PKGVER", long, value_name = "PKGVER")]
183    pub pkgver: Version,
184    /// Provide a file to write to
185    #[arg(default_value_t = OutputFile::default(), env = "BUILDINFO_OUTPUT_FILE", value_name = "FILE")]
186    pub output: OutputFile,
187}
188
189/// Create an BUILDINFO file according to a schema
190///
191/// If the input can be validated according to the schema, the program exits with no output and
192/// a return code of 0. If the input can not be validated according to the schema, an error
193/// is emitted on stderr and the program exits with a non-zero exit code.
194#[derive(Clone, Debug, Subcommand)]
195pub enum CreateCommand {
196    /// Create a BUILDINFO version 1 file
197    V1 {
198        /// Arguments for the `create v1` command.
199        #[command(flatten)]
200        args: V1CreateArgs,
201    },
202    /// Create a BUILDINFO version 2 file
203    V2 {
204        /// Arguments for the `create v2` command.
205        #[command(flatten)]
206        args: V1CreateArgs,
207
208        /// Provide a startdir
209        #[arg(env = "BUILDINFO_STARTDIR", long, value_name = "STARTDIR")]
210        startdir: StartDirectory,
211
212        /// Provide a buildtool
213        #[arg(env = "BUILDINFO_BUILDTOOL", long, value_name = "BUILDTOOL")]
214        buildtool: BuildTool,
215
216        /// Provide a buildtoolver
217        #[arg(env = "BUILDINFO_BUILDTOOLVER", long, value_name = "BUILDTOOLVER")]
218        buildtoolver: BuildToolVersion,
219    },
220}
221
222/// Output format for the format command
223#[derive(Clone, Debug, Default, Display, ValueEnum)]
224#[non_exhaustive]
225pub enum OutputFormat {
226    /// The JSON output format.
227    #[default]
228    #[strum(to_string = "json")]
229    Json,
230}