Skip to content

Commit

Permalink
feat(api): add app-specific directory APIs, closes #5263 (#5272)
Browse files Browse the repository at this point in the history
Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
  • Loading branch information
3 people committed Sep 28, 2022
1 parent eedfa5e commit 5d89905
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 134 deletions.
6 changes: 6 additions & 0 deletions .changes/app-dirs-api.md
@@ -0,0 +1,6 @@
---
"tauri": minor
"api": minor
---

Add new app-specific `BaseDirectory` enum variants `AppConfig`, `AppData`, `AppLocalData`, `AppCache` and `AppLog` along with equivalent functions in `path` module and deprecated ambiguous variants `Log` and `App` along with their equivalent functions in `path` module.
6 changes: 4 additions & 2 deletions core/tauri-utils/src/config.rs
Expand Up @@ -1129,7 +1129,8 @@ macro_rules! check_feature {
/// Each pattern can start with a variable that resolves to a system base directory.
/// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
/// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
/// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`.
/// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,
/// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(untagged)]
Expand Down Expand Up @@ -1465,7 +1466,8 @@ pub struct ShellAllowedCommand {
/// It can start with a variable that resolves to a system base directory.
/// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
/// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
/// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`.
/// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,
/// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.
#[serde(rename = "cmd", default)] // use default just so the schema doesn't flag it as required
pub command: PathBuf,

Expand Down
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

245 changes: 178 additions & 67 deletions core/tauri/src/api/path.rs
Expand Up @@ -13,61 +13,94 @@ use crate::{Config, Env, PackageInfo};

use serde_repr::{Deserialize_repr, Serialize_repr};

/// A base directory to be used in [`resolve_path`].
///
/// The base directory is the optional root of a file system operation.
/// If informed by the API call, all paths will be relative to the path of the given directory.
///
/// For more information, check the [`dirs_next` documentation](https://docs.rs/dirs_next/).
#[derive(Serialize_repr, Deserialize_repr, Clone, Copy, Debug)]
#[repr(u16)]
#[non_exhaustive]
pub enum BaseDirectory {
/// The Audio directory.
Audio = 1,
/// The Cache directory.
Cache,
/// The Config directory.
Config,
/// The Data directory.
Data,
/// The LocalData directory.
LocalData,
/// The Desktop directory.
Desktop,
/// The Document directory.
Document,
/// The Download directory.
Download,
/// The Executable directory.
Executable,
/// The Font directory.
Font,
/// The Home directory.
Home,
/// The Picture directory.
Picture,
/// The Public directory.
Public,
/// The Runtime directory.
Runtime,
/// The Template directory.
Template,
/// The Video directory.
Video,
/// The Resource directory.
Resource,
/// The default App config directory.
/// Resolves to [`BaseDirectory::Config`].
App,
/// The Log directory.
/// Resolves to `BaseDirectory::Home/Library/Logs/{bundle_identifier}` on macOS
/// and `BaseDirectory::Config/{bundle_identifier}/logs` on linux and windows.
Log,
/// A temporary directory.
/// Resolves to [`temp_dir`].
Temp,
// we have to wrap the BaseDirectory enum in a module for #[allow(deprecated)]
// to work, because the procedural macros on the enum prevent it from working directly
// TODO: remove this workaround in v2 along with deprecated variants
#[allow(deprecated)]
mod base_directory {
use super::*;

/// A base directory to be used in [`resolve_path`].
///
/// The base directory is the optional root of a file system operation.
/// If informed by the API call, all paths will be relative to the path of the given directory.
///
/// For more information, check the [`dirs_next` documentation](https://docs.rs/dirs_next/).
#[derive(Serialize_repr, Deserialize_repr, Clone, Copy, Debug)]
#[repr(u16)]
#[non_exhaustive]
pub enum BaseDirectory {
/// The Audio directory.
Audio = 1,
/// The Cache directory.
Cache,
/// The Config directory.
Config,
/// The Data directory.
Data,
/// The LocalData directory.
LocalData,
/// The Desktop directory.
Desktop,
/// The Document directory.
Document,
/// The Download directory.
Download,
/// The Executable directory.
Executable,
/// The Font directory.
Font,
/// The Home directory.
Home,
/// The Picture directory.
Picture,
/// The Public directory.
Public,
/// The Runtime directory.
Runtime,
/// The Template directory.
Template,
/// The Video directory.
Video,
/// The Resource directory.
Resource,
/// The default app config directory.
/// Resolves to [`BaseDirectory::Config`]`/{bundle_identifier}`.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `BaseDirectory::AppConfig` or BaseDirectory::AppData` instead."
)]
App,
/// The default app log directory.
/// Resolves to [`BaseDirectory::Home`]`/Library/Logs/{bundle_identifier}` on macOS
/// and [`BaseDirectory::Config`]`/{bundle_identifier}/logs` on linux and Windows.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `BaseDirectory::AppLog` instead."
)]
Log,
/// A temporary directory.
/// Resolves to [`temp_dir`].
Temp,
/// The default app config directory.
/// Resolves to [`BaseDirectory::Config`]`/{bundle_identifier}`.
AppConfig,
/// The default app data directory.
/// Resolves to [`BaseDirectory::Data`]`/{bundle_identifier}`.
AppData,
/// The default app local data directory.
/// Resolves to [`BaseDirectory::LocalData`]`/{bundle_identifier}`.
AppLocalData,
/// The default app cache directory.
/// Resolves to [`BaseDirectory::Cache`]`/{bundle_identifier}`.
AppCache,
/// The default app log directory.
/// Resolves to [`BaseDirectory::Home`]`/Library/Logs/{bundle_identifier}` on macOS
/// and [`BaseDirectory::Config`]`/{bundle_identifier}/logs` on linux and Windows.
AppLog,
}
}
pub use base_directory::BaseDirectory;

impl BaseDirectory {
/// Gets the variable that represents this [`BaseDirectory`] for string paths.
Expand All @@ -90,9 +123,16 @@ impl BaseDirectory {
Self::Template => "$TEMPLATE",
Self::Video => "$VIDEO",
Self::Resource => "$RESOURCE",
#[allow(deprecated)]
Self::App => "$APP",
#[allow(deprecated)]
Self::Log => "$LOG",
Self::Temp => "$TEMP",
Self::AppConfig => "$APPCONFIG",
Self::AppData => "$APPDATA",
Self::AppLocalData => "$APPLOCALDATA",
Self::AppCache => "$APPCACHE",
Self::AppLog => "$APPLOG",
}
}

Expand All @@ -116,9 +156,16 @@ impl BaseDirectory {
"$TEMPLATE" => Self::Template,
"$VIDEO" => Self::Video,
"$RESOURCE" => Self::Resource,
#[allow(deprecated)]
"$APP" => Self::App,
#[allow(deprecated)]
"$LOG" => Self::Log,
"$TEMP" => Self::Temp,
"$APPCONFIG" => Self::AppConfig,
"$APPDATA" => Self::AppData,
"$APPLOCALDATA" => Self::AppLocalData,
"$APPCACHE" => Self::AppCache,
"$APPLOG" => Self::AppLog,
_ => return None,
};
Some(res)
Expand Down Expand Up @@ -192,7 +239,7 @@ pub fn parse<P: AsRef<Path>>(
/// context.package_info(),
/// &Env::default(),
/// "db/tauri.sqlite",
/// Some(BaseDirectory::App))
/// Some(BaseDirectory::AppData))
/// .expect("failed to resolve path");
/// assert_eq!(path.to_str().unwrap(), "/home/${whoami}/.config/com.tauri.app/db/tauri.sqlite");
///
Expand Down Expand Up @@ -242,9 +289,16 @@ pub fn resolve_path<P: AsRef<Path>>(
BaseDirectory::Template => template_dir(),
BaseDirectory::Video => video_dir(),
BaseDirectory::Resource => resource_dir(package_info, env),
BaseDirectory::App => app_dir(config),
BaseDirectory::Log => log_dir(config),
#[allow(deprecated)]
BaseDirectory::App => app_config_dir(config),
#[allow(deprecated)]
BaseDirectory::Log => app_log_dir(config),
BaseDirectory::Temp => Some(temp_dir()),
BaseDirectory::AppConfig => app_config_dir(config),
BaseDirectory::AppData => app_data_dir(config),
BaseDirectory::AppLocalData => app_local_data_dir(config),
BaseDirectory::AppCache => app_cache_dir(config),
BaseDirectory::AppLog => app_log_dir(config),
};
if let Some(mut base_dir_path_value) = base_dir_path {
// use the same path resolution mechanism as the bundler's resource injection algorithm
Expand Down Expand Up @@ -459,25 +513,52 @@ pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> Option<PathBuf> {
crate::utils::platform::resource_dir(package_info, env).ok()
}

/// Returns the path to the suggested directory for your app config files.
/// Returns the path to the suggested directory for your app's config files.
///
/// Resolves to `${config_dir}/${bundle_identifier}`.
/// Resolves to [`config_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_dir`](crate::PathResolver#method.app_dir) for a more convenient helper function.
pub fn app_dir(config: &Config) -> Option<PathBuf> {
/// See [`PathResolver::app_config_dir`](crate::PathResolver#method.app_config_dir) for a more convenient helper function.
pub fn app_config_dir(config: &Config) -> Option<PathBuf> {
dirs_next::config_dir().map(|dir| dir.join(&config.tauri.bundle.identifier))
}

/// Returns the path to the suggested log directory.
/// Returns the path to the suggested directory for your app's data files.
///
/// Resolves to [`data_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_data_dir`](crate::PathResolver#method.app_data_dir) for a more convenient helper function.
pub fn app_data_dir(config: &Config) -> Option<PathBuf> {
dirs_next::data_dir().map(|dir| dir.join(&config.tauri.bundle.identifier))
}

/// Returns the path to the suggested directory for your app's local data files.
///
/// Resolves to [`local_data_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_data_dir`](crate::PathResolver#method.app_data_dir) for a more convenient helper function.
pub fn app_local_data_dir(config: &Config) -> Option<PathBuf> {
dirs_next::data_local_dir().map(|dir| dir.join(&config.tauri.bundle.identifier))
}

/// Returns the path to the suggested directory for your app's cache files.
///
/// Resolves to [`cache_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_cache_dir`](crate::PathResolver#method.app_cache_dir) for a more convenient helper function.
pub fn app_cache_dir(config: &Config) -> Option<PathBuf> {
dirs_next::cache_dir().map(|dir| dir.join(&config.tauri.bundle.identifier))
}

/// Returns the path to the suggested directory for your app's log files.
///
/// ## Platform-specific
///
/// - **Linux:** Resolves to `${config_dir}/${bundle_identifier}/logs`.
/// - **macOS:** Resolves to `${home_dir}//Library/Logs/{bundle_identifier}`
/// - **Windows:** Resolves to `${config_dir}/${bundle_identifier}/logs`.
/// - **Linux:** Resolves to [`config_dir`]`/${bundle_identifier}/logs`.
/// - **macOS:** Resolves to [`home_dir`]`/Library/Logs/${bundle_identifier}`
/// - **Windows:** Resolves to [`config_dir`]`/${bundle_identifier}/logs`.
///
/// See [`PathResolver::log_dir`](crate::PathResolver#method.log_dir) for a more convenient helper function.
pub fn log_dir(config: &Config) -> Option<PathBuf> {
/// See [`PathResolver::app_log_dir`](crate::PathResolver#method.app_log_dir) for a more convenient helper function.
pub fn app_log_dir(config: &Config) -> Option<PathBuf> {
#[cfg(target_os = "macos")]
let path = dirs_next::home_dir().map(|dir| {
dir
Expand All @@ -491,3 +572,33 @@ pub fn log_dir(config: &Config) -> Option<PathBuf> {

path
}

/// Returns the path to the suggested directory for your app's config files.
///
/// Resolves to [`config_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_config_dir`](crate::PathResolver#method.app_config_dir) for a more convenient helper function.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `app_config_dir` or `app_data_dir` instead."
)]
pub fn app_dir(config: &Config) -> Option<PathBuf> {
app_config_dir(config)
}

/// Returns the path to the suggested directory for your app's log files.
///
/// ## Platform-specific
///
/// - **Linux:** Resolves to [`config_dir`]`/${bundle_identifier}`.
/// - **macOS:** Resolves to [`home_dir`]`/Library/Logs/${bundle_identifier}`
/// - **Windows:** Resolves to [`config_dir`]`/${bundle_identifier}`.
///
/// See [`PathResolver::app_log_dir`](crate::PathResolver#method.app_log_dir) for a more convenient helper function.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `app_log_dir` instead."
)]
pub fn log_dir(config: &Config) -> Option<PathBuf> {
app_log_dir(config)
}
41 changes: 37 additions & 4 deletions core/tauri/src/app.rs
Expand Up @@ -288,14 +288,47 @@ impl PathResolver {
.map(|dir| dir.join(resource_relpath(path.as_ref())))
}

/// Returns the path to the suggested directory for your app config files.
/// Returns the path to the suggested directory for your app's config files.
pub fn app_config_dir(&self) -> Option<PathBuf> {
crate::api::path::app_config_dir(&self.config)
}

/// Returns the path to the suggested directory for your app's data files.
pub fn app_data_dir(&self) -> Option<PathBuf> {
crate::api::path::app_data_dir(&self.config)
}

/// Returns the path to the suggested directory for your app's local data files.
pub fn app_local_data_dir(&self) -> Option<PathBuf> {
crate::api::path::app_local_data_dir(&self.config)
}

/// Returns the path to the suggested directory for your app's cache files.
pub fn app_cache_dir(&self) -> Option<PathBuf> {
crate::api::path::app_cache_dir(&self.config)
}

/// Returns the path to the suggested directory for your app's log files.
pub fn app_log_dir(&self) -> Option<PathBuf> {
crate::api::path::app_log_dir(&self.config)
}

/// Returns the path to the suggested directory for your app's config files.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `app_config_dir` or `app_data_dir` instead."
)]
pub fn app_dir(&self) -> Option<PathBuf> {
crate::api::path::app_dir(&self.config)
self.app_config_dir()
}

/// Returns the path to the suggested log directory.
/// Returns the path to the suggested directory for your app's log files.
#[deprecated(
since = "1.2.0",
note = "Will be removed in 2.0.0. Use `app_log_dir` instead."
)]
pub fn log_dir(&self) -> Option<PathBuf> {
crate::api::path::log_dir(&self.config)
self.app_log_dir()
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/tauri/src/endpoints/file_system.rs
Expand Up @@ -399,7 +399,7 @@ mod tests {
impl Arbitrary for BaseDirectory {
fn arbitrary(g: &mut Gen) -> Self {
if bool::arbitrary(g) {
BaseDirectory::App
BaseDirectory::AppData
} else {
BaseDirectory::Resource
}
Expand Down

0 comments on commit 5d89905

Please sign in to comment.