alpm_srcinfo/
commands.rs

1//! Functions called from the binary.
2use std::{
3    io::{self, IsTerminal},
4    path::PathBuf,
5};
6
7use alpm_common::MetadataFile;
8use alpm_types::Architecture;
9
10use crate::{
11    SourceInfo,
12    SourceInfoSchema,
13    cli::{PackagesOutputFormat, SourceInfoOutputFormat},
14    error::Error,
15    source_info::v1::merged::MergedPackage,
16};
17
18/// Validates a SRCINFO file from a path or stdin.
19///
20/// Wraps the [`parse`] function and allows to ensure that no errors occurred during parsing.
21pub fn validate(file: Option<&PathBuf>, schema: Option<SourceInfoSchema>) -> Result<(), Error> {
22    let _result = parse(file, schema)?;
23
24    Ok(())
25}
26
27/// Parses a SRCINFO file from a path or stdin and outputs it in the specified format on stdout.
28///
29/// # Errors
30///
31/// Returns an error if the input can not be parsed and validated, or if the output can not be
32/// formatted in the selected output format.
33pub fn format_source_info(
34    file: Option<&PathBuf>,
35    schema: Option<SourceInfoSchema>,
36    output_format: SourceInfoOutputFormat,
37    pretty: bool,
38) -> Result<(), Error> {
39    let srcinfo = parse(file, schema)?;
40    let SourceInfo::V1(source_info) = srcinfo;
41
42    match output_format {
43        SourceInfoOutputFormat::Json => {
44            let json = if pretty {
45                serde_json::to_string_pretty(&source_info)?
46            } else {
47                serde_json::to_string(&source_info)?
48            };
49            println!("{json}");
50        }
51        SourceInfoOutputFormat::Srcinfo => {
52            println!("{}", source_info.as_srcinfo())
53        }
54    }
55
56    Ok(())
57}
58
59/// Parses a SRCINFO file from a path or stdin and outputs all info grouped by packages for a given
60/// architecture in the specified format on stdout.
61///
62/// # Errors
63///
64/// Returns an error if the input can not be parsed and validated, or if the output can not be
65/// formatted in the selected output format.
66pub fn format_packages(
67    file: Option<&PathBuf>,
68    schema: Option<SourceInfoSchema>,
69    output_format: PackagesOutputFormat,
70    architecture: Architecture,
71    pretty: bool,
72) -> Result<(), Error> {
73    let srcinfo = parse(file, schema)?;
74    let SourceInfo::V1(source_info) = srcinfo;
75
76    let packages: Vec<MergedPackage> = source_info
77        .packages_for_architecture(architecture)
78        .collect();
79
80    match output_format {
81        PackagesOutputFormat::Json => {
82            let json = if pretty {
83                serde_json::to_string_pretty(&packages)?
84            } else {
85                serde_json::to_string(&packages)?
86            };
87            println!("{json}");
88        }
89    }
90
91    Ok(())
92}
93
94/// Parses and interprets a SRCINFO file from a path or stdin.
95///
96/// ## Note
97///
98/// If a command is piped to this process, the input is read from stdin.
99/// See [`IsTerminal`] for more information about how terminal detection works.
100///
101/// [`IsTerminal`]: https://doc.rust-lang.org/stable/std/io/trait.IsTerminal.html
102///
103/// # Errors
104///
105/// Returns an error if the input can not be parsed and validated, or if the output can not be
106/// formatted in the selected output format.
107///
108/// Furthermore, returns an error array with potentially un/-recoverable (linting-)errors, which
109/// needs to be explicitly handled by the caller.
110pub fn parse(
111    file: Option<&PathBuf>,
112    schema: Option<SourceInfoSchema>,
113) -> Result<SourceInfo, Error> {
114    if let Some(file) = file {
115        SourceInfo::from_file_with_schema(file, schema)
116    } else if !io::stdin().is_terminal() {
117        SourceInfo::from_stdin_with_schema(schema)
118    } else {
119        Err(Error::NoInputFile)
120    }
121}