Add realm prefix to .desktop files imported into citadel
Change the way citadel-desktop-sync works so that gnome-shell can be aware of applications from several realms at once. Each application id is now placed in a separate namespace by adding a prefix to the desktop filename.
This commit is contained in:
parent
e07d35944a
commit
fa3f63b5c7
@ -3,7 +3,7 @@ use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use libcitadel::Result;
|
||||
use libcitadel::{Result, Realm};
|
||||
use std::io;
|
||||
|
||||
|
||||
@ -19,8 +19,13 @@ pub struct DesktopFile {
|
||||
|
||||
impl DesktopFile {
|
||||
|
||||
pub fn write_to_dir<P: AsRef<Path>>(&self, directory: P) -> Result<()> {
|
||||
let path = directory.as_ref().join(&self.filename);
|
||||
pub fn write_to_dir<P: AsRef<Path>>(&self, directory: P, realm: Option<&Realm>) -> Result<()> {
|
||||
let path = if let Some(r) = realm {
|
||||
directory.as_ref().join(format!("realm-{}.{}", r.name(), self.filename))
|
||||
} else {
|
||||
directory.as_ref().join(&self.filename)
|
||||
};
|
||||
|
||||
let f = File::create(&path)
|
||||
.map_err(context!("failed to open desktop file {:?}", path))?;
|
||||
self.write_to(f)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::{OsStr,OsString};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path,PathBuf};
|
||||
use std::time::SystemTime;
|
||||
|
||||
@ -44,6 +44,15 @@ impl DesktopItem {
|
||||
impl DesktopFileSync {
|
||||
pub const CITADEL_APPLICATIONS: &'static str = "/home/citadel/.local/share/applications";
|
||||
|
||||
pub fn sync_active_realms() -> Result<()> {
|
||||
let realms = Realms::load()?;
|
||||
for realm in realms.active(true) {
|
||||
let mut sync = DesktopFileSync::new(realm);
|
||||
sync.run_sync(false)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new_current() -> Option<Self> {
|
||||
Realms::load_current_realm()
|
||||
.filter(|r| r.is_active())
|
||||
@ -51,7 +60,7 @@ impl DesktopFileSync {
|
||||
}
|
||||
|
||||
pub fn new(realm: Realm) -> Self {
|
||||
let icons = match IconSync::new() {
|
||||
let icons = match IconSync::new(&realm) {
|
||||
Ok(icons) => Some(icons),
|
||||
Err(e) => {
|
||||
warn!("Error creating IconSync: {}", e);
|
||||
@ -111,11 +120,14 @@ impl DesktopFileSync {
|
||||
|
||||
fn remove_missing_target_files(&mut self) -> Result<()> {
|
||||
let sources = self.source_filenames();
|
||||
let prefix = format!("realm-{}.", self.realm.name());
|
||||
util::read_directory(Self::CITADEL_APPLICATIONS, |dent| {
|
||||
if !sources.contains(&dent.file_name()) {
|
||||
let path = dent.path();
|
||||
verbose!("Removing desktop entry that no longer exists: {:?}", path);
|
||||
util::remove_file(path)?;
|
||||
if let Some(filename) = dent.file_name().to_str() {
|
||||
if filename.starts_with(&prefix) && !sources.contains(filename) {
|
||||
let path = dent.path();
|
||||
verbose!("Removing desktop entry that no longer exists: {:?}", path);
|
||||
util::remove_file(path)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@ -125,10 +137,15 @@ impl DesktopFileSync {
|
||||
path.metadata().and_then(|meta| meta.modified()).ok()
|
||||
}
|
||||
|
||||
fn source_filenames(&self) -> HashSet<OsString> {
|
||||
fn item_realm_filename(&self, item: &DesktopItem) -> Option<String> {
|
||||
item.path.file_name().map(|s| {
|
||||
format!("realm-{}.{}", self.realm.name(), s.to_string_lossy())
|
||||
})
|
||||
}
|
||||
|
||||
fn source_filenames(&self) -> HashSet<String> {
|
||||
self.items.iter()
|
||||
.flat_map(|item| item.path.file_name())
|
||||
.map(|s| s.to_os_string())
|
||||
.flat_map(|item| self.item_realm_filename(item))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -137,7 +154,7 @@ impl DesktopFileSync {
|
||||
let target = Path::new(Self::CITADEL_APPLICATIONS).join(item.filename());
|
||||
if item.is_newer_than(&target) {
|
||||
if let Err(e) = self.sync_item(item) {
|
||||
warn!("Error synchronzing desktop file {:?} from realm-{}: {}", item.filename(), self.realm.name(), e);
|
||||
warn!("Error synchronizing desktop file {:?} from realm-{}: {}", item.filename(), self.realm.name(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,7 +164,7 @@ impl DesktopFileSync {
|
||||
fn sync_item(&self, item: &DesktopItem) -> Result<()> {
|
||||
let dfp = DesktopFileParser::parse_from_path(&item.path, "/usr/libexec/citadel-run ")?;
|
||||
if dfp.is_showable() {
|
||||
dfp.write_to_dir(Self::CITADEL_APPLICATIONS)?;
|
||||
dfp.write_to_dir(Self::CITADEL_APPLICATIONS, Some(&self.realm))?;
|
||||
if let Some(icon_name)= dfp.icon() {
|
||||
if let Some(ref icons) = self.icons {
|
||||
icons.sync_icon(icon_name)?;
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::sync::icon_cache::IconCache;
|
||||
use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use libcitadel::{Result, Realms, util};
|
||||
use libcitadel::{Result, util, Realm};
|
||||
use std::cell::{RefCell, Cell};
|
||||
|
||||
pub struct IconSync {
|
||||
realm_base: PathBuf,
|
||||
cache: IconCache,
|
||||
known: RefCell<HashSet<String>>,
|
||||
known_changed: Cell<bool>,
|
||||
@ -16,12 +17,13 @@ impl IconSync {
|
||||
const KNOWN_ICONS_FILE: &'static str = "/home/citadel/.local/share/icons/known.cache";
|
||||
const PAPER_ICON_CACHE: &'static str = "/usr/share/icons/Paper/icon-theme.cache";
|
||||
|
||||
pub fn new() -> Result<Self> {
|
||||
pub fn new(realm: &Realm) -> Result<Self> {
|
||||
let realm_base= realm.base_path();
|
||||
let cache = IconCache::open(Self::PAPER_ICON_CACHE)?;
|
||||
let known = Self::read_known_cache()?;
|
||||
let known = RefCell::new(known);
|
||||
let known_changed = Cell::new(false);
|
||||
Ok(IconSync { cache, known, known_changed })
|
||||
Ok(IconSync { realm_base, cache, known, known_changed })
|
||||
}
|
||||
|
||||
pub fn sync_icon(&self, icon_name: &str) -> Result<()> {
|
||||
@ -56,6 +58,7 @@ impl IconSync {
|
||||
let mut names: Vec<String> = self.known.borrow().iter().map(|s| s.to_string()).collect();
|
||||
names.sort_unstable();
|
||||
let out = names.join("\n") + "\n";
|
||||
util::create_dir(Self::CITADEL_ICONS)?;
|
||||
util::write_file(Self::KNOWN_ICONS_FILE, out)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -71,7 +74,7 @@ impl IconSync {
|
||||
}
|
||||
|
||||
fn search(&self, subdir: impl AsRef<Path>, icon_name: &str) -> Result<bool> {
|
||||
let base = Realms::current_realm_symlink().join(subdir.as_ref());
|
||||
let base = self.realm_base.join(subdir.as_ref());
|
||||
if !base.exists() {
|
||||
return Ok(false)
|
||||
}
|
||||
|
@ -8,13 +8,23 @@ mod icon_cache;
|
||||
|
||||
use self::desktop_sync::DesktopFileSync;
|
||||
|
||||
fn has_first_arg(args: &[String], arg: &str) -> bool {
|
||||
args.len() > 1 && args[1].as_str() == arg
|
||||
}
|
||||
|
||||
pub fn main(args: Vec<String>) {
|
||||
|
||||
Logger::set_log_level(LogLevel::Debug);
|
||||
let clear = args.len() > 1 && args[1].as_str() == "--clear";
|
||||
|
||||
if let Err(e) = sync(clear) {
|
||||
println!("Desktop file sync failed: {}", e);
|
||||
if has_first_arg(&args, "--all") {
|
||||
if let Err(e) = DesktopFileSync::sync_active_realms() {
|
||||
println!("Sync all active realms failed: {}", e);
|
||||
}
|
||||
} else {
|
||||
let clear = has_first_arg(&args, "--clear");
|
||||
if let Err(e) = sync(clear) {
|
||||
println!("Desktop file sync failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
30
citadel-tool/src/sync/notes.md
Normal file
30
citadel-tool/src/sync/notes.md
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
### Old Sync
|
||||
|
||||
#### citadel-current-watcher.path
|
||||
|
||||
[Path]
|
||||
PathChanged=/run/citadel/realms/current
|
||||
|
||||
#### citadel-current-watcher.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync --clear
|
||||
ExecStart=/usr/bin/systemctl restart citadel-desktop-watcher.path
|
||||
|
||||
#### citadel-desktop-watcher.path
|
||||
|
||||
[Path]
|
||||
PathChanged=/run/citadel/realms/current/current.realm/rootfs/usr/share/applications
|
||||
PathChanged=/run/citadel/realms/current/current.realm/home/.local/share/applications
|
||||
|
||||
#### citadel-desktop-watcher.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync
|
||||
|
||||
### New Sync
|
||||
|
||||
* Added a new command line option `--all` for syncronizing all active realms
|
@ -4,5 +4,5 @@ StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync --clear
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync --all
|
||||
ExecStart=/usr/bin/systemctl restart citadel-desktop-watcher.path
|
||||
|
@ -4,4 +4,4 @@ StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync
|
||||
ExecStart=/usr/libexec/citadel-desktop-sync --all
|
||||
|
Loading…
Reference in New Issue
Block a user