Change argument parsing to clap v3 derives

With this change the arguments are parsed with the
new clap v3 derive syntax. This commit also sets the
default command to Upgrade similar to the behaviour
of other aur helpers.

Signed-off-by: Trivernis <trivernis@protonmail.com>
i18n
Trivernis 2 years ago
parent 09a5748827
commit 2c2677ae88

@ -51,7 +51,8 @@ codegen-units = 1
[dependencies]
mimalloc = { version = "0.1.27", default-features = false }
clap = { version = "2.34.0", default-features = false, features = ["suggestions"] }
clap = { version = "3.1.9", features = [ "derive", "wrap_help"] }
clap_complete = "3.1.1"
regex = { version = "1.5.4", default-features = false, features = ["std", "unicode-perl"] }
runas = "0.2.1"
rusqlite = { version = "0.26.3", default-features = false }

@ -0,0 +1,85 @@
use clap::{Parser, Subcommand};
#[derive(Debug, Clone, Parser)]
#[clap(name="Amethyst", version=env!("CARGO_PKG_VERSION"), about=env!("CARGO_PKG_DESCRIPTION"))]
pub struct Args {
#[clap(subcommand)]
pub subcommand: Option<Operation>,
/// Sets the level of verbosity
#[clap(long, short, parse(from_occurrences))]
pub verbose: usize,
/// Complete operation without prompting user
#[clap(long = "noconfirm")]
pub no_confirm: bool,
}
#[derive(Debug, Clone, Subcommand)]
pub enum Operation {
/// Installs a package from either the AUR or the PacMan-defined repositories
#[clap(name="install", aliases=&["i", "-S"])]
Install(InstallArgs),
/// Removes a previously installed package
#[clap(name="remove", aliases=&["rm", "-R", "Rs"])]
Remove(RemoveArgs),
/// Searches for the relevant packages in both the AUR and repos
#[clap(name="search", aliases=&["sea", "-Ss"])]
Search(SearchArgs),
/// Queries installed packages
#[clap(name="query", aliases=&["ls", "-Q"])]
Query(QueryArgs),
/// Upgrades locally installed packages to their latest versions
#[clap(name="upgrade", aliases=&["upg", "-Syu"])]
Upgrade,
}
impl Default for Operation {
fn default() -> Self {
Self::Upgrade
}
}
#[derive(Default, Debug, Clone, Parser)]
pub struct InstallArgs {
/// The name of the package(s) to install
#[clap(required = true)]
pub packages: Vec<String>,
}
#[derive(Default, Debug, Clone, Parser)]
pub struct RemoveArgs {
/// The name of the package(s) to remove
#[clap(required = true)]
pub packages: Vec<String>,
}
#[derive(Default, Debug, Clone, Parser)]
pub struct SearchArgs {
/// Searches for the relevant packages in both the AUR and repos
#[clap(long, short)]
pub aur: bool,
/// Searches only local repos for the package
#[clap(long, short)]
pub repo: bool,
/// The string the package must match in the search
#[clap(required = true)]
pub search: Vec<String>,
}
#[derive(Default, Debug, Clone, Parser)]
pub struct QueryArgs {
/// Lists AUR/foreign packages
#[clap(long, short)]
pub aur: bool,
/// Lists repo/native packages
#[clap(long, short)]
pub repo: bool,
}

@ -1,13 +1,16 @@
use std::process::{exit, Command};
use std::{env, io, process};
use clap::Parser;
use std::process;
use std::process::Command;
use clap::{App, AppSettings, Arg, ArgMatches, ArgSettings, Shell, SubCommand};
use crate::args::{InstallArgs, Operation, QueryArgs, RemoveArgs, SearchArgs};
use args::Args;
use crate::internal::{crash, info, init, log, sort, structs::Options};
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
mod args;
mod database;
mod internal;
mod operations;
@ -21,118 +24,10 @@ fn main() {
crash("Running amethyst as root is disallowed as it can lead to system breakage. Instead, amethyst will prompt you when it needs superuser permissions".to_string(), 1);
}
fn build_app() -> App<'static, 'static> {
let app = App::new("Amethyst")
.version(env!("CARGO_PKG_VERSION"))
.about(env!("CARGO_PKG_DESCRIPTION"))
.arg(
Arg::with_name("verbose")
.short("v")
.long("verbose")
.multiple(true)
.set(ArgSettings::Global)
.help("Sets the level of verbosity"),
)
.arg(
Arg::with_name("noconfirm")
.long("noconfirm")
.set(ArgSettings::Global)
.help("Complete operation without prompting user"),
)
.subcommand(
SubCommand::with_name("install")
.about(
"Installs a package from either the AUR or the PacMan-defined repositories",
)
.aliases(&["-S", "ins"])
.arg(
Arg::with_name("package(s)")
.help("The name of the package(s) to install")
.required(true)
.multiple(true)
.index(1),
),
)
.subcommand(
SubCommand::with_name("remove")
.about("Removes a previously installed package")
.aliases(&["-R", "-Rs", "rm"])
.arg(
Arg::with_name("package(s)")
.help("The name of the package(s) to remove")
.required(true)
.multiple(true)
.index(1),
),
)
.subcommand(
SubCommand::with_name("search")
.about("Searches for the relevant packages in both the AUR and repos")
.aliases(&["-Ss", "sea"])
.arg(
Arg::with_name("aur")
.short("a")
.long("aur")
.help("Search only the AUR for the package"),
)
.arg(
Arg::with_name("repo")
.short("r")
.long("repo")
.help("Searches only local repos for the package"),
)
.arg(
Arg::with_name("package(s)")
.help("The name of the package to search for")
.required(true)
.multiple(false)
.index(1),
),
)
.subcommand(
SubCommand::with_name("query")
.about("Queries installed packages")
.aliases(&["-Q", "ls"])
.arg(
Arg::with_name("aur")
.short("a")
.help("Lists AUR/foreign packages"),
)
.arg(
Arg::with_name("repo")
.short("r")
.help("Lists repo/native packages"),
),
)
.subcommand(
SubCommand::with_name("upgrade")
.about("Upgrades locally installed packages to their latest versions")
.aliases(&["-Syu", "upg"]),
)
.subcommand(
SubCommand::with_name("compgen")
.about("Generates shell completions for given shell (bash by default)")
.aliases(&["-G", "cg"])
.arg(
Arg::with_name("shell")
.help("The name of the shell you want to generate completions for")
.possible_values(&["bash", "fish", "zsh", "pwsh", "elvish"])
.required(true),
),
)
.settings(&[
AppSettings::GlobalVersion,
AppSettings::VersionlessSubcommands,
AppSettings::ArgRequiredElseHelp,
AppSettings::InferSubcommands,
]);
app
}
let matches = build_app().get_matches();
let args: Args = Args::parse();
let verbosity: i32 = matches.occurrences_of("verbose") as i32;
let noconfirm: bool = matches.is_present("noconfirm");
let verbosity = args.verbose as i32;
let noconfirm = args.no_confirm;
let options = Options {
verbosity,
@ -142,174 +37,104 @@ fn main() {
init(options);
fn collect_matches(a: &ArgMatches) -> Vec<String> {
a.subcommand()
.1
.unwrap()
.values_of("package(s)")
.unwrap()
.into_iter()
.map(|s| s.to_string())
.collect()
match args.subcommand.unwrap_or_default() {
Operation::Install(install_args) => cmd_install(install_args, options),
Operation::Remove(remove_args) => cmd_remove(remove_args, options),
Operation::Search(search_args) => cmd_search(search_args, options),
Operation::Query(query_args) => cmd_query(query_args),
Operation::Upgrade => {
info("Performing system upgrade".to_string());
operations::upgrade(options);
}
}
}
if let true = matches.is_present("install") {
let packages = collect_matches(&matches);
let sorted = sort(&packages, options);
fn cmd_install(args: InstallArgs, options: Options) {
let packages = args.packages;
let sorted = sort(&packages, options);
info(format!(
"Attempting to install packages: {}",
packages.join(", ")
info(format!(
"Attempting to install packages: {}",
packages.join(", ")
));
if !sorted.repo.is_empty() {
operations::install(sorted.repo, options);
}
if !sorted.aur.is_empty() {
operations::aur_install(sorted.aur, options);
}
if !sorted.nf.is_empty() {
log(format!(
"Couldn't find packages: {} in repos or the AUR",
sorted.nf.join(", ")
));
}
if !sorted.repo.is_empty() {
operations::install(sorted.repo, options);
}
if !sorted.aur.is_empty() {
operations::aur_install(sorted.aur, options);
}
if !sorted.nf.is_empty() {
log(format!(
"Couldn't find packages: {} in repos or the AUR",
sorted.nf.join(", ")
));
}
let out = process::Command::new("bash")
.args(&["-c", "sudo find /etc -name *.pacnew"])
.output()
.expect("Something has gone wrong")
.stdout;
let out = process::Command::new("bash")
.args(&["-c", "sudo find /etc -name *.pacnew"])
.output()
.expect("Something has gone wrong")
.stdout;
if !String::from_utf8((*out).to_owned()).unwrap().is_empty() {
info(format!("You have .pacnew files in /etc ({}) that you haven't removed or acted upon, it is recommended you do that now", String::from_utf8((*out).to_owned()).unwrap().split_whitespace().collect::<Vec<&str>>().join(", ")));
}
}
if !String::from_utf8((*out).to_owned()).unwrap().is_empty() {
info(format!("You have .pacnew files in /etc ({}) that you haven't removed or acted upon, it is recommended you do that now", String::from_utf8((*out).to_owned()).unwrap().split_whitespace().collect::<Vec<&str>>().join(", ")));
}
fn cmd_remove(args: RemoveArgs, options: Options) {
let packages = args.packages;
info(format!("Uninstalling packages: {}", &packages.join(", ")));
operations::uninstall(packages, options);
}
exit(0);
fn cmd_search(args: SearchArgs, options: Options) {
let query_string = args.search.join(" ");
if args.aur {
info(format!("Searching AUR for {}", &query_string));
operations::aur_search(&query_string, options);
}
if let true = matches.is_present("remove") {
let packages = collect_matches(&matches);
info(format!("Uninstalling packages: {}", &packages.join(", ")));
operations::uninstall(packages, options);
exit(0);
if args.repo {
info(format!("Searching repos for {}", &query_string));
operations::search(&query_string, options);
}
if let true = matches.is_present("upgrade") {
info("Performing system upgrade".to_string());
operations::upgrade(options);
exit(0);
if !args.aur && !args.repo {
info(format!("Searching AUR and repos for {}", &query_string));
operations::search(&query_string, options);
operations::aur_search(&query_string, options);
}
}
if let true = matches.is_present("search") {
let packages = collect_matches(&matches);
if matches
.subcommand_matches("search")
.unwrap()
.is_present("aur")
{
info(format!("Searching AUR for {}", &packages[0]));
operations::aur_search(&packages[0], options);
}
if matches
.subcommand_matches("search")
.unwrap()
.is_present("repo")
{
info(format!("Searching repos for {}", &packages[0]));
operations::search(&packages[0], options);
}
if !matches
.subcommand_matches("search")
.unwrap()
.is_present("repo")
&& !matches
.subcommand_matches("search")
.unwrap()
.is_present("aur")
{
info(format!("Searching AUR and repos for {}", &packages[0]));
operations::search(&packages[0], options);
operations::aur_search(&packages[0], options);
}
exit(0);
fn cmd_query(args: QueryArgs) {
if args.aur {
Command::new("pacman")
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
if let true = matches.is_present("query") {
if matches
.subcommand_matches("query")
.unwrap()
.is_present("aur")
{
Command::new("pacman")
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
if matches
.subcommand_matches("query")
.unwrap()
.is_present("repo")
{
Command::new("pacman")
.arg("-Qn")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
if !matches
.subcommand_matches("query")
.unwrap()
.is_present("aur")
&& !matches
.subcommand_matches("query")
.unwrap()
.is_present("repo")
{
Command::new("pacman")
.arg("-Qn")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
Command::new("pacman")
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
exit(0);
if args.repo {
Command::new("pacman")
.arg("-Qn")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
if let true = &matches.is_present("compgen") {
let mut app = build_app();
match matches
.subcommand_matches("compgen")
.unwrap()
.value_of("shell")
.unwrap()
{
"bash" => {
app.gen_completions_to("ame", Shell::Bash, &mut io::stdout());
}
"fish" => {
app.gen_completions_to("ame", Shell::Fish, &mut io::stdout());
}
"zsh" => {
app.gen_completions_to("ame", Shell::Zsh, &mut io::stdout());
}
"pwsh" => {
app.gen_completions_to("ame", Shell::PowerShell, &mut io::stdout());
}
"elvish" => {
app.gen_completions_to("ame", Shell::Elvish, &mut io::stdout());
}
_ => {}
}
if !args.repo && !args.aur {
Command::new("pacman")
.arg("-Qn")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
Command::new("pacman")
.arg("-Qm")
.spawn()
.expect("Something has gone wrong")
.wait()
.unwrap();
}
}

Loading…
Cancel
Save