Replace freedesktop_entry_parser with cosmic-mime-apps

This commit is contained in:
Jonatan Pettersson 2025-11-26 12:46:28 +01:00 committed by Jacob Kauffmann
parent 3baaf4b452
commit f0e41d701c

View file

@ -8,7 +8,6 @@ pub use mime_guess::Mime;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
env,
ffi::OsStr, ffi::OsStr,
fs, io, fs, io,
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -280,107 +279,62 @@ impl MimeAppCache {
} }
} }
let desktops: Vec<String> = env::var("XDG_CURRENT_DESKTOP") let mut list = cosmic_mime_apps::List::default();
.unwrap_or_default()
.split(':')
.map(str::to_ascii_lowercase)
.collect();
// Load mimeapps.list files let paths = cosmic_mime_apps::list_paths();
// https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-latest.html list.load_from_paths(&paths);
//TODO: ensure correct lookup order
let mut mimeapps_paths = Vec::new();
let xdg_dirs = xdg::BaseDirectories::new();
mimeapps_paths.extend(xdg_dirs.find_data_files("applications/mimeapps.list")); for (mime, filenames) in list
.added_associations
for desktop in desktops.iter().rev() { .iter()
mimeapps_paths .chain(list.default_apps.iter())
.extend(xdg_dirs.find_data_files(format!("applications/{desktop}-mimeapps.list"))); {
} for filename in filenames {
log::trace!("add {mime}={filename}");
mimeapps_paths.extend(xdg_dirs.find_config_files("mimeapps.list")); let apps = self
.cache
for desktop in desktops.iter().rev() { .entry(mime.clone())
mimeapps_paths.extend(xdg_dirs.find_config_files(format!("{desktop}-mimeapps.list"))); .or_insert_with(|| Vec::with_capacity(1));
} if !apps.iter().any(|x| filename_eq(&x.path, filename)) {
if let Some(app) = all_apps.iter().find(|&x| filename_eq(&x.path, filename)) {
//TODO: handle directory specific behavior apps.push(MimeApp::from(app));
for path in mimeapps_paths { } else {
let entry = match freedesktop_entry_parser::parse_entry(&path) { log::info!(
Ok(ok) => ok, "failed to add association for {mime:?}: application {filename:?} not found"
Err(err) => { );
log::warn!("failed to parse {}: {}", path.display(), err);
continue;
}
};
for attr in entry
.section("Added Associations")
.attrs()
.chain(entry.section("Default Applications").attrs())
{
if let Ok(mime) = attr.name.parse::<Mime>() {
if let Some(filenames) = attr.value {
for filename in filenames.split_terminator(';') {
log::trace!("add {mime}={filename}");
let apps = self
.cache
.entry(mime.clone())
.or_insert_with(|| Vec::with_capacity(1));
if !apps.iter().any(|x| filename_eq(&x.path, filename)) {
if let Some(app) =
all_apps.iter().find(|&x| filename_eq(&x.path, filename))
{
apps.push(MimeApp::from(app));
} else {
log::info!(
"failed to add association for {mime:?}: application {filename:?} not found"
);
}
}
}
} }
} }
} }
}
for attr in entry.section("Removed Associations").attrs() { for (mime, filenames) in list.removed_associations.iter() {
if let Ok(mime) = attr.name.parse::<Mime>() { for filename in filenames {
if let Some(filenames) = attr.value { log::trace!("remove {mime}={filename}");
for filename in filenames.split_terminator(';') { if let Some(apps) = self.cache.get_mut(&mime) {
log::trace!("remove {mime}={filename}"); apps.retain(|x| !filename_eq(&x.path, filename));
if let Some(apps) = self.cache.get_mut(&mime) {
apps.retain(|x| !filename_eq(&x.path, filename));
}
}
}
} }
} }
}
for attr in entry.section("Default Applications").attrs() { for (mime, filenames) in list.default_apps.iter() {
if let Ok(mime) = attr.name.parse::<Mime>() { for filename in filenames {
if let Some(filenames) = attr.value { log::trace!("default {mime}={filename}");
for filename in filenames.split_terminator(';') { if let Some(apps) = self.cache.get_mut(&mime) {
log::trace!("default {mime}={filename}"); let mut found = false;
if let Some(apps) = self.cache.get_mut(&mime) { for app in apps.iter_mut() {
let mut found = false; if filename_eq(&app.path, filename) {
for app in apps.iter_mut() { app.is_default = true;
if filename_eq(&app.path, filename) { found = true;
app.is_default = true; } else {
found = true; app.is_default = false;
} else {
app.is_default = false;
}
}
if found {
break;
}
log::debug!(
"failed to set default for {mime:?}: application {filename:?} not found"
);
}
} }
} }
if found {
break;
}
log::debug!(
"failed to set default for {mime:?}: application {filename:?} not found"
);
} }
} }
} }