Skip to content

Commit

Permalink
Move implementations to shared dirs-sys crate
Browse files Browse the repository at this point in the history
Co-authored-by: Alejandro Domínguez <[email protected]>
  • Loading branch information
soc and aledomu committed May 13, 2019
1 parent 7a7b2cb commit 25d9992
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 161 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Cargo.lock
/target
**/*.rs.bk
.idea
8 changes: 3 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ repository = "https://github.com/soc/directories-rs"
maintenance = { status = "actively-developed" }
keywords = ["xdg", "basedir", "app_dirs", "path", "folder"]

[target.'cfg(unix)'.dependencies]
libc = "0.2"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["knownfolders", "objbase", "shlobj", "winbase", "winerror"] }
[dependencies]
cfg-if = "0.1"
dirs-sys = ""

[dev-dependencies]
bencher = "0.1.5"
Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- a tiny mid-level library with a minimal API
- that provides the platform-specific, user-accessible locations
- for retrieving and storing configuration, cache and other data
- on Linux, Windows (≥ Vista), macOS and other platforms.
- on Linux, Redox, Windows (≥ Vista), macOS and other platforms.

The library provides the location of these directories by leveraging the mechanisms defined by
- the [XDG base directory](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) and
Expand All @@ -23,7 +23,7 @@ The library provides the location of these directories by leveraging the mechani

## Platforms

This library is written in Rust, and supports Linux, macOS and Windows.
This library is written in Rust, and supports Linux, Redox, macOS and Windows.
Other platforms are also supported; they use the Linux conventions.

_dirs_, the low-level sister library, is available at [dirs-rs](https://github.com/soc/dirs-rs).
Expand Down Expand Up @@ -194,10 +194,19 @@ Please take this table with a grain of salt: a different crate might very well b
- Proj: Supports [project-specific base directories](#projectdirs)
- Conv: Follows naming conventions of the operating system it runs on

## Versioning
## Build

After 1.0, the version number of this library consists of a whole number, which is incremented with each release.
(Think semantic versioning without _minor_ and _patch_ versions.)
It's possible to cross-compile this library if the necessary toolchains are installed with rustup.
This is helpful to ensure a change has not broken compilation on a different platform.

The following commands will build this library on Linux, macOS and Windows:

```
cargo build --target=x86_64-unknown-linux-gnu
cargo build --target=x86_64-pc-windows-gnu
cargo build --target=x86_64-apple-darwin
cargo build --target=x86_64-unknown-redox
```

## License

Expand Down
28 changes: 19 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! - a tiny library with a minimal API (3 structs, 4 factory functions, getters)
//! - that provides the platform-specific, user-accessible locations
//! - for finding and storing configuration, cache and other data
//! - on Linux, Windows (≥ Vista) and macOS.
//! - on Linux, Redox, Windows (≥ Vista) and macOS.
//!
//! The library provides the location of these directories by leveraging the mechanisms defined by
//!
Expand All @@ -14,17 +14,27 @@
#![deny(missing_docs)]

#[macro_use]
extern crate cfg_if;

use std::path::Path;
use std::path::PathBuf;

#[cfg(target_os = "windows")] mod win;
#[cfg(target_os = "macos")] mod mac;
#[cfg(not(any(target_os = "windows", target_os = "macos")))] mod lin;
#[cfg(unix)] mod unix;

#[cfg(target_os = "windows")] use win as sys;
#[cfg(target_os = "macos")] use mac as sys;
#[cfg(not(any(target_os = "windows", target_os = "macos")))] use lin as sys;
cfg_if! {
if #[cfg(target_os = "windows")] {
mod win;
use win as sys;
} else if #[cfg(target_os = "macos")] {
mod mac;
use mac as sys;
} else if #[cfg(target_os = "wasi")] {
mod wasi;
use wasi as sys;
} else {
mod lin;
use lin as sys;
}
}

/// `BaseDirs` provides paths of user-invisible standard directories, following the conventions of the operating system the library is running on.
///
Expand Down
70 changes: 23 additions & 47 deletions src/lin.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
extern crate dirs_sys;

use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::Command;

use BaseDirs;
use UserDirs;
use ProjectDirs;

use unix;

pub fn base_dirs() -> Option<BaseDirs> {
if let Some(home_dir) = unix::home_dir() {
let cache_dir = env::var_os("XDG_CACHE_HOME") .and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".cache"));
let config_dir = env::var_os("XDG_CONFIG_HOME").and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".config"));
let data_dir = env::var_os("XDG_DATA_HOME") .and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
if let Some(home_dir) = dirs_sys::home_dir() {
let cache_dir = env::var_os("XDG_CACHE_HOME") .and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".cache"));
let config_dir = env::var_os("XDG_CONFIG_HOME").and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".config"));
let data_dir = env::var_os("XDG_DATA_HOME") .and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
let data_local_dir = data_dir.clone();
let runtime_dir = env::var_os("XDG_RUNTIME_DIR").and_then(is_absolute_path);
let runtime_dir = env::var_os("XDG_RUNTIME_DIR").and_then(dirs_sys::is_absolute_path);
let executable_dir =
env::var_os("XDG_BIN_HOME").and_then(is_absolute_path).unwrap_or_else(|| {
env::var_os("XDG_BIN_HOME").and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| {
let mut new_dir = data_dir.clone(); new_dir.pop(); new_dir.push("bin"); new_dir });

let base_dirs = BaseDirs {
Expand All @@ -36,21 +34,21 @@ pub fn base_dirs() -> Option<BaseDirs> {
}

pub fn user_dirs() -> Option<UserDirs> {
if let Some(home_dir) = unix::home_dir() {
let data_dir = env::var_os("XDG_DATA_HOME").and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
if let Some(home_dir) = dirs_sys::home_dir() {
let data_dir = env::var_os("XDG_DATA_HOME").and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share"));
let font_dir = data_dir.join("fonts");

let user_dirs = UserDirs {
home_dir: home_dir,
audio_dir: run_xdg_user_dir_command("MUSIC"),
desktop_dir: run_xdg_user_dir_command("DESKTOP"),
document_dir: run_xdg_user_dir_command("DOCUMENTS"),
download_dir: run_xdg_user_dir_command("DOWNLOAD"),
audio_dir: dirs_sys::user_dir("MUSIC"),
desktop_dir: dirs_sys::user_dir("DESKTOP"),
document_dir: dirs_sys::user_dir("DOCUMENTS"),
download_dir: dirs_sys::user_dir("DOWNLOAD"),
font_dir: Some(font_dir),
picture_dir: run_xdg_user_dir_command("PICTURES"),
public_dir: run_xdg_user_dir_command("PUBLICSHARE"),
template_dir: run_xdg_user_dir_command("TEMPLATES"),
video_dir: run_xdg_user_dir_command("VIDEOS")
picture_dir: dirs_sys::user_dir("PICTURES"),
public_dir: dirs_sys::user_dir("PUBLICSHARE"),
template_dir: dirs_sys::user_dir("TEMPLATES"),
video_dir: dirs_sys::user_dir("VIDEOS")
};
Some(user_dirs)
} else {
Expand All @@ -59,12 +57,12 @@ pub fn user_dirs() -> Option<UserDirs> {
}

pub fn project_dirs_from_path(project_path: PathBuf) -> Option<ProjectDirs> {
if let Some(home_dir) = unix::home_dir() {
let cache_dir = env::var_os("XDG_CACHE_HOME") .and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".cache")).join(&project_path);
let config_dir = env::var_os("XDG_CONFIG_HOME").and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".config")).join(&project_path);
let data_dir = env::var_os("XDG_DATA_HOME") .and_then(is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share")).join(&project_path);
if let Some(home_dir) = dirs_sys::home_dir() {
let cache_dir = env::var_os("XDG_CACHE_HOME") .and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".cache")).join(&project_path);
let config_dir = env::var_os("XDG_CONFIG_HOME").and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".config")).join(&project_path);
let data_dir = env::var_os("XDG_DATA_HOME") .and_then(dirs_sys::is_absolute_path).unwrap_or_else(|| home_dir.join(".local/share")).join(&project_path);
let data_local_dir = data_dir.clone();
let runtime_dir = env::var_os("XDG_RUNTIME_DIR").and_then(is_absolute_path).map(|o| o.join(&project_path));
let runtime_dir = env::var_os("XDG_RUNTIME_DIR").and_then(dirs_sys::is_absolute_path).map(|o| o.join(&project_path));

let project_dirs = ProjectDirs {
project_path: project_path,
Expand All @@ -84,28 +82,6 @@ pub fn project_dirs_from(_qualifier: &str, _organization: &str, application: &st
ProjectDirs::from_path(PathBuf::from(&trim_and_lowercase_then_replace_spaces(application, "")))
}

// we don't need to explicitly handle empty strings in the code above,
// because an empty string is not considered to be a absolute path here.
fn is_absolute_path(path: OsString) -> Option<PathBuf> {
let path = PathBuf::from(path);
if path.is_absolute() {
Some(path)
} else {
None
}
}

fn run_xdg_user_dir_command(arg: &str) -> Option<PathBuf> {
use std::os::unix::ffi::OsStringExt;
let mut out = match Command::new("xdg-user-dir").arg(arg).output() {
Ok(output) => output.stdout,
Err(_) => return None,
};
let out_len = out.len();
out.truncate(out_len - 1);
Some(PathBuf::from(OsString::from_vec(out)))
}

fn trim_and_lowercase_then_replace_spaces(name: &str, replacement: &str) -> String {
let mut buf = String::with_capacity(name.len());
let mut parts = name.split_whitespace();
Expand Down
10 changes: 5 additions & 5 deletions src/mac.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
extern crate dirs_sys;

use std::path::PathBuf;

use BaseDirs;
use UserDirs;
use ProjectDirs;

use unix;

pub fn base_dirs() -> Option<BaseDirs> {
if let Some(home_dir) = unix::home_dir() {
if let Some(home_dir) = dirs_sys::home_dir() {
let cache_dir = home_dir.join("Library/Caches");
let config_dir = home_dir.join("Library/Preferences");
let data_dir = home_dir.join("Library/Application Support");
Expand All @@ -29,7 +29,7 @@ pub fn base_dirs() -> Option<BaseDirs> {
}

pub fn user_dirs() -> Option<UserDirs> {
if let Some(home_dir) = unix::home_dir() {
if let Some(home_dir) = dirs_sys::home_dir() {
let audio_dir = home_dir.join("Music");
let desktop_dir = home_dir.join("Desktop");
let document_dir = home_dir.join("Documents");
Expand Down Expand Up @@ -58,7 +58,7 @@ pub fn user_dirs() -> Option<UserDirs> {
}

pub fn project_dirs_from_path(project_path: PathBuf) -> Option<ProjectDirs> {
if let Some(home_dir) = unix::home_dir() {
if let Some(home_dir) = dirs_sys::home_dir() {
let cache_dir = home_dir.join("Library/Caches").join(&project_path);
let config_dir = home_dir.join("Library/Preferences").join(&project_path);
let data_dir = home_dir.join("Library/Application Support").join(&project_path);
Expand Down
49 changes: 0 additions & 49 deletions src/unix.rs

This file was deleted.

12 changes: 12 additions & 0 deletions src/wasi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Stub definitions to make things *compile*.

use std::path::PathBuf;

use BaseDirs;
use UserDirs;
use ProjectDirs;

pub fn base_dirs() -> Option<BaseDirs> { None }
pub fn user_dirs() -> Option<UserDirs> { None }
pub fn project_dirs_from_path(project_path: PathBuf) -> Option<ProjectDirs> { None }
pub fn project_dirs_from(qualifier: &str, organization: &str, application: &str) -> Option<ProjectDirs> { None }
Loading

0 comments on commit 25d9992

Please sign in to comment.