From 5711936392b898fe61c26dae017f9878966998e3 Mon Sep 17 00:00:00 2001 From: diced Date: Sun, 17 Oct 2021 15:34:19 -0700 Subject: [PATCH] run command & new log macros --- Cargo.lock | 4 +++- Cargo.toml | 7 ++----- README.md | 14 ++++++++------ src/cli/install.rs | 7 +++---- src/cli/mod.rs | 3 ++- src/cli/remove.rs | 19 +++++++++---------- src/cli/run.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/cli/update.rs | 9 ++++----- src/common.rs | 2 ++ src/completions.rs | 3 +-- src/lib.rs | 34 +++++++++++++++++++++++----------- src/main.rs | 41 ++++++++++++++++++++++++++++------------- src/util.rs | 37 ++++++++++++++++++------------------- 13 files changed, 141 insertions(+), 77 deletions(-) create mode 100644 src/cli/run.rs diff --git a/Cargo.lock b/Cargo.lock index 92af227..8bab8a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "atty" version = "0.2.14" @@ -123,7 +125,7 @@ checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "dvm" -version = "1.1.6" +version = "1.1.7" dependencies = [ "clap", "clap_generate", diff --git a/Cargo.toml b/Cargo.toml index 31f46cb..cb7a2a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,16 +4,13 @@ description = "discord version manager for linux" homepage = "https://github.com/diced/dvm" repository = "https://github.com/diced/dvm.git" license = "MIT" -version = "1.1.6" +version = "1.1.7" authors = ["diced "] -edition = "2018" +edition = "2021" [[bin]] name = "dvm" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] tokio = { version = "1.6.0", features = ["full"] } reqwest = { version = "0.11.3", features = ["json", "native-tls", "blocking"], default-features = false } diff --git a/README.md b/README.md index 7b584ac..8846e38 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Allowing you to manage all of your discord versions. This was made as I was impa # Usage ``` -dvm 0.1.1 +dvm 1.1.4 USAGE: dvm @@ -14,11 +14,13 @@ FLAGS: -V, --version Prints version information SUBCOMMANDS: - help Prints this message or the help of the given subcommand(s) - install install the latest of discord - remove remove the installed of discord - show show all installed versions - update update to the latest of discord + completions get shell completions + help Prints this message or the help of the given subcommand(s) + install install the latest of discord + remove remove the installed of discord + run run discord with specific options + show show all installed versions + update update to the latest of discord ``` # Installing diff --git a/src/cli/install.rs b/src/cli/install.rs index fd2ae70..2feecec 100644 --- a/src/cli/install.rs +++ b/src/cli/install.rs @@ -7,7 +7,7 @@ pub async fn install(release_type: Type, verbose: bool) -> Res<()> { let user = env::var("USER")?; fs::create_dir_all(format!("/home/{}/.dvm/bin", user))?; if verbose { - info("created .dvm dir") + info!("created .dvm dir") } let pascal_pkg = match release_type { @@ -20,12 +20,11 @@ pub async fn install(release_type: Type, verbose: bool) -> Res<()> { let exists = Path::new(&format!("/home/{}/.dvm/{}", user, pascal_pkg)).exists(); if exists { - error(format!("{} is already installed", release_type)); - std::process::exit(1); + error!("{} is already installed", release_type); } let (latest, _) = install_version(false, release_type.clone(), verbose, user).await?; - success(format!("installed {}:{}", release_type, latest)); + success!("installed {}:{}", release_type, latest); Ok(()) } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 26e1368..07daec2 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -2,5 +2,6 @@ mod install; mod remove; mod show; mod update; +mod run; -pub use {install::install, remove::remove, show::show, update::update}; \ No newline at end of file +pub use {install::install, remove::remove, show::show, update::update, run::run}; \ No newline at end of file diff --git a/src/cli/remove.rs b/src/cli/remove.rs index 56bbe36..8c1f05a 100644 --- a/src/cli/remove.rs +++ b/src/cli/remove.rs @@ -23,33 +23,32 @@ pub async fn remove(release_type: Type, verbose: bool) -> Res<()> { let exists = Path::new(&format!("/home/{}/.dvm/{}", user, pascal_pkg)).exists(); if verbose { - info("checking if installation exists") + info!("checking if installation exists") } if !exists { - error(format!("{} not installed", release_type)); - std::process::exit(1); + error!("{} not installed", release_type); } let version = fs::read_to_string(format!("/home/{}/.dvm/{}/version", user, pascal_pkg)) .expect("could not read version file: malformed installation detected"); if verbose { - info("reading version file") + info!("reading version file") } - info(format!("removing version {}:{}", release_type, version)); + info!("removing version {}:{}", release_type, version); // remove all {release type} associated files fs::remove_dir_all(format!("/home/{}/.dvm/{}", user, pascal_pkg)) .expect("error when removing data dirs"); if verbose { - info("removed data dirs") + info!("removed data dirs") } fs::remove_file(format!("/home/{}/.dvm/bin/{}", user, pkg_name)) .expect("error when removing bin file"); if verbose { - info("removed bin file") + info!("removed bin file") } fs::remove_file(format!( @@ -58,7 +57,7 @@ pub async fn remove(release_type: Type, verbose: bool) -> Res<()> { )) .expect("error when removing desktop file"); if verbose { - info("removed desktop file") + info!("removed desktop file") } fs::remove_file(format!( @@ -67,9 +66,9 @@ pub async fn remove(release_type: Type, verbose: bool) -> Res<()> { )) .expect("error when removing icon"); if verbose { - info("removed icon") + info!("removed icon") } - success(format!("removed version {}:{}", release_type, version)); + success!("removed version {}:{}", release_type, version); Ok(()) } diff --git a/src/cli/run.rs b/src/cli/run.rs new file mode 100644 index 0000000..7bdd603 --- /dev/null +++ b/src/cli/run.rs @@ -0,0 +1,38 @@ +use std::{env, fs, path::Path}; + +use tokio::process::Command; + +use crate::{Res, error, info, r#type::Type}; + +pub async fn run(release_type: Type, args: Vec, verbose: bool) -> Res<()> { + // create user var & create .dvm dirs + let user = env::var("USER")?; + fs::create_dir_all(format!("/home/{}/.dvm/bin", user))?; + + // create user var & create .dvm dirs + let user = env::var("USER")?; + fs::create_dir_all(format!("/home/{}/.dvm/bin", user))?; + if verbose { + info!("created .dvm dir") + } + + let pascal_pkg = match release_type { + Type::STABLE => "Discord", + Type::PTB => "DiscordPTB", + Type::CANARY => "DiscordCanary", + Type::DEVELOPMENT => "DiscordDevelopment", + }; + + let exists = Path::new(&format!("/home/{}/.dvm/{}", user, pascal_pkg)).exists(); + + if !exists { + error!("{} is not installed", release_type); + } + + Command::new(format!("/home/{}/.dvm/{}/{}", user, pascal_pkg, pascal_pkg)) + .args(&args) + .spawn()? + .wait_with_output().await?; + + Ok(()) +} diff --git a/src/cli/update.rs b/src/cli/update.rs index b642431..f85c0e9 100644 --- a/src/cli/update.rs +++ b/src/cli/update.rs @@ -11,7 +11,7 @@ pub async fn update(release_type: Type, verbose: bool) -> Res<()> { let user = env::var("USER")?; fs::create_dir_all(format!("/home/{}/.dvm/bin", user))?; if verbose { - info("created .dvm dir") + info!("created .dvm dir") } let pascal_pkg = match release_type { @@ -24,16 +24,15 @@ pub async fn update(release_type: Type, verbose: bool) -> Res<()> { let exists = Path::new(&format!("/home/{}/.dvm/{}", user, pascal_pkg)).exists(); if !exists { - error(format!("{} is not installed", release_type)); - std::process::exit(1); + error!("{} is not installed", release_type); } let (latest, version) = install_version(true, release_type.clone(), verbose, user).await?; - success(format!( + success!( "updated {}:{} -> {}:{}", release_type, version, release_type, latest - )); + ); Ok(()) } diff --git a/src/common.rs b/src/common.rs index 25fb2ae..7e18c10 100644 --- a/src/common.rs +++ b/src/common.rs @@ -9,6 +9,8 @@ pub const SHOW_DESC: &str = "show all installed versions"; pub const SHOW_ALIASES: &[&str] = &["s", "installed", "all", "a", "versions", "types"]; pub const COMP_DESC: &str = "get shell completions"; pub const COMP_ALIASES: &[&str] = &["c", "comp"]; +pub const RUN_DESC: &str = "run discord with specific options"; +pub const RUN_ALIASES: &[&str] = &["r", "start", "s"]; pub const POSSIBLE_SHELLS: &[&str] = &[ "bash", "b", diff --git a/src/completions.rs b/src/completions.rs index d69ea4d..c0781da 100644 --- a/src/completions.rs +++ b/src/completions.rs @@ -12,8 +12,7 @@ pub fn give_completions(shell: &str) { "powershell" | "pwsh" | "ps" | "p" => return_bash(), "zsh" | "z" => return_bash(), _ => { - error(format!("shell \"{}\" is not supported", shell)); - std::process::exit(1); + error!("shell \"{}\" is not supported", shell); } }; } diff --git a/src/lib.rs b/src/lib.rs index 8b671a2..4bad0fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(format_args_nl)] + pub mod cli; pub mod util; pub mod r#type; @@ -7,25 +9,34 @@ pub mod completions; pub type Res = std::result::Result>; use clap::{App, Arg}; -use colored::*; use common::*; -pub fn info(text: impl Into) { - println!("{}{}", "info: ".white().bold(), text.into()); +#[macro_export] +macro_rules! info { + ($($arg:tt)*) => ({ + use colored::Colorize; + println!("{}{}", "info: ".white().bold(), std::format_args!($($arg)*)); + }) } -pub fn success(text: impl Into) { - println!( - "\n\t{}{}\n", - "success: ".green().bold(), - text.into() - ); +#[macro_export] +macro_rules! success { + ($($arg:tt)*) => ({ + use colored::Colorize; + println!("\n\t{}{}\n", "success: ".green().bold(), std::format_args!($($arg)*)); + }) } -pub fn error(text: impl Into) { - println!("{}{}", "error: ".red().bold(), text.into()); +#[macro_export] +macro_rules! error { + ($($arg:tt)*) => ({ + use colored::Colorize; + println!("{}{}", "error: ".red().bold(), std::format_args!($($arg)*)); + std::process::exit(1); + }) } + pub fn build_cli() -> App<'static> { App::new("dvm") .version("1.1.4") @@ -60,4 +71,5 @@ pub fn build_cli() -> App<'static> { .aliases(COMP_ALIASES) .arg(Arg::new("type").possible_values(POSSIBLE_SHELLS)) ) + } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6111ab8..7cc4733 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ compile_error!("can only be compiled on linux ;)"); use clap::{AppSettings, Clap}; -use dvm::{Res, cli::{install, remove, show, update}, common::*, common::VERSION, completions, error, r#type::Type}; +use dvm::{Res, cli::{install, remove, show, update, run}, common::*, common::VERSION, completions, error, r#type::Type}; #[derive(Clap, Debug)] #[clap(version = VERSION, setting = AppSettings::ColoredHelp)] @@ -26,7 +26,10 @@ enum Command { Show(ShowOption), #[clap(about = COMP_DESC, aliases = COMP_ALIASES)] - Completions(CompletionsOption) + Completions(CompletionsOption), + + #[clap(about = RUN_DESC, aliases = RUN_ALIASES)] + Run(RunOptions) } #[derive(Clap, Debug)] @@ -71,6 +74,18 @@ struct CompletionsOption { shell: String } +#[derive(Clap, Debug)] +struct RunOptions { + #[clap(short, long)] + verbose: bool, + + #[clap(possible_values = POSSIBLE_VALUES)] + r#type: String, + + #[clap(last = true)] + args: Vec +} + fn str_to_type(s: String) -> Type { match s.as_str() { "stable" | "discord-stable" | "s" => Type::STABLE, @@ -78,8 +93,7 @@ fn str_to_type(s: String) -> Type { "ptb" | "discord-ptb" | "p" => Type::PTB, "development" | "dev" | "discord-development" | "d" => Type::DEVELOPMENT, _ => { - error(format!("type \"{}\" does not exist", s)); - std::process::exit(1); + error!("type \"{}\" does not exist", s); } } } @@ -88,29 +102,30 @@ fn str_to_type(s: String) -> Type { async fn main() -> Res<()> { let opts = Opts::parse(); - match opts.command { + Ok(match opts.command { Command::Install(opt) => { for r#type in opt.r#type { - install(str_to_type(r#type), opt.verbose).await?; + install(str_to_type(r#type), opt.verbose).await? } } Command::Update(opt) => { for r#type in opt.r#type { - update(str_to_type(r#type), opt.verbose).await?; + update(str_to_type(r#type), opt.verbose).await? } } Command::Remove(opt) => { for r#type in opt.r#type { - remove(str_to_type(r#type), opt.verbose).await?; + remove(str_to_type(r#type), opt.verbose).await? } } Command::Show(opt) => { - show(opt.verbose, opt.check).await?; + show(opt.verbose, opt.check).await? } Command::Completions(opt) => { - completions::give_completions(&opt.shell); + completions::give_completions(&opt.shell) } - }; - - Ok(()) + Command::Run(opt) => { + run(str_to_type(opt.r#type), opt.args.clone(), opt.verbose).await? + } + }) } diff --git a/src/util.rs b/src/util.rs index d206ebf..90e9465 100644 --- a/src/util.rs +++ b/src/util.rs @@ -42,7 +42,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .json::>() .await?; if verbose { - info("requested api for latest version") + info!("requested api for latest version") } // exit if the api doesn't return a name (latest version) @@ -50,32 +50,31 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us Some(v) => v, None => std::process::exit(1), }; - info(format!("found latest version {}:{}", release_type, latest)); + info!("found latest version {}:{}", release_type, latest); let mut version = String::new(); if update { version = get_version(&user, pascal_pkg); // check if the version is the same & clean file of \n's if verbose { - info("checking if existing version and latest match") + info!("checking if existing version and latest match") } if version.eq(latest) { - error(format!( + error!( "you already have the latest version of {}", release_type - )); - std::process::exit(1); + ); } // remove installed to make room for upgrade fs::remove_dir_all(format!("/home/{}/.dvm/{}", user, pascal_pkg))?; - info("removing old components"); + info!("removing old components"); } // download tarball let tar_name = format!("{}-{}", pkg_name, latest); - info(format!("downloading version {}:{}", release_type, latest)); + info!("downloading version {}:{}", release_type, latest); let tar_bytes = reqwest::get(format!( "https://{}.discordapp.net/apps/linux/{}/{}.tar.gz", @@ -85,14 +84,14 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .bytes() .await?; if verbose { - info("downloaded tarball") + info!("downloaded tarball") } // write tar to /tmp let tmp_file = format!("/tmp/{}.tar.gz", tar_name); fs::write(&tmp_file, tar_bytes)?; if verbose { - info("wrote tar to /tmp") + info!("wrote tar to /tmp") } // extract tar to .dvm @@ -104,10 +103,10 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .spawn()? .wait() .await?; - info(format!( + info!( "extracting components to {}", format!("/home/{}/.dvm/{}", user, pascal_pkg) - )); + ); // change Exec= to dvm path from the desktop file Command::new("sed") @@ -124,7 +123,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .wait() .await?; if verbose { - info("changing bin locations in desktop entries") + info!("changing bin locations in desktop entries") } // write a shell script to .dvm/bin to run discord @@ -137,7 +136,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us ), )?; if verbose { - info("created executable bin") + info!("created executable bin") } // make bin executable @@ -148,7 +147,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .wait() .await?; if verbose { - info("allowed execution for bin") + info!("allowed execution for bin") } // copy desktop file to .local/share/applications @@ -162,7 +161,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .spawn()? .wait() .await?; - info("installing desktop file"); + info!("installing desktop file"); // copy icon to .local/share/icons fs::create_dir_all(format!("/home/{}/.local/share/icons", user))?; @@ -175,7 +174,7 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us .spawn()? .wait() .await?; - info("installing icons"); + info!("installing icons"); // create a file that contains the current version to use for updating fs::write( @@ -183,13 +182,13 @@ pub async fn install_version(update: bool, release_type: Type, verbose: bool, us latest, )?; if verbose { - info("created version file") + info!("created version file") } // remove tmp tar ball fs::remove_file(tmp_file)?; if verbose { - info("remove tmp tar ball") + info!("remove tmp tar ball") } Ok((latest.to_string(), version))