Add system modification tracking for reversible installs
This commit is contained in:
@@ -2,7 +2,7 @@ use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use super::database::AppImageRecord;
|
||||
use super::database::{AppImageRecord, Database};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum IntegrationError {
|
||||
@@ -46,7 +46,7 @@ pub struct IntegrationResult {
|
||||
pub icon_install_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn applications_dir() -> PathBuf {
|
||||
pub fn applications_dir() -> PathBuf {
|
||||
crate::config::data_dir_fallback()
|
||||
.join("applications")
|
||||
}
|
||||
@@ -220,6 +220,71 @@ fn remove_icon_files(icon_id: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Integrate and track all created files in the system_modifications table.
|
||||
pub fn integrate_tracked(record: &AppImageRecord, db: &Database) -> Result<IntegrationResult, IntegrationError> {
|
||||
let result = integrate(record)?;
|
||||
|
||||
// Register desktop file
|
||||
db.register_modification(
|
||||
record.id,
|
||||
"desktop_file",
|
||||
&result.desktop_file_path.to_string_lossy(),
|
||||
None,
|
||||
).ok();
|
||||
|
||||
// Register icon file
|
||||
if let Some(ref icon_path) = result.icon_install_path {
|
||||
db.register_modification(
|
||||
record.id,
|
||||
"icon",
|
||||
&icon_path.to_string_lossy(),
|
||||
None,
|
||||
).ok();
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Undo all tracked system modifications for an AppImage.
|
||||
pub fn undo_all_modifications(db: &Database, appimage_id: i64) -> Result<(), String> {
|
||||
let mods = db.get_modifications(appimage_id)
|
||||
.map_err(|e| format!("Failed to get modifications: {}", e))?;
|
||||
|
||||
for m in &mods {
|
||||
match m.mod_type.as_str() {
|
||||
"desktop_file" | "autostart" | "icon" => {
|
||||
let path = Path::new(&m.file_path);
|
||||
if path.exists() {
|
||||
if let Err(e) = fs::remove_file(path) {
|
||||
log::warn!("Failed to remove {}: {}", m.file_path, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
"mime_default" => {
|
||||
if let Some(ref prev) = m.previous_value {
|
||||
let _ = Command::new("xdg-mime")
|
||||
.args(["default", prev, &m.file_path])
|
||||
.status();
|
||||
}
|
||||
}
|
||||
"system_desktop" | "system_icon" | "system_binary" => {
|
||||
let _ = Command::new("pkexec")
|
||||
.args(["rm", "-f", &m.file_path])
|
||||
.status();
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Unknown modification type: {}", m.mod_type);
|
||||
}
|
||||
}
|
||||
db.remove_modification(m.id).ok();
|
||||
}
|
||||
|
||||
// Refresh desktop database and icon cache
|
||||
update_desktop_database();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_desktop_database() {
|
||||
let apps_dir = applications_dir();
|
||||
Command::new("update-desktop-database")
|
||||
@@ -301,6 +366,15 @@ mod tests {
|
||||
desktop_actions: None,
|
||||
has_signature: false,
|
||||
screenshot_urls: None,
|
||||
previous_version_path: None,
|
||||
source_url: None,
|
||||
autostart: false,
|
||||
startup_wm_class: None,
|
||||
verification_status: None,
|
||||
first_run_prompted: false,
|
||||
system_wide: false,
|
||||
is_portable: false,
|
||||
mount_point: None,
|
||||
};
|
||||
|
||||
// We can't easily test the full integrate() without mocking dirs,
|
||||
|
||||
Reference in New Issue
Block a user