dev_scripts/
cli.rs

1use std::{fmt::Display, path::PathBuf};
2
3use alpm_types::{MetadataFileName, PKGBUILD_FILE_NAME, SRCINFO_FILE_NAME};
4use clap::{Parser, ValueEnum};
5
6use crate::sync::PackageRepositories;
7
8#[derive(Debug, Parser)]
9#[clap(name = "dev-scripts", about = "Dev scripts for the ALPM project")]
10pub struct Cli {
11    /// Log verbosity level
12    #[command(flatten)]
13    pub verbose: clap_verbosity_flag::Verbosity,
14
15    #[clap(subcommand)]
16    pub cmd: Command,
17}
18
19#[derive(Debug, Parser)]
20pub enum Command {
21    /// Tests file formats with real-world files from official repositories.
22    TestFiles {
23        #[clap(subcommand)]
24        cmd: TestFilesCmd,
25
26        #[arg(
27            help = "The directory to use for download and test artifacts",
28            long,
29            long_help = r#"The directory to use for download and test artifacts.
30
31If unset, defaults to "$XDG_CACHE_HOME/alpm/testing/".
32If "$XDG_CACHE_HOME" is unset, falls back to "~/.cache/alpm/testing/"."#,
33            short,
34            value_name = "DIR"
35        )]
36        cache_dir: Option<PathBuf>,
37    },
38
39    /// Run the `alpm-pkgbuild srcinfo format` command on a PKGBUILD and compare its output with a
40    /// given .SRCINFO file.
41    CompareSrcinfo {
42        /// Path to the PKGBUILD file.
43        #[arg(
44            short,
45            long = "pkgbuild",
46            value_name = "PKGBUILD_PATH",
47            default_value = format!("./{PKGBUILD_FILE_NAME}")
48        )]
49        pkgbuild_path: PathBuf,
50
51        /// Path to the .SRCINFO file.
52        #[arg(
53            short,
54            long = "srcinfo",
55            value_name = "SRCINFO_PATH",
56            default_value = format!("./{SRCINFO_FILE_NAME}")
57        )]
58        srcinfo_path: PathBuf,
59    },
60}
61
62#[derive(Clone, Copy, Debug, Eq, Parser, PartialEq, ValueEnum)]
63pub enum TestFileType {
64    BuildInfo,
65    SrcInfo,
66    PackageInfo,
67    MTree,
68    RemoteDesc,
69    RemoteFiles,
70    LocalDesc,
71    LocalFiles,
72    Signatures,
73}
74
75impl Display for TestFileType {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        write!(
78            f,
79            "{}",
80            match self {
81                Self::BuildInfo => MetadataFileName::BuildInfo.as_ref(),
82                Self::PackageInfo => MetadataFileName::PackageInfo.as_ref(),
83                Self::SrcInfo => SRCINFO_FILE_NAME,
84                Self::MTree => MetadataFileName::Mtree.as_ref(),
85                Self::RemoteDesc | Self::LocalDesc => "desc",
86                Self::RemoteFiles | Self::LocalFiles => "files",
87                Self::Signatures => "sig",
88            }
89        )
90    }
91}
92
93#[derive(Debug, Parser)]
94pub enum TestFilesCmd {
95    /// Run tests against a specific file type.
96    ///
97    /// The required data needs to be downloaded up front using "dev-scripts test-files download".
98    Test {
99        /// Package repositories to test.
100        ///
101        /// If not set, all official repositories are tested.
102        #[arg(short, long)]
103        repositories: Option<Vec<PackageRepositories>>,
104
105        /// The type of file that should be tested.
106        file_type: TestFileType,
107    },
108
109    /// Download/synchronize files for testing to this machine.
110    ///
111    /// Each type of file can be downloaded individually.
112    Download {
113        /// Package repositories to download.
114        ///
115        /// If not set, all official repositories are downloaded.
116        #[arg(short, long)]
117        repositories: Option<Vec<PackageRepositories>>,
118
119        #[clap(subcommand)]
120        source: DownloadCmd,
121    },
122
123    /// Remove or clean downloaded local testing files.
124    Clean {
125        #[clap(subcommand)]
126        source: CleanCmd,
127    },
128}
129
130#[derive(Debug, Parser)]
131pub enum DownloadCmd {
132    /// Download all official package source repositories
133    ///
134    /// This is done by querying all active repositories via the arch web API
135    /// (<https://archlinux.org/packages/pkgbase-maintainer>) and cloning the respective
136    /// package source repositories via git.
137    ///
138    /// This command differs from `pkgctl repo clone --universe` in so far that it
139    /// also updates git repositories and removes repositories that're no longer used.
140    ///
141    /// The repositories contain the following file types for each package.
142    /// - .SRCINFO
143    PkgSrcRepositories {},
144
145    /// Download all AUR packages metadata.
146    ///
147    /// AUR uses a monorepo that holds each package in a separate branch.
148    /// This command first fetches a list of all packages from aurweb and clones aur.git mirror.
149    /// The `.SRCINFO` and `PKGBUILD` files are then extracted from the git branches.
150    Aur {},
151
152    /// Create a copy of a mirror's pacman database.
153    ///
154    /// The database contains the following file types for each package.
155    /// - `files`
156    /// - `desc`
157    Databases {
158        /// The domain + base path under which the mirror can be found.
159        ///
160        /// The mirror must support the `rsync` protocol
161        #[arg(short, long, env, default_value = "mirror.pseudoform.org/packages")]
162        mirror: String,
163
164        /// Force re-extraction of the files regardless of reported changes.
165        ///
166        /// This is useful for if the download is cancelled halfway, in which case
167        /// `rsync` will not report changes for files that it downloaded last time.
168        #[arg(short, long, default_value_t = false)]
169        force_extract: bool,
170    },
171    /// The packages contain the following file types for each package.
172    /// - `.INSTALL`
173    /// - `.BUILDINFO`
174    /// - `.MTREE`
175    /// - `.PKGINFO`
176    Packages {
177        /// The domain + base path under which the mirror can be found.
178        ///
179        /// The mirror must support the `rsync` protocol
180        #[arg(short, long, env, default_value = "mirror.pseudoform.org/packages")]
181        mirror: String,
182
183        /// Force re-extraction of the files regardless of reported changes.
184        ///
185        /// This is useful for if the download is cancelled halfway, in which case
186        /// `rsync` will not report changes for files that it downloaded last time.
187        #[arg(short, long, default_value_t = false)]
188        force_extract: bool,
189    },
190}
191
192#[derive(Debug, Parser)]
193pub enum CleanCmd {
194    /// Remove all package source repositories and .SRCINFO files
195    PkgSrcRepositories,
196
197    /// Remove extracted repository sync database files and tarballs.
198    Databases,
199
200    /// Remove all downloaded packages and any other files extracted from them.
201    Packages,
202}