Skip to content

Commit

Permalink
fix(remove): improve package removal
Browse files Browse the repository at this point in the history
  • Loading branch information
QaidVoid committed Nov 2, 2024
1 parent a18cba3 commit 3f0307a
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 57 deletions.
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ pub enum Commands {
/// Packages to remove
#[arg(required = true)]
packages: Vec<String>,

/// Remove exact package only
#[arg(required = false, long, short)]
exact: bool,
},

/// Sync with remote metadata
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ pub async fn init() -> Result<()> {
// nothing to do here
// it can be used to force sync without doing any other operation
}
Commands::Remove { packages } => {
registry.remove_packages(&packages).await?;
Commands::Remove { packages, exact } => {
registry.remove_packages(&packages, exact).await?;
}
Commands::Update { packages } => {
registry.update(packages.as_deref()).await?;
Expand Down
10 changes: 1 addition & 9 deletions src/package/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mod appimage;
pub mod image;
mod install;
mod remove;
pub mod remove;
pub mod run;
pub mod update;

Expand All @@ -10,7 +10,6 @@ use std::{path::PathBuf, sync::Arc};
use anyhow::Result;
use indicatif::MultiProgress;
use install::Installer;
use remove::Remover;
use serde::{Deserialize, Serialize};
use tokio::sync::Mutex;

Expand Down Expand Up @@ -73,13 +72,6 @@ impl ResolvedPackage {
.await?;
Ok(())
}

pub async fn remove(&self) -> Result<()> {
let remover = Remover::new(self).await?;
let mut installed_packages = InstalledPackages::new().await?;
remover.execute(&mut installed_packages).await?;
Ok(())
}
}

impl Package {
Expand Down
30 changes: 9 additions & 21 deletions src/package/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,30 @@ use crate::{
constant::BIN_PATH,
},
package::appimage::remove_applinks,
registry::installed::InstalledPackages,
registry::installed::{InstalledPackage, InstalledPackages},
success,
};

use super::ResolvedPackage;

pub struct Remover {
resolved_package: ResolvedPackage,
package: InstalledPackage,
}

impl Remover {
pub async fn new(resolved_package: &ResolvedPackage) -> Result<Self> {
pub async fn new(package: &InstalledPackage) -> Result<Self> {
Ok(Self {
resolved_package: resolved_package.to_owned(),
package: package.clone(),
})
}

pub async fn execute(&self, installed_packages: &mut InstalledPackages) -> Result<()> {
let package = &self.resolved_package.package;
let installed = installed_packages.find_package(&self.resolved_package);
let Some(installed) = installed else {
return Err(anyhow::anyhow!(
"Package {}-{} is not installed.",
package.full_name('/').color(Color::Blue),
package.version.clone().color(Color::Green)
));
};
let package = &self.package;

let install_dir = package.get_install_dir(&installed.checksum);
let install_path = package.get_install_path(&installed.checksum);
let install_dir = package.get_install_dir();
let install_path = package.get_install_path();
self.remove_symlink(&install_path).await?;
remove_applinks(&package.name, &package.bin_name, &install_path).await?;
self.remove_package_path(&install_dir).await?;
installed_packages
.unregister_package(&self.resolved_package)
.await?;
installed_packages.unregister_package(&self.package).await?;

success!(
"Package {} removed successfully.",
Expand All @@ -55,7 +43,7 @@ impl Remover {
}

pub async fn remove_symlink(&self, install_path: &Path) -> Result<()> {
let package = &self.resolved_package.package;
let package = &self.package;
let symlink_path = BIN_PATH.join(&package.bin_name);
if symlink_path.exists() {
let target = fs::read_link(&symlink_path).await?;
Expand Down
36 changes: 20 additions & 16 deletions src/registry/installed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, path::PathBuf};

use anyhow::{Context, Result};
use chrono::{DateTime, Utc};
Expand All @@ -8,10 +8,10 @@ use tokio::fs;
use crate::{
core::{
color::{Color, ColorExt},
constant::{BIN_PATH, INSTALL_TRACK_PATH},
constant::{BIN_PATH, INSTALL_TRACK_PATH, PACKAGES_PATH},
util::{format_bytes, parse_size},
},
package::{parse_package_query, ResolvedPackage},
package::{parse_package_query, remove::Remover, ResolvedPackage},
};

use super::storage::PackageStorage;
Expand Down Expand Up @@ -111,25 +111,21 @@ impl InstalledPackages {
Ok(())
}

pub async fn unregister_package(&mut self, resolved_package: &ResolvedPackage) -> Result<()> {
match self.is_installed(resolved_package) {
true => {
self.packages.retain(|installed| {
installed.full_name('-') != resolved_package.package.full_name('-')
});
}
false => {
return Err(anyhow::anyhow!(
"Package is not registered to install database."
))
}
};
pub async fn unregister_package(&mut self, installed_package: &InstalledPackage) -> Result<()> {
self.packages
.retain(|installed| installed.full_name('-') != installed_package.full_name('-'));

self.save().await?;

Ok(())
}

pub async fn remove(&mut self, installed_package: &InstalledPackage) -> Result<()> {
let remover = Remover::new(installed_package).await?;
remover.execute(self).await?;
Ok(())
}

pub async fn save(&self) -> Result<()> {
let path = INSTALL_TRACK_PATH.join("latest");

Expand Down Expand Up @@ -259,4 +255,12 @@ impl InstalledPackage {
.unwrap_or_default();
format!("{}{}", family_prefix, self.name)
}

pub fn get_install_dir(&self) -> PathBuf {
PACKAGES_PATH.join(format!("{}-{}", &self.checksum[..8], self.full_name('-')))
}

pub fn get_install_path(&self) -> PathBuf {
self.get_install_dir().join(&self.bin_name)
}
}
6 changes: 4 additions & 2 deletions src/registry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ impl PackageRegistry {
.await
}

pub async fn remove_packages(&self, package_names: &[String]) -> Result<()> {
self.storage.remove_packages(package_names).await
pub async fn remove_packages(&self, package_names: &[String], exact: bool) -> Result<()> {
self.storage
.remove_packages(package_names, self.installed_packages.clone(), exact)
.await
}

pub async fn search(&self, package_name: &str, case_sensitive: bool) -> Result<()> {
Expand Down
54 changes: 47 additions & 7 deletions src/registry/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,53 @@ impl PackageStorage {
Ok(())
}

pub async fn remove_packages(&self, package_names: &[String]) -> Result<()> {
let resolved_packages: Vec<ResolvedPackage> = package_names
.iter()
.filter_map(|package_name| self.resolve_package(package_name, false).ok())
.collect();
for package in resolved_packages {
package.remove().await?;
pub async fn remove_packages(
&self,
package_names: &[String],
installed_packages: Arc<Mutex<InstalledPackages>>,
exact: bool,
) -> Result<()> {
let mut mut_guard = installed_packages.lock().await;
let installed_packages = &mut_guard.packages;

let mut packages_to_remove = Vec::new();
for package_name in package_names.iter() {
let query = parse_package_query(package_name);
let mut matching_packages = Vec::new();

for package in installed_packages {
if package.name != query.name {
continue;
}
if let Some(ref ckey) = query.collection {
if package.collection != *ckey {
continue;
}
}

let family_matches = match (&query.family, &package.family) {
(None, None) => true,
(None, Some(_)) => !exact,
(Some(ref query_family), Some(ref package_family)) => {
query_family == package_family
}
_ => false,
};

if family_matches {
matching_packages.push(package.clone());
}
}

if matching_packages.is_empty() {
error!("{} is not installed.", package_name);
} else {
packages_to_remove.extend(matching_packages);
}
}

for package in packages_to_remove {
mut_guard.remove(&package).await?;
}

Ok(())
Expand Down

0 comments on commit 3f0307a

Please sign in to comment.