Skip to content
This repository was archived by the owner on Nov 21, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 54 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ categories = ["command-line-utilities"]
bat = { version = "0.21.0", default-features = false, features = ["paging", "regex-fancy"]}
colored = { git = "https://github.com/mackwic/colored" }
chrono = "0.4.19"
clap = { version = "3.2.16", features = ["cargo", "env"] }
clap = { version = "4.0.18", features = ["cargo", "env", "derive"] }
dirs = "4.0.0"
edit = "0.1.4"
exitcode = "1.1.2"
Expand Down
157 changes: 157 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use clap::{Parser, ValueEnum};

#[derive(Debug, Clone, ValueEnum)]
pub enum CliPaging {
/// auto
Auto,
/// always
Always,
/// never
Never,
}

#[derive(Debug, Parser)]
#[command(author, version, about)]
pub struct Cli {
/// The API token to authenticate to the MPR with
#[clap(long, env = "MPR_TOKEN", hide_env_values = true)]
pub token: Option<String>,

/// URL to access the MPR from
#[clap(
long,
env = "MPR_URL",
hide_env_values = true,
default_value = "https://mpr.makedeb.org"
)]
pub mpr_url: String,

/// Filter results to packages available on the MPR
#[arg(long, default_value_t = false, conflicts_with = "apt_only")]
pub mpr_only: bool,

/// Filter results to packages available via APT
#[arg(long, default_value_t = false, conflicts_with = "mpr_only")]
pub apt_only: bool,

/// Filter results to installed packages
#[clap(long, short = 'i')]
#[arg(default_value_t = false)]
pub installed_only: bool,

/// Output the package's name without any extra details
#[clap(long, default_value = "false")]
pub name_only: bool,

#[clap(subcommand)]
pub subcommand: CliSubcommand,
}

#[derive(Debug, Parser)]
pub enum CliSubcommand {
/// Clone a package base from the MPR
Clone(CliClone),

/// Comment on a package page
Comment(CliComment),

/// Install packages from APT and the MPR
Install(CliInstall),

/// List packages available via APT and the MPR
List(CliList),

/// List the comments on a package
ListComments(CliListComments),

/// Remove packages from the system
Remove(CliRemove),

/// Search for an APT/MPR package
Search(CliSearch),

/// Update the APT cache on the system
Update(CliUpdate),

/// Upgrade the packages on the system
Upgrade(CliUpgrade),

/// Show the currently authenticated user
Whoami(CliWhoami),
}

#[derive(Debug, Parser)]
pub struct CliClone {
/// The package to clone
#[clap(required = true)]
pub pkg: String,
}

#[derive(Debug, Parser)]
pub struct CliComment {
/// The package to comment on
#[clap(required = true)]
pub pkg: String,

/// The comment to post
#[clap(long, short)]
pub msg: Option<String>,
}

#[derive(Debug, Parser)]
pub struct CliInstall {
/// The package(s) to install
#[clap(required = true)]
pub pkg: Vec<String>,
}

#[derive(Debug, Parser)]
pub struct CliList {
/// The package(s) to get information for
pub pkg: Vec<String>,
}

#[derive(Debug, Parser)]
pub struct CliListComments {
/// The package to view comments for
#[clap(required = true)]
pub pkg: String,

/// When to send output to a pager
#[clap(long)]
#[arg(value_enum, default_value_t = CliPaging::Auto)]
pub paging: CliPaging,
}

#[derive(Debug, Parser)]
pub struct CliRemove {
/// The package(s) to remove
#[clap(required = true)]
pub pkg: Vec<String>,

/// Remove configuration files along with the package(s)
#[clap(long)]
#[arg(default_value_t = false)]
pub purge: bool,

/// Automatically remove any unneeded packages
#[clap(long)]
#[arg(default_value_t = false)]
pub autoremove: bool,
}

#[derive(Debug, Parser)]
pub struct CliSearch {
/// The query to search for
#[clap(required = true)]
pub query: Vec<String>,
}

#[derive(Debug, Parser)]
pub struct CliUpdate {}

#[derive(Debug, Parser)]
pub struct CliUpgrade {}

#[derive(Debug, Parser)]
pub struct CliWhoami {}
7 changes: 4 additions & 3 deletions src/clone.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::{
cache::{Cache, MprCache},
cli::{Cli, CliClone},
message, util,
};
use rust_apt::cache::Cache as AptCache;

pub fn clone(args: &clap::ArgMatches) {
let pkg: &String = args.get_one("pkg").unwrap();
let mpr_url: &String = args.get_one("mpr-url").unwrap();
pub fn clone(args: &Cli, cmd_args: &CliClone) {
let pkg = &cmd_args.pkg;
let mpr_url = &args.mpr_url;
let cache = Cache::new(AptCache::new(), MprCache::new());
let mut pkgbases: Vec<&String> = Vec::new();

Expand Down
13 changes: 7 additions & 6 deletions src/comment.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::cli::{Cli, CliComment};
use crate::{cache::MprCache, message, util};
use serde::Deserialize;
use serde_json::json;
Expand All @@ -9,10 +10,10 @@ struct CommentResult {
link: String,
}

pub fn comment(args: &clap::ArgMatches) {
let pkg: &String = args.get_one("pkg").unwrap();
let mpr_url: &String = args.get_one("mpr-url").unwrap();
let api_token: &String = match args.get_one("token") {
pub fn comment(args: &Cli, cmd_args: &CliComment) {
let pkg = &cmd_args.pkg;
let mpr_url = &args.mpr_url;
let api_token = match &args.token {
Some(token) => token,
None => {
message::error("No API token was provided.\n");
Expand All @@ -36,8 +37,8 @@ pub fn comment(args: &clap::ArgMatches) {

// Get the message.
// If no message was supplied, get one from the user.
let msg: String = match args.get_one::<String>("msg") {
Some(msg) => (msg).to_owned(),
let msg: String = match &cmd_args.msg {
Some(msg) => msg.to_owned(),
None => {
// Get the editor.
let editor = match edit::get_editor() {
Expand Down
16 changes: 8 additions & 8 deletions src/install.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::{
cache::{Cache, MprCache},
cli::{Cli, CliInstall},
install_util, message,
style::Colorize,
util,
};
use rust_apt::cache::Cache as AptCache;

pub fn install(args: &clap::ArgMatches) {
let pkglist: Vec<&String> = args.get_many("pkg").unwrap().collect();
let mpr_url: &String = args.get_one("mpr-url").unwrap();
pub fn install(args: &Cli, cmd_args: &CliInstall) {
let pkglist = &cmd_args.pkg;
let mpr_url = &args.mpr_url;
let cache = Cache::new(AptCache::new(), MprCache::new());

// Package sources.
Expand All @@ -20,9 +21,8 @@ pub fn install(args: &clap::ArgMatches) {
// should just show those packages and abort.
let mut unfindable = false;

for pkg in &pkglist {
if cache.apt_cache().get(pkg).is_none() && !cache.mpr_cache().packages().contains_key(*pkg)
{
for pkg in pkglist {
if cache.apt_cache().get(pkg).is_none() && !cache.mpr_cache().packages().contains_key(pkg) {
message::error(&format!(
"Unable to find package '{}'.\n",
pkg.green().bold()
Expand All @@ -35,9 +35,9 @@ pub fn install(args: &clap::ArgMatches) {
quit::with_code(exitcode::USAGE);
}

for pkg in &pkglist {
for pkg in pkglist {
let apt_pkg = cache.apt_cache().get(pkg);
let mpr_pkg = cache.mpr_cache().packages().get(*pkg);
let mpr_pkg = cache.mpr_cache().packages().get(pkg);

if apt_pkg.is_some() && mpr_pkg.is_some() {
let resp = util::ask_question(
Expand Down
16 changes: 7 additions & 9 deletions src/list.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use crate::{
cache::{Cache, MprCache},
cli::{Cli, CliList},
style,
};
use rust_apt::cache::{Cache as AptCache, PackageSort};

pub fn list(args: &clap::ArgMatches) {
let pkglist: Vec<&String> = match args.get_many("pkg") {
Some(pkglist) => pkglist.collect(),
None => Vec::new(),
};
let apt_only = args.is_present("apt-only");
let mpr_only = args.is_present("mpr-only");
let installed_only = args.is_present("installed-only");
let name_only = args.is_present("name-only");
pub fn list(args: &Cli, cmd_args: &CliList) {
let pkglist = &cmd_args.pkg;
let apt_only = args.apt_only;
let mpr_only = args.mpr_only;
let installed_only = args.installed_only;
let name_only = args.name_only;

let cache = Cache::new(AptCache::new(), MprCache::new());
let mut candidates = Vec::new();
Expand Down
Loading