From 4907787911cfcfe847a64ee8a673b06ddbd69346 Mon Sep 17 00:00:00 2001 From: steven-omaha <35634100+steven-omaha@users.noreply.github.com> Date: Mon, 9 Jan 2023 18:30:12 +0100 Subject: [PATCH] start reimplementing main functions again --- src/backend/macros.rs | 4 ++ src/backend/mod.rs | 36 ++++++++++++--- src/core.rs | 100 ++++++++++++++++++++++++++++-------------- src/group.rs | 4 +- src/package.rs | 2 +- src/ui.rs | 7 +-- 6 files changed, 107 insertions(+), 46 deletions(-) diff --git a/src/backend/macros.rs b/src/backend/macros.rs index d13c183..d5b2012 100644 --- a/src/backend/macros.rs +++ b/src/backend/macros.rs @@ -16,5 +16,9 @@ macro_rules! impl_backend_constants { fn get_switches_remove(&self) -> Switches { SWITCHES_REMOVE } + + fn get_managed_packages(&self) -> &HashSet { + &self.packages + } }; } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 1e1a013..619b5da 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -13,8 +13,8 @@ pub use rust::Rust; pub(in crate::backend) type Switches = &'static [&'static str]; pub(in crate::backend) type Text = &'static str; -#[derive(Debug)] -pub enum Backends { +#[derive(Debug, Hash, PartialEq, Eq)] +pub(crate) enum Backends { Pacman, Rust, } @@ -24,7 +24,7 @@ impl Backends { BackendIter(Some(Self::Pacman)) } - pub fn get(&self) -> Box { + fn get(&self) -> Box { match self { Self::Pacman => Box::new(Pacman { packages: HashSet::new(), @@ -36,7 +36,7 @@ impl Backends { } } -pub struct BackendIter(Option); +pub(crate) struct BackendIter(Option); impl Iterator for BackendIter { type Item = Box; @@ -56,11 +56,12 @@ impl Iterator for BackendIter { } } -pub trait Backend { +pub(crate) trait Backend { fn get_binary(&self) -> Text; fn get_section(&self) -> Text; fn get_switches_install(&self) -> Switches; fn get_switches_remove(&self) -> Switches; + fn get_managed_packages(&self) -> &HashSet; /// Get all packages that are installed in the system. fn get_all_installed_packages(&self) -> HashSet; @@ -69,7 +70,11 @@ pub trait Backend { fn get_explicitly_installed_packages(&self) -> HashSet; /// Install the specified packages. - fn install_packages(&self, packages: Vec) { + fn install_packages(&self, packages: &[Package]) { + if packages.is_empty() { + return; + } + let mut cmd = Command::new(self.get_binary()); cmd.args(self.get_switches_install()); for p in packages { @@ -100,5 +105,24 @@ pub trait Backend { .collect() } + fn get_missing_packages_sorted(&self) -> Vec { + let installed = self.get_all_installed_packages(); + let managed = self.get_managed_packages(); + let mut diff: Vec<_> = managed.difference(&installed).cloned().collect(); + diff.sort_unstable(); + diff + } + fn add_packages(&mut self, packages: HashSet); + + fn get_unmanaged_packages_sorted(&self) -> Vec { + let installed = self.get_explicitly_installed_packages(); + let required = self.get_managed_packages(); + let mut diff: Vec<_> = dbg!(installed) + .difference(dbg!(required)) + .cloned() + .collect(); + diff.sort_unstable(); + diff + } } diff --git a/src/core.rs b/src/core.rs index bf1ed61..3292cdf 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::process::exit; use anyhow::{bail, Context, Result}; @@ -21,33 +21,35 @@ impl Pacdef { Self { args, groups } } - // pub(crate) fn get_packages_to_install(&mut self) -> Vec { - // let managed = self.take_packages_as_set(); - // let local_packages = Pacman::get_all_installed_packages(); - // let mut diff: Vec<_> = managed - // .into_iter() - // .filter(|p| !local_packages.contains(p)) - // .collect(); - // diff.sort_unstable(); - // diff - // } - pub(crate) fn install_packages(&self) { - for b in Backends::iter() { - println!("{}", b.get_binary()); - } - // let diff = self.get_packages_to_install(); - // if diff.is_empty() { - // println!("nothing to do"); - // exit(0); - // } - // println!("Would install the following packages:"); - // for p in &diff { - // println!(" {p}"); - // } - // crate::ui::get_user_confirmation(); + let mut to_install = ToInstallPerBackend::new(); - // Pacman::install_packages(diff); + for b in Backends::iter() { + print!("{}: ", b.get_binary()); + + let diff = b.get_missing_packages_sorted(); + if diff.is_empty() { + println!("nothing to do"); + continue; + } + + println!(" Would install the following packages:"); + for p in &diff { + println!(" {p}"); + } + to_install.push((b, diff)); + println!(); + } + + if to_install.nothing_to_do_for_all_backends() { + return; + } + + if !get_user_confirmation() { + return; + }; + + to_install.install_missing_packages() } #[allow(clippy::unit_arg)] @@ -57,7 +59,7 @@ impl Pacdef { Some((action::EDIT, groups)) => self.edit_group_files(groups).context("editing"), // Some((action::GROUPS, _)) => Ok(self.show_groups()), Some((action::SYNC, _)) => Ok(self.install_packages()), - // Some((action::UNMANAGED, _)) => Ok(self.show_unmanaged_packages()), + Some((action::UNMANAGED, _)) => Ok(self.show_unmanaged_packages()), Some((action::VERSION, _)) => Ok(self.show_version()), _ => todo!(), } @@ -87,11 +89,19 @@ impl Pacdef { println!("pacdef, version: {}", env!("CARGO_PKG_VERSION")) } - // pub(crate) fn show_unmanaged_packages(mut self) { - // for p in &self.get_unmanaged_packages() { - // println!("{p}"); - // } - // } + pub(crate) fn show_unmanaged_packages(self) { + for b in Backends::iter() { + let unmanaged = b.get_unmanaged_packages_sorted(); + if unmanaged.is_empty() { + continue; + } + + println!("{}", b.get_section()); + for p in unmanaged { + println!(" {p}"); + } + } + } // /// Returns a `Vec` of alphabetically sorted unmanaged packages. // pub(crate) fn get_unmanaged_packages(&mut self) -> Vec { @@ -129,3 +139,29 @@ impl Pacdef { // Pacman::remove_packages(unmanaged); // } } + +struct ToInstallPerBackend(Vec<(Box, Vec)>); + +impl ToInstallPerBackend { + fn new() -> Self { + Self(vec![]) + } + + fn push(&mut self, item: (Box, Vec)) { + self.0.push(item); + } + + fn iter(&self) -> impl Iterator, Vec)> { + self.0.iter() + } + + fn nothing_to_do_for_all_backends(&self) -> bool { + self.0.iter().all(|(_, diff)| diff.is_empty()) + } + + fn install_missing_packages(&self) { + self.0 + .iter() + .for_each(|(backend, diff)| backend.install_packages(diff)); + } +} diff --git a/src/group.rs b/src/group.rs index 6e990df..802243e 100644 --- a/src/group.rs +++ b/src/group.rs @@ -22,9 +22,9 @@ impl Group { let path = crate::path::get_pacdef_group_dir().context("getting pacdef group dir")?; for entry in path.read_dir().context("reading group dir")? { let file = entry.context("getting a file")?; - let name = file.file_name(); + let path = file.path(); - let group = Group::try_from(name)?; + let group = Group::try_from(dbg!(path))?; result.insert(group); } diff --git a/src/package.rs b/src/package.rs index bb4618f..b8d1929 100644 --- a/src/package.rs +++ b/src/package.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::fmt::{Display, Write}; use std::hash::Hash; -#[derive(Debug, Eq, PartialOrd, Ord)] +#[derive(Debug, Eq, PartialOrd, Ord, Clone)] pub struct Package { pub name: String, repo: Option, diff --git a/src/ui.rs b/src/ui.rs index 3ea626e..e6a98bd 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,11 +1,8 @@ use std::io::{BufRead, Write}; -use std::process::exit; -pub(crate) fn get_user_confirmation() { +pub(crate) fn get_user_confirmation() -> bool { print!("Continue? [Y/n] "); std::io::stdout().flush().unwrap(); let reply = std::io::stdin().lock().lines().next().unwrap().unwrap(); - if !(reply.is_empty() || reply.to_lowercase().contains('y')) { - exit(0) - } + !(reply.is_empty() || reply.to_lowercase().contains('y')) }