Skip to content

Commit 980f97b

Browse files
Hugo Osvaldo Barrerammstick
authored andcommitted
feat!: Replace hardcoded paths with XDG_DATA_DIRs
1 parent ccb4e86 commit 980f97b

File tree

4 files changed

+58
-44
lines changed

4 files changed

+58
-44
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ dirs = "3"
1616
gettext-rs = { version = "0.7", features = ["gettext-system"]}
1717
memchr = "2"
1818
thiserror = "1"
19+
xdg = "2.4.0"

examples/example.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33

44
use std::fs;
55

6-
use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter};
6+
use freedesktop_desktop_entry::{default_paths, DesktopEntry, Iter, PathSource};
77

88
fn main() {
9-
for (path_src, path) in Iter::new(default_paths()) {
9+
for path in Iter::new(default_paths()) {
10+
let path_src = PathSource::guess_from(&path);
1011
if let Ok(bytes) = fs::read_to_string(&path) {
1112
if let Ok(entry) = DesktopEntry::decode(&path, &bytes) {
1213
println!("{:?}: {}\n---\n{}", path_src, path.display(), entry);

src/iter.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
// Copyright 2021 System76 <[email protected]>
22
// SPDX-License-Identifier: MPL-2.0
33

4-
use crate::PathSource;
54
use std::{fs, path::PathBuf};
65

76
pub struct Iter {
8-
directories_to_walk: Vec<(PathSource, PathBuf)>,
9-
actively_walking: Option<(PathSource, fs::ReadDir)>,
7+
directories_to_walk: Vec<PathBuf>,
8+
actively_walking: Option<fs::ReadDir>,
109
}
1110

1211
impl Iter {
13-
pub fn new(directories_to_walk: Vec<(PathSource, PathBuf)>) -> Self {
12+
pub fn new(directories_to_walk: Vec<PathBuf>) -> Self {
1413
Self {
1514
directories_to_walk,
1615
actively_walking: None,
@@ -19,17 +18,17 @@ impl Iter {
1918
}
2019

2120
impl Iterator for Iter {
22-
type Item = (PathSource, PathBuf);
21+
type Item = PathBuf;
2322

2423
fn next(&mut self) -> Option<Self::Item> {
2524
'outer: loop {
26-
let (path_src, mut iterator) = match self.actively_walking.take() {
25+
let mut iterator = match self.actively_walking.take() {
2726
Some(dir) => dir,
2827
None => {
29-
while let Some((path_src, path)) = self.directories_to_walk.pop() {
28+
while let Some(path) = self.directories_to_walk.pop() {
3029
match fs::read_dir(&path) {
3130
Ok(directory) => {
32-
self.actively_walking = Some((path_src, directory));
31+
self.actively_walking = Some(directory);
3332
continue 'outer;
3433
}
3534

@@ -48,12 +47,12 @@ impl Iterator for Iter {
4847

4948
if let Ok(file_type) = entry.file_type() {
5049
if file_type.is_dir() {
51-
self.directories_to_walk.push((path_src.clone(), path));
50+
self.directories_to_walk.push(path);
5251
} else if (file_type.is_file() || file_type.is_symlink())
5352
&& path.extension().map_or(false, |ext| ext == "desktop")
5453
{
55-
self.actively_walking = Some((path_src.clone(), iterator));
56-
return Some((path_src, path));
54+
self.actively_walking = Some(iterator);
55+
return Some(path);
5756
}
5857
}
5958
}

src/lib.rs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ mod iter;
99
pub use self::iter::Iter;
1010
use std::borrow::Cow;
1111
use std::collections::BTreeMap;
12+
1213
use std::path::{Path, PathBuf};
14+
use xdg::BaseDirectories;
1315

1416
pub type Group<'a> = &'a str;
1517
pub type Groups<'a> = BTreeMap<Group<'a>, KeyMap<'a>>;
@@ -279,42 +281,53 @@ pub enum PathSource {
279281
LocalNix,
280282
Nix,
281283
System,
284+
SystemLocal,
282285
SystemFlatpak,
283286
SystemSnap,
284287
Other(String),
285288
}
286289

287-
pub fn default_paths() -> Vec<(PathSource, PathBuf)> {
288-
let home_dir = dirs::home_dir().unwrap();
289-
290-
vec![
291-
(PathSource::LocalDesktop, home_dir.join("Desktop")),
292-
(
293-
PathSource::LocalFlatpak,
294-
home_dir.join(".local/share/flatpak/exports/share/applications"),
295-
),
296-
(
297-
PathSource::Local,
298-
home_dir.join(".local/share/applications"),
299-
),
300-
(
301-
PathSource::LocalNix,
302-
home_dir.join(".nix-profile/share/applications"),
303-
),
304-
(
305-
PathSource::SystemSnap,
306-
PathBuf::from("/var/lib/snapd/desktop/applications"),
307-
),
308-
(
309-
PathSource::SystemFlatpak,
310-
PathBuf::from("/var/lib/flatpak/exports/share/applications"),
311-
),
312-
(
313-
PathSource::Nix,
314-
PathBuf::from("/nix/var/nix/profiles/default/share/applications"),
315-
),
316-
(PathSource::System, PathBuf::from("/usr/share/applications")),
317-
]
290+
impl PathSource {
291+
292+
/// Attempts to determine the PathSource for a given Path.
293+
/// Note that this is a best-effort guesting function, and its results should be treated as
294+
/// such (e.g.: non-canonical).
295+
pub fn guess_from(path: &Path) -> PathSource {
296+
let base_dirs = BaseDirectories::new().unwrap();
297+
let data_home = base_dirs.get_data_home();
298+
299+
if path.starts_with("/usr/share") {
300+
PathSource::System
301+
} else if path.starts_with("/usr/local/share") {
302+
PathSource::SystemLocal
303+
} else if path.starts_with("/var/lib/flatpak") {
304+
PathSource::SystemFlatpak
305+
} else if path.starts_with("/var/lib/snapd") {
306+
PathSource::SystemSnap
307+
} else if path.starts_with("/nix/var/nix/profiles/default") || path.starts_with("/nix/store") {
308+
PathSource::Nix
309+
} else if path.to_string_lossy().contains("/flatpak/") {
310+
PathSource::LocalFlatpak
311+
} else if path.starts_with(&data_home.as_path()) {
312+
PathSource::Local
313+
} else if path.starts_with("/nix/var/nix/profiles/per-user") || path.to_string_lossy().contains(".nix") {
314+
PathSource::LocalNix
315+
} else {
316+
PathSource::Other(String::from("unknown"))
317+
}
318+
}
319+
}
320+
321+
/// Returns the default paths in which desktop entries should be searched for based on the current
322+
/// environment.
323+
///
324+
/// Panics in case determining the current home directory fails.
325+
pub fn default_paths() -> Vec<PathBuf> {
326+
let base_dirs = BaseDirectories::new().unwrap();
327+
let mut data_dirs = base_dirs.get_data_dirs();
328+
data_dirs.push(base_dirs.get_data_home());
329+
330+
data_dirs.iter().map(|d| d.join("applications")).collect()
318331
}
319332

320333
fn dgettext(domain: &str, message: &str) -> String {

0 commit comments

Comments
 (0)