feat: pure subcommand

This commit is contained in:
2026-05-29 23:51:27 +02:00
parent 95a75dcd76
commit 5a614e366e
3 changed files with 66 additions and 9 deletions
+23 -3
View File
@@ -30,7 +30,7 @@ mod world;
use error::*; use error::*;
use crate::{ use crate::{
package_manager::get_system_state, package_manager::{get_system_state, get_unneeded_packages, remove_packages},
world::{World, get_world_location}, world::{World, get_world_location},
}; };
@@ -40,7 +40,7 @@ compile_error!("'yay' and 'paru' are mutually exclusive and cannot be enabled to
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
compile_error!("Only (Arch) linux is supported!"); compile_error!("Only (Arch) linux is supported!");
const PRIVLAGE_ESCELATE_COMMAND: &str = "sudo"; pub const PRIVLAGE_ESCELATE_COMMAND: &str = "sudo";
#[derive(Parser)] #[derive(Parser)]
struct Args { struct Args {
@@ -233,7 +233,27 @@ fn main() -> Result<()> {
print!("{}", s); print!("{}", s);
} }
} }
Commands::Pure { all } => todo!(), Commands::Pure { all } => {
let world = World::load_from(world_path)?;
let state = get_system_state()?;
let aditional = {
let mut x = state.exclude(world.get_packages());
x.ignore = world.get_packages().ignore.clone();
x.official.extend(get_unneeded_packages()?);
x.exclude_ignored();
x.get_package_list()
};
if aditional.is_empty() {
if !args.quiet {
println!("No packages to remove.");
}
return Ok(());
}
remove_packages(&aditional, all)?;
}
} }
Ok(()) Ok(())
} }
+35 -1
View File
@@ -1,4 +1,4 @@
use crate::{error::Result, world::Packages}; use crate::{PRIVLAGE_ESCELATE_COMMAND, error::Result, world::Packages};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
pub fn get_system_state() -> Result<Packages> { pub fn get_system_state() -> Result<Packages> {
@@ -28,3 +28,37 @@ pub fn get_system_state() -> Result<Packages> {
ignore: Vec::new(), ignore: Vec::new(),
}) })
} }
pub fn get_unneeded_packages() -> Result<Vec<String>> {
let command = Command::new("pacman")
.arg("-Qqdt")
.stdout(Stdio::piped())
.output()?;
let packages: Vec<String> = String::from_utf8(command.stdout)?
.split_whitespace()
.map(|x| x.to_owned())
.collect();
Ok(packages)
}
pub fn remove_packages(packages: &[String], all: bool) -> Result<()> {
let mut command = Command::new(PRIVLAGE_ESCELATE_COMMAND);
command.arg("pacman");
if all {
command.arg("-Rns");
} else {
command.arg("-Rs");
}
command
.args(packages)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status()?;
Ok(())
}
+8 -5
View File
@@ -1,7 +1,5 @@
use std::env; use std::env;
use std::error::Error; use std::io::Read;
use std::fs::OpenOptions;
use std::io::{Read, Write};
use std::{fs::File, path::PathBuf}; use std::{fs::File, path::PathBuf};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -36,9 +34,7 @@ impl Packages {
ignore: Vec::new(), ignore: Vec::new(),
} }
} }
}
impl Packages {
pub fn exclude(&self, other: &Self) -> Self { pub fn exclude(&self, other: &Self) -> Self {
let official = self let official = self
.official .official
@@ -64,6 +60,13 @@ impl Packages {
self.official.retain(|x| !self.ignore.contains(x)); self.official.retain(|x| !self.ignore.contains(x));
self.foreign.retain(|x| !self.ignore.contains(x)); self.foreign.retain(|x| !self.ignore.contains(x));
} }
pub fn get_package_list(&self) -> Vec<String> {
let mut packages_list = self.official.clone();
packages_list.extend(self.foreign.clone());
packages_list
}
} }
impl World { impl World {