Эх сурвалжийг харах

refactor(core): use bundle identifier on app dir, closes #1693 (#1703)

* refactor(core): use bundle identifier on app dir, closes #1693

* fix: tests

* clippy
Lucas Fernandes Nogueira 4 жил өмнө
parent
commit
428d50add4

+ 6 - 0
.changes/app-dir-refactor.md

@@ -0,0 +1,6 @@
+---
+"tauri": patch
+---
+
+**Breaking:** `api::path::resolve_path()` and `api::path::app_dir()` now takes the config as first argument.
+**Breaking:** `api::path::app_dir()` now resolves to `${configDir}/${config.tauri.bundle.identifier}`.

+ 1 - 1
core/tauri-utils/src/config.rs

@@ -397,7 +397,7 @@ pub struct PackageConfig {
 }
 
 /// The tauri.conf.json mapper.
-#[derive(Debug, PartialEq, Deserialize)]
+#[derive(Debug, Default, PartialEq, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct Config {
   /// Package settings.

+ 9 - 22
core/tauri/src/api/path.rs

@@ -7,6 +7,8 @@ use std::{
   path::{Path, PathBuf},
 };
 
+use crate::Config;
+
 use serde_repr::{Deserialize_repr, Serialize_repr};
 
 /// A Base Directory to use.
@@ -52,7 +54,7 @@ pub enum BaseDirectory {
   /// The Resource directory.
   Resource,
   /// The default App config directory.
-  /// Resolves to ${CONFIG_DIR}/${APP_NAME}
+  /// Resolves to ${BaseDirectory::Config}/${config.tauri.bundle.identifier}
   App,
   /// The current working directory.
   Current,
@@ -63,11 +65,13 @@ pub enum BaseDirectory {
 /// # Example
 /// ```
 /// use tauri::api::path::{resolve_path, BaseDirectory};
-/// let path = resolve_path("path/to/something", Some(BaseDirectory::Config))
+/// // we use the default config, but in an actual app you should get the Config created from tauri.conf.json
+/// let path = resolve_path(&Default::default(), "path/to/something", Some(BaseDirectory::Config))
 ///   .expect("failed to resolve path");
 /// // path is equal to "/home/${whoami}/.config/path/to/something" on Linux
 /// ```
 pub fn resolve_path<P: AsRef<Path>>(
+  config: &Config,
   path: P,
   dir: Option<BaseDirectory>,
 ) -> crate::api::Result<PathBuf> {
@@ -90,7 +94,7 @@ pub fn resolve_path<P: AsRef<Path>>(
       BaseDirectory::Template => template_dir(),
       BaseDirectory::Video => video_dir(),
       BaseDirectory::Resource => resource_dir(),
-      BaseDirectory::App => app_dir(),
+      BaseDirectory::App => app_dir(config),
       BaseDirectory::Current => Some(env::current_dir()?),
     };
     if let Some(mut base_dir_path_value) = base_dir_path {
@@ -193,24 +197,7 @@ pub fn resource_dir() -> Option<PathBuf> {
   crate::api::platform::resource_dir().ok()
 }
 
-fn app_name() -> crate::api::Result<String> {
-  let exe = std::env::current_exe()?;
-  let app_name = exe
-    .file_stem()
-    .expect("failed to get exe filename")
-    .to_string_lossy();
-
-  Ok(app_name.to_string())
-}
-
 /// Returns the path to the suggested directory for your app config files.
-pub fn app_dir() -> Option<PathBuf> {
-  dirs_next::config_dir().and_then(|mut dir| {
-    if let Ok(app_name) = app_name() {
-      dir.push(app_name);
-      Some(dir)
-    } else {
-      None
-    }
-  })
+pub fn app_dir(config: &Config) -> Option<PathBuf> {
+  dirs_next::config_dir().map(|dir| dir.join(&config.tauri.bundle.identifier))
 }

+ 17 - 13
core/tauri/src/endpoints.rs

@@ -9,6 +9,9 @@ use crate::{
 };
 use serde::{Deserialize, Serialize};
 use serde_json::Value as JsonValue;
+
+use std::sync::Arc;
+
 mod app;
 mod cli;
 mod dialog;
@@ -58,7 +61,7 @@ impl Module {
     self,
     window: Window<M>,
     resolver: InvokeResolver<M>,
-    config: &Config,
+    config: Arc<Config>,
     package_info: PackageInfo,
   ) {
     match self {
@@ -70,8 +73,12 @@ impl Module {
       }),
       Self::Process(cmd) => resolver
         .respond_async(async move { cmd.run().and_then(|r| r.json).map_err(InvokeError::from) }),
-      Self::Fs(cmd) => resolver
-        .respond_async(async move { cmd.run().and_then(|r| r.json).map_err(InvokeError::from) }),
+      Self::Fs(cmd) => resolver.respond_async(async move {
+        cmd
+          .run(config)
+          .and_then(|r| r.json)
+          .map_err(InvokeError::from)
+      }),
       Self::Window(cmd) => resolver.respond_async(async move {
         cmd
           .run(window)
@@ -113,15 +120,12 @@ impl Module {
           })
         }
       }
-      Self::Notification(cmd) => {
-        let identifier = config.tauri.bundle.identifier.clone();
-        resolver.respond_async(async move {
-          cmd
-            .run(identifier)
-            .and_then(|r| r.json)
-            .map_err(InvokeError::from)
-        })
-      }
+      Self::Notification(cmd) => resolver.respond_closure(move || {
+        cmd
+          .run(config)
+          .and_then(|r| r.json)
+          .map_err(InvokeError::from)
+      }),
       Self::Http(cmd) => resolver.respond_async(async move {
         cmd
           .run()
@@ -142,7 +146,7 @@ impl Module {
 pub(crate) fn handle<P: Params>(
   module: String,
   invoke: Invoke<P>,
-  config: &Config,
+  config: Arc<Config>,
   package_info: &PackageInfo,
 ) {
   let Invoke { message, resolver } = invoke;

+ 62 - 31
core/tauri/src/endpoints/file_system.rs

@@ -3,12 +3,17 @@
 // SPDX-License-Identifier: MIT
 
 use super::InvokeResponse;
-use crate::api::path::BaseDirectory;
+use crate::{
+  api::{
+    dir, file,
+    path::{resolve_path, BaseDirectory},
+  },
+  Config,
+};
 
-use crate::api::{dir, file, path::resolve_path};
 use serde::{Deserialize, Serialize};
 
-use std::{fs, fs::File, io::Write, path::PathBuf};
+use std::{fs, fs::File, io::Write, path::PathBuf, sync::Arc};
 
 /// The options for the directory functions on the file system API.
 #[derive(Deserialize)]
@@ -96,17 +101,22 @@ pub enum Cmd {
 }
 
 impl Cmd {
-  pub fn run(self) -> crate::Result<InvokeResponse> {
+  #[allow(unused_variables)]
+  pub fn run(self, config: Arc<Config>) -> crate::Result<InvokeResponse> {
     match self {
       #[cfg(fs_read_text_file)]
-      Self::ReadTextFile { path, options } => read_text_file(path, options).map(Into::into),
+      Self::ReadTextFile { path, options } => {
+        read_text_file(&config, path, options).map(Into::into)
+      }
       #[cfg(not(fs_read_text_file))]
       Self::ReadTextFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > readTextFile".to_string(),
       )),
 
       #[cfg(fs_read_binary_file)]
-      Self::ReadBinaryFile { path, options } => read_binary_file(path, options).map(Into::into),
+      Self::ReadBinaryFile { path, options } => {
+        read_binary_file(&config, path, options).map(Into::into)
+      }
       #[cfg(not(fs_read_binary_file))]
       Self::ReadBinaryFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "readBinaryFile".to_string(),
@@ -117,7 +127,7 @@ impl Cmd {
         path,
         contents,
         options,
-      } => write_file(path, contents, options).map(Into::into),
+      } => write_file(&config, path, contents, options).map(Into::into),
       #[cfg(not(fs_write_file))]
       Self::WriteFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > writeFile".to_string(),
@@ -128,14 +138,14 @@ impl Cmd {
         path,
         contents,
         options,
-      } => write_binary_file(path, contents, options).map(Into::into),
+      } => write_binary_file(&config, path, contents, options).map(Into::into),
       #[cfg(not(fs_write_binary_file))]
       Self::WriteBinaryFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "writeBinaryFile".to_string(),
       )),
 
       #[cfg(fs_read_dir)]
-      Self::ReadDir { path, options } => read_dir(path, options).map(Into::into),
+      Self::ReadDir { path, options } => read_dir(&config, path, options).map(Into::into),
       #[cfg(not(fs_read_dir))]
       Self::ReadDir { .. } => Err(crate::Error::ApiNotAllowlisted("fs > readDir".to_string())),
 
@@ -144,26 +154,26 @@ impl Cmd {
         source,
         destination,
         options,
-      } => copy_file(source, destination, options).map(Into::into),
+      } => copy_file(&config, source, destination, options).map(Into::into),
       #[cfg(not(fs_copy_file))]
       Self::CopyFile { .. } => Err(crate::Error::ApiNotAllowlisted("fs > copyFile".to_string())),
 
       #[cfg(fs_create_dir)]
-      Self::CreateDir { path, options } => create_dir(path, options).map(Into::into),
+      Self::CreateDir { path, options } => create_dir(&config, path, options).map(Into::into),
       #[cfg(not(fs_create_dir))]
       Self::CreateDir { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > createDir".to_string(),
       )),
 
       #[cfg(fs_remove_dir)]
-      Self::RemoveDir { path, options } => remove_dir(path, options).map(Into::into),
+      Self::RemoveDir { path, options } => remove_dir(&config, path, options).map(Into::into),
       #[cfg(not(fs_remove_dir))]
       Self::RemoveDir { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > removeDir".to_string(),
       )),
 
       #[cfg(fs_remove_file)]
-      Self::RemoveFile { path, options } => remove_file(path, options).map(Into::into),
+      Self::RemoveFile { path, options } => remove_file(&config, path, options).map(Into::into),
       #[cfg(not(fs_remove_file))]
       Self::RemoveFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > removeFile".to_string(),
@@ -174,7 +184,7 @@ impl Cmd {
         old_path,
         new_path,
         options,
-      } => rename_file(old_path, new_path, options).map(Into::into),
+      } => rename_file(&config, old_path, new_path, options).map(Into::into),
       #[cfg(not(fs_rename_file))]
       Self::RenameFile { .. } => Err(crate::Error::ApiNotAllowlisted(
         "fs > renameFile".to_string(),
@@ -182,7 +192,7 @@ impl Cmd {
 
       #[cfg(fs_path)]
       Self::ResolvePath { path, directory } => {
-        resolve_path_handler(path, directory).map(Into::into)
+        resolve_path_handler(&config, path, directory).map(Into::into)
       }
       #[cfg(not(fs_path))]
       Self::ResolvePath { .. } => Err(crate::Error::ApiNotAllowlisted("fs > pathApi".to_string())),
@@ -193,6 +203,7 @@ impl Cmd {
 /// Reads a directory.
 #[cfg(fs_read_dir)]
 pub fn read_dir(
+  config: &Config,
   path: PathBuf,
   options: Option<DirOperationOptions>,
 ) -> crate::Result<Vec<dir::DiskEntry>> {
@@ -201,20 +212,22 @@ pub fn read_dir(
   } else {
     (false, None)
   };
-  dir::read_dir(resolve_path(path, dir)?, recursive).map_err(crate::Error::FailedToExecuteApi)
+  dir::read_dir(resolve_path(config, path, dir)?, recursive)
+    .map_err(crate::Error::FailedToExecuteApi)
 }
 
 /// Copies a file.
 #[cfg(fs_copy_file)]
 pub fn copy_file(
+  config: &Config,
   source: PathBuf,
   destination: PathBuf,
   options: Option<FileOperationOptions>,
 ) -> crate::Result<()> {
   let (src, dest) = match options.and_then(|o| o.dir) {
     Some(dir) => (
-      resolve_path(source, Some(dir.clone()))?,
-      resolve_path(destination, Some(dir))?,
+      resolve_path(config, source, Some(dir.clone()))?,
+      resolve_path(config, destination, Some(dir))?,
     ),
     None => (source, destination),
   };
@@ -224,13 +237,17 @@ pub fn copy_file(
 
 /// Creates a directory.
 #[cfg(fs_create_dir)]
-pub fn create_dir(path: PathBuf, options: Option<DirOperationOptions>) -> crate::Result<()> {
+pub fn create_dir(
+  config: &Config,
+  path: PathBuf,
+  options: Option<DirOperationOptions>,
+) -> crate::Result<()> {
   let (recursive, dir) = if let Some(options_value) = options {
     (options_value.recursive, options_value.dir)
   } else {
     (false, None)
   };
-  let resolved_path = resolve_path(path, dir)?;
+  let resolved_path = resolve_path(config, path, dir)?;
   if recursive {
     fs::create_dir_all(resolved_path)?;
   } else {
@@ -242,13 +259,17 @@ pub fn create_dir(path: PathBuf, options: Option<DirOperationOptions>) -> crate:
 
 /// Removes a directory.
 #[cfg(fs_remove_dir)]
-pub fn remove_dir(path: PathBuf, options: Option<DirOperationOptions>) -> crate::Result<()> {
+pub fn remove_dir(
+  config: &Config,
+  path: PathBuf,
+  options: Option<DirOperationOptions>,
+) -> crate::Result<()> {
   let (recursive, dir) = if let Some(options_value) = options {
     (options_value.recursive, options_value.dir)
   } else {
     (false, None)
   };
-  let resolved_path = resolve_path(path, dir)?;
+  let resolved_path = resolve_path(config, path, dir)?;
   if recursive {
     fs::remove_dir_all(resolved_path)?;
   } else {
@@ -260,8 +281,12 @@ pub fn remove_dir(path: PathBuf, options: Option<DirOperationOptions>) -> crate:
 
 /// Removes a file
 #[cfg(fs_remove_file)]
-pub fn remove_file(path: PathBuf, options: Option<FileOperationOptions>) -> crate::Result<()> {
-  let resolved_path = resolve_path(path, options.and_then(|o| o.dir))?;
+pub fn remove_file(
+  config: &Config,
+  path: PathBuf,
+  options: Option<FileOperationOptions>,
+) -> crate::Result<()> {
+  let resolved_path = resolve_path(config, path, options.and_then(|o| o.dir))?;
   fs::remove_file(resolved_path)?;
   Ok(())
 }
@@ -269,14 +294,15 @@ pub fn remove_file(path: PathBuf, options: Option<FileOperationOptions>) -> crat
 /// Renames a file.
 #[cfg(fs_rename_file)]
 pub fn rename_file(
+  config: &Config,
   old_path: PathBuf,
   new_path: PathBuf,
   options: Option<FileOperationOptions>,
 ) -> crate::Result<()> {
   let (old, new) = match options.and_then(|o| o.dir) {
     Some(dir) => (
-      resolve_path(old_path, Some(dir.clone()))?,
-      resolve_path(new_path, Some(dir))?,
+      resolve_path(config, old_path, Some(dir.clone()))?,
+      resolve_path(config, new_path, Some(dir))?,
     ),
     None => (old_path, new_path),
   };
@@ -286,11 +312,12 @@ pub fn rename_file(
 /// Writes a text file.
 #[cfg(fs_write_file)]
 pub fn write_file(
+  config: &Config,
   path: PathBuf,
   contents: String,
   options: Option<FileOperationOptions>,
 ) -> crate::Result<()> {
-  File::create(resolve_path(path, options.and_then(|o| o.dir))?)
+  File::create(resolve_path(config, path, options.and_then(|o| o.dir))?)
     .map_err(crate::Error::Io)
     .and_then(|mut f| f.write_all(contents.as_bytes()).map_err(|err| err.into()))?;
   Ok(())
@@ -299,6 +326,7 @@ pub fn write_file(
 /// Writes a binary file.
 #[cfg(fs_write_binary_file)]
 pub fn write_binary_file(
+  config: &Config,
   path: PathBuf,
   contents: String,
   options: Option<FileOperationOptions>,
@@ -306,7 +334,7 @@ pub fn write_binary_file(
   base64::decode(contents)
     .map_err(crate::Error::Base64Decode)
     .and_then(|c| {
-      File::create(resolve_path(path, options.and_then(|o| o.dir))?)
+      File::create(resolve_path(config, path, options.and_then(|o| o.dir))?)
         .map_err(Into::into)
         .and_then(|mut f| f.write_all(&c).map_err(|err| err.into()))
     })?;
@@ -316,29 +344,32 @@ pub fn write_binary_file(
 /// Reads a text file.
 #[cfg(fs_read_text_file)]
 pub fn read_text_file(
+  config: &Config,
   path: PathBuf,
   options: Option<FileOperationOptions>,
 ) -> crate::Result<String> {
-  file::read_string(resolve_path(path, options.and_then(|o| o.dir))?)
+  file::read_string(resolve_path(config, path, options.and_then(|o| o.dir))?)
     .map_err(crate::Error::FailedToExecuteApi)
 }
 
 /// Reads a binary file.
 #[cfg(fs_read_binary_file)]
 pub fn read_binary_file(
+  config: &Config,
   path: PathBuf,
   options: Option<FileOperationOptions>,
 ) -> crate::Result<Vec<u8>> {
-  file::read_binary(resolve_path(path, options.and_then(|o| o.dir))?)
+  file::read_binary(resolve_path(config, path, options.and_then(|o| o.dir))?)
     .map_err(crate::Error::FailedToExecuteApi)
 }
 
 #[cfg(fs_path)]
 pub fn resolve_path_handler(
+  config: &Config,
   path: String,
   directory: Option<BaseDirectory>,
 ) -> crate::Result<PathBuf> {
-  resolve_path(path, directory).map_err(Into::into)
+  resolve_path(config, path, directory).map_err(Into::into)
 }
 
 // test webview functionality.

+ 16 - 12
core/tauri/src/endpoints/notification.rs

@@ -7,6 +7,9 @@ use serde::Deserialize;
 
 #[cfg(notification_all)]
 use crate::api::notification::Notification;
+use crate::Config;
+
+use std::sync::Arc;
 
 // `Granted` response from `request_permission`. Matches the Web API return value.
 #[cfg(notification_all)]
@@ -39,21 +42,21 @@ pub enum Cmd {
 
 impl Cmd {
   #[allow(unused_variables)]
-  pub fn run(self, identifier: String) -> crate::Result<InvokeResponse> {
+  pub fn run(self, config: Arc<Config>) -> crate::Result<InvokeResponse> {
     match self {
       #[cfg(notification_all)]
-      Self::Notification { options } => send(options, identifier).map(Into::into),
+      Self::Notification { options } => send(options, &config).map(Into::into),
       #[cfg(not(notification_all))]
       Self::Notification { .. } => Err(crate::Error::ApiNotAllowlisted("notification".to_string())),
       Self::IsNotificationPermissionGranted => {
         #[cfg(notification_all)]
-        return is_permission_granted().map(Into::into);
+        return is_permission_granted(&config).map(Into::into);
         #[cfg(not(notification_all))]
         Ok(false.into())
       }
       Self::RequestNotificationPermission => {
         #[cfg(notification_all)]
-        return request_permission().map(Into::into);
+        return request_permission(&config).map(Into::into);
         #[cfg(not(notification_all))]
         Ok(PERMISSION_DENIED.into())
       }
@@ -62,8 +65,9 @@ impl Cmd {
 }
 
 #[cfg(notification_all)]
-pub fn send(options: NotificationOptions, identifier: String) -> crate::Result<InvokeResponse> {
-  let mut notification = Notification::new(identifier).title(options.title);
+pub fn send(options: NotificationOptions, config: &Config) -> crate::Result<InvokeResponse> {
+  let mut notification =
+    Notification::new(config.tauri.bundle.identifier.clone()).title(options.title);
   if let Some(body) = options.body {
     notification = notification.body(body);
   }
@@ -75,8 +79,8 @@ pub fn send(options: NotificationOptions, identifier: String) -> crate::Result<I
 }
 
 #[cfg(notification_all)]
-pub fn is_permission_granted() -> crate::Result<InvokeResponse> {
-  let settings = crate::settings::read_settings()?;
+pub fn is_permission_granted(config: &Config) -> crate::Result<InvokeResponse> {
+  let settings = crate::settings::read_settings(config)?;
   if let Some(allow_notification) = settings.allow_notification {
     Ok(allow_notification.into())
   } else {
@@ -85,8 +89,8 @@ pub fn is_permission_granted() -> crate::Result<InvokeResponse> {
 }
 
 #[cfg(notification_all)]
-pub fn request_permission() -> crate::Result<String> {
-  let mut settings = crate::settings::read_settings()?;
+pub fn request_permission(config: &Config) -> crate::Result<String> {
+  let mut settings = crate::settings::read_settings(config)?;
   if let Some(allow_notification) = settings.allow_notification {
     return Ok(if allow_notification {
       PERMISSION_GRANTED.to_string()
@@ -101,12 +105,12 @@ pub fn request_permission() -> crate::Result<String> {
   match answer {
     crate::api::dialog::AskResponse::Yes => {
       settings.allow_notification = Some(true);
-      crate::settings::write_settings(settings)?;
+      crate::settings::write_settings(config, settings)?;
       Ok(PERMISSION_GRANTED.to_string())
     }
     crate::api::dialog::AskResponse::No => {
       settings.allow_notification = Some(false);
-      crate::settings::write_settings(settings)?;
+      crate::settings::write_settings(config, settings)?;
       Ok(PERMISSION_DENIED.to_string())
     }
   }

+ 1 - 1
core/tauri/src/lib.rs

@@ -144,7 +144,7 @@ pub trait Params: sealed::ParamsBase {
 /// TODO: expand these docs
 pub trait Manager<P: Params>: sealed::ManagerBase<P> {
   /// The [`Config`] the manager was created with.
-  fn config(&self) -> &Config {
+  fn config(&self) -> Arc<Config> {
     self.manager().config()
   }
 

+ 8 - 4
core/tauri/src/runtime/manager.rs

@@ -62,7 +62,7 @@ pub struct InnerWindowManager<P: Params> {
   /// The page load hook, invoked when the webview performs a navigation.
   on_page_load: Box<OnPageLoad<P>>,
 
-  config: Config,
+  config: Arc<Config>,
   assets: Arc<P::Assets>,
   default_window_icon: Option<Vec<u8>>,
 
@@ -133,7 +133,7 @@ impl<P: Params> WindowManager<P> {
         state: Arc::new(state),
         invoke_handler,
         on_page_load,
-        config: context.config,
+        config: Arc::new(context.config),
         assets: context.assets,
         default_window_icon: context.default_window_icon,
         salts: Mutex::default(),
@@ -215,6 +215,7 @@ impl<P: Params> WindowManager<P> {
     }
 
     let local_app_data = resolve_path(
+      &self.inner.config,
       &self.inner.config.tauri.bundle.identifier,
       Some(BaseDirectory::LocalData),
     );
@@ -525,12 +526,15 @@ impl<P: Params> WindowManager<P> {
   pub fn labels(&self) -> HashSet<P::Label> {
     self.windows_lock().keys().cloned().collect()
   }
-  pub fn config(&self) -> &Config {
-    &self.inner.config
+
+  pub fn config(&self) -> Arc<Config> {
+    self.inner.config.clone()
   }
+
   pub fn package_info(&self) -> &PackageInfo {
     &self.inner.package_info
   }
+
   pub fn unlisten(&self, handler_id: EventHandler) {
     self.inner.listeners.unlisten(handler_id)
   }

+ 12 - 9
core/tauri/src/settings.rs

@@ -2,9 +2,12 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-License-Identifier: MIT
 
-use crate::api::{
-  file::read_string,
-  path::{resolve_path, BaseDirectory},
+use crate::{
+  api::{
+    file::read_string,
+    path::{resolve_path, BaseDirectory},
+  },
+  Config,
 };
 use serde::{Deserialize, Serialize};
 use std::{
@@ -22,14 +25,14 @@ pub struct Settings {
 }
 
 /// Gets the path to the settings file
-fn get_settings_path() -> crate::api::Result<PathBuf> {
-  resolve_path(".tauri-settings.json", Some(BaseDirectory::App))
+fn get_settings_path(config: &Config) -> crate::api::Result<PathBuf> {
+  resolve_path(config, ".tauri-settings.json", Some(BaseDirectory::App))
 }
 
 /// Write the settings to the file system.
 #[allow(dead_code)]
-pub(crate) fn write_settings(settings: Settings) -> crate::Result<()> {
-  let settings_path = get_settings_path()?;
+pub(crate) fn write_settings(config: &Config, settings: Settings) -> crate::Result<()> {
+  let settings_path = get_settings_path(config)?;
   let settings_folder = Path::new(&settings_path).parent().unwrap();
   if !settings_folder.exists() {
     std::fs::create_dir(settings_folder)?;
@@ -43,8 +46,8 @@ pub(crate) fn write_settings(settings: Settings) -> crate::Result<()> {
 }
 
 /// Reads the settings from the file system.
-pub fn read_settings() -> crate::Result<Settings> {
-  let settings_path = get_settings_path()?;
+pub fn read_settings(config: &Config) -> crate::Result<Settings> {
+  let settings_path = get_settings_path(config)?;
   if settings_path.exists() {
     read_string(settings_path)
       .and_then(|settings| serde_json::from_str(settings.as_str()).map_err(Into::into))