Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/app-directories-override.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": minor:feat
---

Introduce a new config `appDirectoriesOverride` that changes what `app_*_dir` APIs return, useful for putting all your data besides the executable for testing or as portable apps
7 changes: 7 additions & 0 deletions crates/tauri-cli/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@
"description": "If set to true \"identifier\" will be set as GTK app ID (on systems that use GTK).",
"default": false,
"type": "boolean"
},
"appDirectoriesOverride": {
"description": "Override the path returned from `app_*_dir` APIs,\n this is useful for making portable apps that stores all the data inside a single place\n\n Note: relative paths are resolved based on the app's executable path\n\n ## Example:\n\n To put all the data besides your current executable:\n\n ```json\n {\n \"app\": {\n \"appDirectoriesOverride\": \"./\"\n }\n }\n ```\n\n `app.path().app_local_data_dir()` should now return `${current_exe_dir}/`\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
Expand Down
7 changes: 7 additions & 0 deletions crates/tauri-schema-generator/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@
"description": "If set to true \"identifier\" will be set as GTK app ID (on systems that use GTK).",
"default": false,
"type": "boolean"
},
"appDirectoriesOverride": {
"description": "Override the path returned from `app_*_dir` APIs,\n this is useful for making portable apps that stores all the data inside a single place\n\n Note: relative paths are resolved based on the app's executable path\n\n ## Example:\n\n To put all the data besides your current executable:\n\n ```json\n {\n \"app\": {\n \"appDirectoriesOverride\": \"./\"\n }\n }\n ```\n\n `app.path().app_local_data_dir()` should now return `${current_exe_dir}/`\n\n ## Platform-specific:\n\n - **Android**: Unsupported.",
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
Expand Down
25 changes: 25 additions & 0 deletions crates/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2763,6 +2763,30 @@ pub struct AppConfig {
/// If set to true "identifier" will be set as GTK app ID (on systems that use GTK).
#[serde(rename = "enableGTKAppId", alias = "enable-gtk-app-id", default)]
pub enable_gtk_app_id: bool,
/// Override the path returned from `app_*_dir` APIs,
/// this is useful for making portable apps that stores all the data inside a single place
///
/// Note: relative paths are resolved based on the app's executable path
///
/// ## Example:
///
/// To put all the data besides your current executable:
///
/// ```json
/// {
/// "app": {
/// "appDirectoriesOverride": "./"
/// }
/// }
/// ```
///
/// `app.path().app_local_data_dir()` should now return `${current_exe_dir}/`
///
/// ## Platform-specific:
///
/// - **Android**: Unsupported.
#[serde(alias = "app-directories-override")]
pub app_directories_override: Option<PathBuf>,
}

impl AppConfig {
Expand Down Expand Up @@ -4119,6 +4143,7 @@ mod test {
macos_private_api: false,
with_global_tauri: false,
enable_gtk_app_id: false,
app_directories_override: None,
};

// create a build config
Expand Down
6 changes: 1 addition & 5 deletions crates/tauri/src/manager/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,7 @@ impl<R: Runtime> WebviewManager<R> {
// but we do respect user-specification
#[cfg(any(target_os = "linux", target_os = "windows"))]
if pending.webview_attributes.data_directory.is_none() {
let local_app_data = manager.path().resolve(
&app_manager.config.identifier,
crate::path::BaseDirectory::LocalData,
);
if let Ok(user_data_dir) = local_app_data {
if let Ok(user_data_dir) = manager.path().app_local_data_dir() {
pending.webview_attributes.data_directory = Some(user_data_dir);
}
}
Expand Down
38 changes: 38 additions & 0 deletions crates/tauri/src/path/desktop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ impl<R: Runtime> PathResolver<R> {
///
/// Resolves to [`config_dir`](Self::config_dir)`/${bundle_identifier}`.
pub fn app_config_dir(&self) -> Result<PathBuf> {
if let Some(app_directories_override) = self.app_directories_override() {
return app_directories_override;
}

dirs::config_dir()
.ok_or(Error::UnknownPath)
.map(|dir| dir.join(&self.0.config().identifier))
Expand All @@ -245,6 +249,10 @@ impl<R: Runtime> PathResolver<R> {
///
/// Resolves to [`data_dir`](Self::data_dir)`/${bundle_identifier}`.
pub fn app_data_dir(&self) -> Result<PathBuf> {
if let Some(app_directories_override) = self.app_directories_override() {
return app_directories_override;
}

dirs::data_dir()
.ok_or(Error::UnknownPath)
.map(|dir| dir.join(&self.0.config().identifier))
Expand All @@ -254,6 +262,10 @@ impl<R: Runtime> PathResolver<R> {
///
/// Resolves to [`local_data_dir`](Self::local_data_dir)`/${bundle_identifier}`.
pub fn app_local_data_dir(&self) -> Result<PathBuf> {
if let Some(app_directories_override) = self.app_directories_override() {
return app_directories_override;
}

dirs::data_local_dir()
.ok_or(Error::UnknownPath)
.map(|dir| dir.join(&self.0.config().identifier))
Expand All @@ -263,6 +275,10 @@ impl<R: Runtime> PathResolver<R> {
///
/// Resolves to [`cache_dir`](Self::cache_dir)`/${bundle_identifier}`.
pub fn app_cache_dir(&self) -> Result<PathBuf> {
if let Some(app_directories_override) = self.app_directories_override() {
return Ok(app_directories_override?.join("caches"));
}

dirs::cache_dir()
.ok_or(Error::UnknownPath)
.map(|dir| dir.join(&self.0.config().identifier))
Expand All @@ -276,6 +292,10 @@ impl<R: Runtime> PathResolver<R> {
/// - **macOS:** Resolves to [`home_dir`](Self::home_dir)`/Library/Logs/${bundle_identifier}`
/// - **Windows:** Resolves to [`local_data_dir`](Self::local_data_dir)`/${bundle_identifier}/logs`.
pub fn app_log_dir(&self) -> Result<PathBuf> {
if let Some(app_directories_override) = self.app_directories_override() {
return Ok(app_directories_override?.join("logs"));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very much open to suggestion on those paths, and we could document them once settled

}

#[cfg(target_os = "macos")]
let path = dirs::home_dir()
.ok_or(Error::UnknownPath)
Expand All @@ -293,4 +313,22 @@ impl<R: Runtime> PathResolver<R> {
pub fn temp_dir(&self) -> Result<PathBuf> {
Ok(std::env::temp_dir())
}

/// Resolves the `app_directories_override` based on `current_exe` if it exists
fn app_directories_override(&self) -> Option<Result<PathBuf>> {
self
.0
.config()
.app
.app_directories_override
.as_ref()
.map(|app_directories_override| {
Ok(
tauri_utils::platform::current_exe()?
.parent()
.expect("current executable doesn't have a parent directory")
.join(app_directories_override),
)
})
}
}
Loading