From 640cd7b258ff48a0df0785a6398dfa064b2166b7 Mon Sep 17 00:00:00 2001 From: Ryan Brue Date: Sat, 27 Apr 2024 13:29:59 -0500 Subject: [PATCH] feat: Separate dirs for different lifetimes --- profile.d/desktop-entry-daemon.sh | 2 +- src/entry_management.rs | 87 +++++++++++++++++++++++-------- src/main.rs | 5 +- src/tools.rs | 47 +++++++++++------ 4 files changed, 100 insertions(+), 41 deletions(-) diff --git a/profile.d/desktop-entry-daemon.sh b/profile.d/desktop-entry-daemon.sh index 8fa3317..2abbd14 100644 --- a/profile.d/desktop-entry-daemon.sh +++ b/profile.d/desktop-entry-daemon.sh @@ -1,3 +1,3 @@ # set XDG_DATA_DIRS to include desktop-entry-daemon installations export XDG_DATA_DIRS -XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.cache/desktop-entry-daemon/:$XDG_RUNTIME_DIR/desktop-entry-daemon/" \ No newline at end of file +XDG_DATA_DIRS="$XDG_DATA_DIRS:$HOME/.cache/desktop-entry-daemon/:$XDG_RUNTIME_DIR/desktop-entry-daemon/session/:$XDG_RUNTIME_DIR/desktop-entry-daemon/proc/" \ No newline at end of file diff --git a/src/entry_management.rs b/src/entry_management.rs index 3b6c25e..9408d21 100644 --- a/src/entry_management.rs +++ b/src/entry_management.rs @@ -87,10 +87,9 @@ impl Lifetime { #[derive(Clone, Debug, PartialEq, Eq)] pub struct EntryManager { pub cache: EntryCache, - pub temp_entry_dir: PathBuf, - pub temp_icon_dir: PathBuf, - pub persistent_entry_dir: PathBuf, - pub persistent_icon_dir: PathBuf, + pub proc_dir: PathBuf, + pub session_dir: PathBuf, + pub persistent_dir: PathBuf, pub config_file: PathBuf, pub change_handlers: HashSet, } @@ -101,6 +100,12 @@ pub struct EntryCache { pub icons: HashMap>, } +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum ResourceType { + DesktopEntry, + Icon, +} + pub enum ConfigError { IO(std::io::Error), Parse(SpannedError), @@ -127,13 +132,17 @@ impl EntryCache { } impl EntryManager { - pub fn new(tmp_dir: PathBuf, persistent_dir: PathBuf, config_file: PathBuf) -> Self { + pub fn new( + proc_dir: PathBuf, + session_dir: PathBuf, + persistent_dir: PathBuf, + config_file: PathBuf, + ) -> Self { let mut manager = Self { cache: EntryCache::new(&config_file).unwrap_or_default(), - temp_entry_dir: tmp_dir.join(Path::new("applications")), - temp_icon_dir: tmp_dir.join(Path::new("icons")), - persistent_entry_dir: persistent_dir.join(Path::new("applications")), - persistent_icon_dir: persistent_dir.join(Path::new("icons")), + proc_dir, + session_dir, + persistent_dir, config_file, change_handlers: HashSet::new(), }; @@ -145,6 +154,28 @@ impl EntryManager { } manager } + pub fn directory_for_lifetime( + &self, + lifetime: Lifetime, + resource_type: ResourceType, + ) -> PathBuf { + match (lifetime, resource_type) { + (Lifetime::Process(_), ResourceType::DesktopEntry) => { + self.proc_dir.join(Path::new("applications")) + } + (Lifetime::Process(_), ResourceType::Icon) => self.proc_dir.join(Path::new("icons")), + (Lifetime::Session(_), ResourceType::DesktopEntry) => { + self.session_dir.join(Path::new("applications")) + } + (Lifetime::Session(_), ResourceType::Icon) => self.session_dir.join(Path::new("icons")), + (Lifetime::Persistent(_), ResourceType::DesktopEntry) => { + self.persistent_dir.join(Path::new("applications")) + } + (Lifetime::Persistent(_), ResourceType::Icon) => { + self.persistent_dir.join(Path::new("icons")) + } + } + } /// responsible for registering a desktop `entry` with a given `lifetime`. saves file as /// `appid`.desktop, and can be referred to with the specified appid pub fn register_entry( @@ -156,7 +187,7 @@ impl EntryManager { // validate entry let entry = validate_desktop_entry(entry, appid)?; let desktop_file_path = self - .temp_entry_dir + .directory_for_lifetime(lifetime.clone(), ResourceType::DesktopEntry) .as_path() .join(format!("{}.desktop", appid)); if desktop_file_path.exists() { @@ -196,10 +227,10 @@ impl EntryManager { .decode() { // image sent as bytes - self.icon_as_bytes(&img, icon_name)? + self.icon_as_bytes(&img, icon_name, lifetime.clone())? } else if let Ok(text_data) = String::from_utf8(icon_data.into()) { // image sent as svg - self.icon_as_svg(text_data, icon_name)? + self.icon_as_svg(text_data, icon_name, lifetime.clone())? } else { return Err(EntryManagerError::IconValidation( IconValidationError::NoTypeFound, @@ -225,6 +256,7 @@ impl EntryManager { &self, img: &DynamicImage, icon_name: &str, + lifetime: Lifetime, ) -> Result { log::info!("{} is a valid image as bytes", icon_name); if img.width() != img.height() { @@ -239,12 +271,14 @@ impl EntryManager { } else { img.to_owned() }; - let icon_path = self.temp_icon_dir.join(Path::new(&format!( - "hicolor/{}x{}/apps/{}.png", - img.width(), - img.height(), - icon_name - ))); + let icon_path = self + .directory_for_lifetime(lifetime, ResourceType::Icon) + .join(Path::new(&format!( + "hicolor/{}x{}/apps/{}.png", + img.width(), + img.height(), + icon_name + ))); let _ = create_dir_all(icon_path.parent().unwrap()); if icon_path.exists() { return Err(EntryManagerError::PathCollision(icon_path)); @@ -253,13 +287,20 @@ impl EntryManager { Ok(icon_path) } - fn icon_as_svg(&self, svg_text: String, icon_name: &str) -> Result { + fn icon_as_svg( + &self, + svg_text: String, + icon_name: &str, + lifetime: Lifetime, + ) -> Result { // check for valid svg svg::read(&svg_text)?; - let icon_path = self.temp_icon_dir.join(Path::new(&format!( - "hicolor/scalable/apps/{}.svg", - icon_name - ))); + let icon_path = self + .directory_for_lifetime(lifetime, ResourceType::Icon) + .join(Path::new(&format!( + "hicolor/scalable/apps/{}.svg", + icon_name + ))); let _ = create_dir_all(icon_path.parent().unwrap()); if icon_path.exists() { return Err(EntryManagerError::PathCollision(icon_path)); diff --git a/src/main.rs b/src/main.rs index 0a57c46..13ebcae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,9 +18,10 @@ mod tools; #[async_std::main] async fn main() -> ZbusResult<()> { env_logger::init(); - let (tmp_dir, persistent_dir, config_file) = get_dirs(); + let (proc_dir, session_dir, persistent_dir, config_file) = get_dirs(); let manager = Arc::new(Mutex::new(EntryManager::new( - tmp_dir, + proc_dir, + session_dir, persistent_dir, config_file, ))); diff --git a/src/tools.rs b/src/tools.rs index 5c34111..63e210a 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -36,22 +36,37 @@ fn app_exists(id: &str) -> bool { false } -pub fn get_dirs() -> (PathBuf, PathBuf, PathBuf) { +pub fn get_dirs() -> (PathBuf, PathBuf, PathBuf, PathBuf) { let home_str = env::var("HOME").unwrap(); - let runtime_dir_str = env::var("RUNTIME_DIRECTORY").unwrap_or(format!( - "/run/user/{}/desktop-entry-daemon/", + let proc_dir_str = env::var("RUNTIME_DIRECTORY").unwrap_or(format!( + "/run/user/{}/desktop-entry-daemon/proc/", env::var("UID").unwrap_or("1000".to_string()) )); - let tmp_dir = Path::new(&runtime_dir_str); - if !tmp_dir.exists() { + let proc_dir = Path::new(&proc_dir_str); + if !proc_dir.exists() { log::warn!( - "tmp_dir {} does not exist! creating directory...", - tmp_dir.to_str().unwrap() + "proc_dir {} does not exist! creating directory...", + proc_dir.to_str().unwrap() ); - fs::create_dir(tmp_dir).unwrap(); + fs::create_dir(proc_dir).unwrap(); } - let _ = fs::create_dir(tmp_dir.join(Path::new("applications"))); - let _ = fs::create_dir(tmp_dir.join(Path::new("icons"))); + let _ = fs::create_dir(proc_dir.join(Path::new("applications"))); + let _ = fs::create_dir(proc_dir.join(Path::new("icons"))); + + let session_dir_str = env::var("RUNTIME_DIRECTORY").unwrap_or(format!( + "/run/user/{}/desktop-entry-daemon/session/", + env::var("UID").unwrap_or("1000".to_string()) + )); + let session_dir = Path::new(&session_dir_str); + if !session_dir.exists() { + log::warn!( + "session_dir {} does not exist! creating directory...", + session_dir.to_str().unwrap() + ); + fs::create_dir(session_dir).unwrap(); + } + let _ = fs::create_dir(session_dir.join(Path::new("applications"))); + let _ = fs::create_dir(session_dir.join(Path::new("icons"))); let persistent_dir_str = format!("{}/.cache/desktop-entry-daemon/", home_str); let persistent_dir = Path::new(&persistent_dir_str); @@ -62,20 +77,22 @@ pub fn get_dirs() -> (PathBuf, PathBuf, PathBuf) { ); fs::create_dir(persistent_dir).unwrap(); } - let _ = fs::create_dir(tmp_dir.join(Path::new("applications"))); - let _ = fs::create_dir(tmp_dir.join(Path::new("icons"))); + let _ = fs::create_dir(proc_dir.join(Path::new("applications"))); + let _ = fs::create_dir(proc_dir.join(Path::new("icons"))); let config_file_str = format!("{}/.config/desktop-entry-daemon/cache.ron", home_str); let config_file = Path::new(&config_file_str); let _ = fs::create_dir(config_file.parent().unwrap()); log::debug!( - "tmp_dir: {:?} | persistent_dir: {:?} | config_file: {:?}", - tmp_dir, + "proc_dir: {:?} | session_dir: {:?} | persistent_dir: {:?} | config_file: {:?}", + proc_dir, + session_dir, persistent_dir, config_file, ); ( - tmp_dir.to_owned(), + proc_dir.to_owned(), + session_dir.to_owned(), persistent_dir.to_owned(), config_file.to_owned(), )