From d1fbeea1df3e8f8d28273e3e98e7892d4080d958 Mon Sep 17 00:00:00 2001 From: Beefki Date: Fri, 13 Oct 2017 11:53:50 -0500 Subject: [PATCH] Initial Commit --- Cargo.toml | 6 +++ src/config.rs | 71 ++++++++++++++++++++++++ src/main.rs | 67 +++++++++++++++++++++++ src/management.rs | 36 +++++++++++++ src/packagemanager.rs | 123 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 303 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/config.rs create mode 100644 src/main.rs create mode 100644 src/management.rs create mode 100644 src/packagemanager.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..89bcf4e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rux" +version = "0.1.0" +authors = ["Beefki "] + +[dependencies] diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..b3b0965 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,71 @@ +use super::*; +/// A struct to hold parsed arg data. +#[derive(Debug)] +pub struct Config { + pub action: Management, + pub term: Option, +} + +impl Config { + /// Actually runs the package manager. Checks what command was requested + /// and loads the appropriate data from the passed `PackageManager`. + /// Finally calls the program and passes the appropriate arguments + pub fn run(&self, pac: PackageManager) -> Child { + let prog = match self.action { + Management::Search => (pac.search.0, pac.search.1.unwrap_or_else(|| "".to_string())), + Management::Install => ( + pac.install.0, + pac.install.1.unwrap_or_else(|| "".to_string()), + ), + Management::Uninstall => ( + pac.uninstall.0, + pac.uninstall.1.unwrap_or_else(|| "".to_string()), + ), + Management::Remove => (pac.purge.0, pac.purge.1.unwrap_or_else(|| "".to_string())), + Management::Update => (pac.update.0, pac.update.1.unwrap_or_else(|| "".to_string())), + Management::Upgrade => ( + pac.upgrade.0, + pac.upgrade.1.unwrap_or_else(|| "".to_string()), + ), + Management::Full => (pac.sup.0, pac.sup.1.unwrap_or_else(|| "".to_string())), + Management::Clear => ( + pac.cache_clear.0, + pac.cache_clear.1.unwrap_or_else(|| "".to_string()), + ), + Management::CompleteClear => ( + pac.complete_cache_clear.0, + pac.complete_cache_clear.1.unwrap_or_else( + || "".to_string(), + ), + ), + }; + + let term = match self.term { + None => "", + Some(ref val) => val, + }; + + Command::new(&prog.0) + .arg(&prog.1) + .arg(term) + .spawn() + .expect("Failed to call package manager") + } + /// Creates a `Config` from passed arguments, parses the `Management` enum + /// and term (if any). Requires an action, while the term can be `None`. + pub fn new() -> Config { + let action = match Management::parse(std::env::args().nth(1)) { + None => { + println!("No command actions passed"); + std::process::exit(0) + } + Some(command) => command, + }; + let term = std::env::args().nth(2); + + Config { + action: action, + term: term, + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b01fc12 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,67 @@ +mod packagemanager; +use packagemanager::*; + +mod management; +use management::Management; + +mod config; +use config::Config; + +use std::process::{Command, Child}; +use std::io; +use std::path::Path; + +fn input() -> Result { + let mut val = String::new(); + io::stdin().read_line(&mut val)?; + Ok(val) +} + +fn main() { + let config = Config::new(); + + if Path::new("default.conf").is_file() { + let pac = read_default(); + let mut child = config.run(pac); + child.wait().expect("Failed to wait on child"); + std::process::exit(0); + } + + let pacmatic = PackageManager::pacmatic(); + let pacman = PackageManager::pacman(); + let aptget = PackageManager::apt(); + let xbps = PackageManager::xbps(); + + + let managers: Vec = vec![pacmatic, pacman, aptget, xbps]; + + let mut found: bool = false; + for prog in managers { + if found { break } + if prog.exe.is_file() { + println!("Found {}, is this the manager you want to use? [Y/n]", prog.name); + if input().unwrap().trim().to_lowercase() == "n" { + continue + }else { + found = true; + println!("Would you like to set {} as default? [y/N]", prog.name); + if input().unwrap().trim().to_lowercase() == "y" { + let check = prog.set_default(); + match check { + Ok(_) => println!("Default set"), + Err(err) => println!("An error occured while setting default:\ + {}", err) + } + } + + //let mut child = call(prog, &config.action, &config.term.clone().unwrap_or_else(|| "".to_string())); + let mut child = config.run(prog); + child.wait().expect("Failed to wait on child"); + } + } + } + if !found { + println!("Sorry, your desired package manager is not supported at this time"); + std::process::exit(0); + } +} diff --git a/src/management.rs b/src/management.rs new file mode 100644 index 0000000..13250ef --- /dev/null +++ b/src/management.rs @@ -0,0 +1,36 @@ +#[allow(dead_code)] +#[derive(Debug)] +/// enum for passing data around the program. Contains each option +/// that rux supports for package management. +pub enum Management { + Search, + Install, + Uninstall, + Remove, + Update, + Upgrade, + Full, + Clear, + CompleteClear, +} + +impl Management { + /// Searches through the given commands to find the proper enum variant + /// Setup here to use the same commands `pacman` does though it's no + /// where near as robust. This is very basic and may be improved later + pub fn parse(man: Option) -> Option { + match &*man.expect("No commands were passed") { + "-Ss" => Some(Management::Search), + "-S" => Some(Management::Install), + "-R" => Some(Management::Uninstall), + "-Rdns" => Some(Management::Remove), + "-Sy" => Some(Management::Upgrade), + "-Su" => Some(Management::Update), + "-Syu" => Some(Management::Full), + "-Sc" => Some(Management::Clear), + "-Scc" => Some(Management::CompleteClear), + _ => None, + + } + } +} diff --git a/src/packagemanager.rs b/src/packagemanager.rs new file mode 100644 index 0000000..29d7b5a --- /dev/null +++ b/src/packagemanager.rs @@ -0,0 +1,123 @@ +use std::path::PathBuf; +use std::io::BufReader; +use std::io::prelude::*; +use std::fs::File; +use super::*; + +/// Creates a `PackageManager` struct to hold in the needed data +/// to run our commands. +// TODO: figure out a better way to store and access the data. +// Maybe a Vec? +// Currently actions that require multiple inputs will not work +// such as `apt-get update && apt-get upgrade` +#[derive(Debug, Clone, Default)] +pub struct PackageManager { + pub name: String, + pub search: (String, Option), + pub install: (String, Option), + pub uninstall: (String, Option), + pub sup: (String, Option), + pub purge: (String, Option), + pub update: (String, Option), + pub upgrade: (String, Option), + pub cache_clear: (String, Option), + pub complete_cache_clear: (String, Option), + pub exe: PathBuf, +} + +/// This holds the various implementations of `PackageManagers` so far. +impl PackageManager { + pub fn pacmatic() -> PackageManager { + PackageManager { + name: "pacmatic".to_string(), + search: ("pacmatic".to_string(), Some("-Ss".to_string())), + install: ("pacmatic".to_string(), Some("-S".to_string())), + uninstall: ("pacmatic".to_string(), Some("-R".to_string())), + sup: ("pacmatic".to_string(), Some("-Syu".to_string())), + purge: ("pacmatic".to_string(), Some("-Rdns".to_string())), + upgrade: ("pacmatic".to_string(), Some("-Su".to_string())), + update: ("pacmatic".to_string(), Some("-Sy".to_string())), + cache_clear: ("pacmatic".to_string(), Some("-Sc".to_string())), + complete_cache_clear: ("pacmatic".to_string(), Some("-Scc".to_string())), + exe: PathBuf::from("/bin/pacmatic"), + } + } + + pub fn pacman() -> PackageManager { + PackageManager { + name: "pacman".to_string(), + search: ("pacman".to_string(), Some("-Ss".to_string())), + install: ("pacman".to_string(), Some("-S".to_string())), + uninstall: ("pacman".to_string(), Some("-R".to_string())), + sup: ("pacman".to_string(), Some("-Syu".to_string())), + purge: ("pacman".to_string(), Some("-Rdns".to_string())), + upgrade: ("pacman".to_string(), Some("-Su".to_string())), + update: ("pacman".to_string(), Some("-Sy".to_string())), + cache_clear: ("pacman".to_string(), Some("-Sc".to_string())), + complete_cache_clear: ("pacman".to_string(), Some("-Scc".to_string())), + exe: PathBuf::from("/bin/pacman"), + } + } + + pub fn apt() -> PackageManager { + PackageManager { + name: "apt".to_string(), + search: ("apt".to_string(), Some("search".to_string())), + install: ("apt".to_string(), Some("install".to_string())), + uninstall: ("apt".to_string(), Some("remove".to_string())), + sup: ("apt".to_string(), Some("update".to_string())), + purge: ("apt".to_string(), Some("purge".to_string())), + upgrade: ("apt".to_string(), Some("upgrade".to_string())), + update: ("apt".to_string(), Some("update".to_string())), + cache_clear: ("apt".to_string(), Some("clean".to_string())), + complete_cache_clear: ("apt-get".to_string(), Some("autoclean".to_string())), + exe: PathBuf::from("/bin/apt"), + } + } + + pub fn xbps() -> PackageManager { + PackageManager { + name: "xbps".to_string(), + search: ("xbps-query".to_string(), Some("-Rs".to_string())), + install: ("xbps-install".to_string(), Some("-S".to_string())), + uninstall: ("xbps-remove".to_string(), None), + sup: ("xbps-install".to_string(), Some("-Su".to_string())), + purge: ("xbps-remove".to_string(), Some("-R".to_string())), + upgrade: ("xbps-install".to_string(), Some("-Su".to_string())), + update: ("xbps-install".to_string(), None), + cache_clear: ("xbps-remove".to_string(), Some("-0".to_string())), + complete_cache_clear: ("xbps-remove".to_string(), Some("-0".to_string())), + exe: PathBuf::from("bin/xbps-install"), + } + } + // allows setting the default.conf + // TODO: put default.conf somewhere it actually belongs rather than in + // the current folder. + pub fn set_default(&self) -> std::io::Result<()> { + let mut file = File::create("default.conf")?; + file.write_all(format!("{}", self.name).as_bytes())?; + Ok(()) + } +} + +/// Reads from default.conf and returns the appropriate `PackageManager` +/// Pulls the first line out of the default.conf and loads that. +/// If it doesn't recognize the file it will tell the user that there's an +/// issue before exiting. +pub fn read_default() -> PackageManager { + let file = File::open("default.conf").unwrap(); + let buffered = BufReader::new(file); + for line in buffered.lines() { + match &*line.unwrap() { + "pacmatic" => return PackageManager::pacmatic(), + "pacman" => return PackageManager::pacman(), + "apt" => return PackageManager::apt(), + "xbps" => return PackageManager::xbps(), + _ => { + println!("Default either not set or has been changed"); + std::process::exit(1) + } + } + } + PackageManager::default() +}