mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
refactor: cleanup and remove unused tauri::api modules (#7352)
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
"pref": "Performance Improvements",
|
||||
"changes": "What's Changed",
|
||||
"sec": "Security fixes",
|
||||
"deps": "Dependencies"
|
||||
"deps": "Dependencies",
|
||||
"breaking": "Breaking Changes"
|
||||
},
|
||||
"defaultChangeTag": "changes",
|
||||
"pkgManagers": {
|
||||
|
||||
6
.changes/core-remove-file-dir-semver-apis.md
Normal file
6
.changes/core-remove-file-dir-semver-apis.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'tauri': 'patch:breaking'
|
||||
---
|
||||
|
||||
- Removed `tauri::api::file` and `tauri::api::dir` modules, use `std::fs` instead.
|
||||
- Removed `tauri::api::version` module, use `semver` crate instead.
|
||||
@@ -52,10 +52,8 @@ tauri-macros = { version = "2.0.0-alpha.6", path = "../tauri-macros" }
|
||||
tauri-utils = { version = "2.0.0-alpha.6", features = [ "resources" ], path = "../tauri-utils" }
|
||||
tauri-runtime-wry = { version = "0.13.0-alpha.6", path = "../tauri-runtime-wry", optional = true }
|
||||
rand = "0.8"
|
||||
semver = { version = "1.0", features = [ "serde" ] }
|
||||
serde_repr = "0.1"
|
||||
state = "0.6"
|
||||
tempfile = "3"
|
||||
http = "0.2"
|
||||
dirs-next = "2.0"
|
||||
percent-encoding = "2.2"
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Types and functions related to file system directory management.
|
||||
|
||||
use serde::Serialize;
|
||||
use std::{
|
||||
fs::{self, metadata, symlink_metadata},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use tempfile::{self, tempdir};
|
||||
|
||||
/// A disk entry which is either a file or a directory.
|
||||
///
|
||||
/// This is the result of the [`read_dir`]. The `children` field is always `Some` if the entry is a directory.
|
||||
#[derive(Debug, Serialize)]
|
||||
#[non_exhaustive]
|
||||
pub struct DiskEntry {
|
||||
/// The path to the entry.
|
||||
pub path: PathBuf,
|
||||
/// The name of the entry (file name with extension or directory name).
|
||||
pub name: Option<String>,
|
||||
/// The children of this entry if it's a directory.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub children: Option<Vec<DiskEntry>>,
|
||||
}
|
||||
|
||||
/// Checks if the given path is a directory.
|
||||
pub fn is_dir<P: AsRef<Path>>(path: P) -> crate::api::Result<bool> {
|
||||
metadata(path).map(|md| md.is_dir()).map_err(Into::into)
|
||||
}
|
||||
|
||||
fn is_symlink<P: AsRef<Path>>(path: P) -> crate::api::Result<bool> {
|
||||
// TODO: remove the different implementation once we raise tauri's MSRV to at least 1.58
|
||||
#[cfg(windows)]
|
||||
let ret = symlink_metadata(path)
|
||||
.map(|md| md.is_symlink())
|
||||
.map_err(Into::into);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let ret = symlink_metadata(path)
|
||||
.map(|md| md.file_type().is_symlink())
|
||||
.map_err(Into::into);
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/// Reads a directory. Can perform recursive operations.
|
||||
pub fn read_dir<P: AsRef<Path>>(path: P, recursive: bool) -> crate::api::Result<Vec<DiskEntry>> {
|
||||
read_dir_with_options(path, recursive, ReadDirOptions { scope: None })
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct ReadDirOptions<'a> {
|
||||
pub scope: Option<&'a crate::FsScope>,
|
||||
}
|
||||
|
||||
pub(crate) fn read_dir_with_options<P: AsRef<Path>>(
|
||||
path: P,
|
||||
recursive: bool,
|
||||
options: ReadDirOptions<'_>,
|
||||
) -> crate::api::Result<Vec<DiskEntry>> {
|
||||
let mut files_and_dirs: Vec<DiskEntry> = vec![];
|
||||
for entry in fs::read_dir(path)? {
|
||||
let path = entry?.path();
|
||||
let path_as_string = path.display().to_string();
|
||||
|
||||
if let Ok(flag) = is_dir(&path_as_string) {
|
||||
files_and_dirs.push(DiskEntry {
|
||||
path: path.clone(),
|
||||
children: if flag {
|
||||
Some(
|
||||
if recursive
|
||||
&& (!is_symlink(&path_as_string)?
|
||||
|| options.scope.map(|s| s.is_allowed(&path)).unwrap_or(true))
|
||||
{
|
||||
read_dir_with_options(&path_as_string, true, options)?
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
name: path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy())
|
||||
.map(|name| name.to_string()),
|
||||
});
|
||||
}
|
||||
}
|
||||
Result::Ok(files_and_dirs)
|
||||
}
|
||||
|
||||
/// Runs a closure with a temporary directory argument.
|
||||
pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir)>(callback: F) -> crate::api::Result<()> {
|
||||
let dir = tempdir()?;
|
||||
callback(&dir);
|
||||
dir.close()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use quickcheck_macros::quickcheck;
|
||||
use std::{ffi::OsStr, path::PathBuf};
|
||||
|
||||
// check is dir function by passing in arbitrary strings
|
||||
#[quickcheck]
|
||||
fn qc_is_dir(f: String) -> bool {
|
||||
// if the string runs through is_dir and comes out as an OK result then it must be a DIR.
|
||||
if is_dir(f.clone()).is_ok() {
|
||||
PathBuf::from(f).is_dir()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn name_from_path(path: PathBuf) -> Option<String> {
|
||||
path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy())
|
||||
.map(|name| name.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
// check the read_dir function with recursive = true
|
||||
fn check_read_dir_recursively() {
|
||||
// define a relative directory string test/api/
|
||||
let dir = PathBuf::from("test/api/");
|
||||
// add the files to this directory
|
||||
let mut file_one = dir.clone();
|
||||
file_one.push("test.txt");
|
||||
let mut file_two = dir.clone();
|
||||
file_two.push("test_binary");
|
||||
|
||||
// call walk_dir on the directory
|
||||
let res = read_dir(dir, true);
|
||||
|
||||
// assert that the result is Ok()
|
||||
assert!(res.is_ok());
|
||||
|
||||
// destruct the OK into a vector of DiskEntry Structs
|
||||
if let Ok(vec) = res {
|
||||
// assert that the vector length is only 3
|
||||
assert_eq!(vec.len(), 2);
|
||||
|
||||
// get the first DiskEntry
|
||||
let first = &vec[0];
|
||||
// get the second DiskEntry
|
||||
let second = &vec[1];
|
||||
|
||||
if first.path.extension() == Some(OsStr::new("txt")) {
|
||||
// check the fields for the first DiskEntry
|
||||
assert_eq!(first.path, file_one);
|
||||
assert!(first.children.is_none());
|
||||
assert_eq!(first.name, name_from_path(file_one));
|
||||
|
||||
// check the fields for the third DiskEntry
|
||||
assert_eq!(second.path, file_two);
|
||||
assert!(second.children.is_none());
|
||||
assert_eq!(second.name, name_from_path(file_two));
|
||||
} else {
|
||||
// check the fields for the second DiskEntry
|
||||
assert_eq!(first.path, file_two);
|
||||
assert!(first.children.is_none());
|
||||
assert_eq!(first.name, name_from_path(file_two));
|
||||
|
||||
// check the fields for the third DiskEntry
|
||||
assert_eq!(second.path, file_one);
|
||||
assert!(second.children.is_none());
|
||||
assert_eq!(second.name, name_from_path(file_one));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// check the read_dir function with recursive = false
|
||||
fn check_read_dir() {
|
||||
// define a relative directory test/api/
|
||||
let dir = PathBuf::from("test/api/");
|
||||
|
||||
// call list_dir_contents on the dir
|
||||
let res = read_dir(dir, false);
|
||||
|
||||
// assert that the result is Ok()
|
||||
assert!(res.is_ok());
|
||||
|
||||
// destruct the vector from the Ok()
|
||||
if let Ok(vec) = res {
|
||||
// assert the length of the vector is 2
|
||||
assert_eq!(vec.len(), 2);
|
||||
|
||||
// get the two DiskEntry structs in this vector
|
||||
let first = &vec[0];
|
||||
let second = &vec[1];
|
||||
|
||||
if first.path.extension() == Some(OsStr::new("txt")) {
|
||||
// check the fields for the first DiskEntry
|
||||
assert_eq!(first.path, PathBuf::from("test/api/test.txt"));
|
||||
assert!(first.children.is_none());
|
||||
assert_eq!(first.name, Some("test.txt".to_string()));
|
||||
|
||||
// check the fields for the second DiskEntry
|
||||
assert_eq!(second.path, PathBuf::from("test/api/test_binary"));
|
||||
assert!(second.children.is_none());
|
||||
assert_eq!(second.name, Some("test_binary".to_string()));
|
||||
} else {
|
||||
// check the fields for the first DiskEntry
|
||||
assert_eq!(second.path, PathBuf::from("test/api/test.txt"));
|
||||
assert!(second.children.is_none());
|
||||
assert_eq!(second.name, Some("test.txt".to_string()));
|
||||
|
||||
// check the fields for the second DiskEntry
|
||||
assert_eq!(first.path, PathBuf::from("test/api/test_binary"));
|
||||
assert!(first.children.is_none());
|
||||
assert_eq!(first.name, Some("test_binary".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// test the with_temp_dir function
|
||||
fn check_test_dir() {
|
||||
// create a callback closure that takes in a TempDir type and prints it.
|
||||
let callback = |td: &tempfile::TempDir| {
|
||||
println!("{td:?}");
|
||||
};
|
||||
|
||||
// execute the with_temp_dir function on the callback
|
||||
let res = with_temp_dir(callback);
|
||||
|
||||
// assert that the result is an OK type.
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
}
|
||||
@@ -2,17 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/// The error types.
|
||||
/// The result type of Tauri API module.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// The error type of Tauri API module.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Semver error.
|
||||
#[error(transparent)]
|
||||
Semver(#[from] semver::Error),
|
||||
/// JSON error.
|
||||
#[error(transparent)]
|
||||
Json(#[from] serde_json::Error),
|
||||
/// IO error.
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Types and functions related to file operations.
|
||||
|
||||
use std::{fs, path::Path};
|
||||
|
||||
/// Reads the entire contents of a file into a string.
|
||||
pub fn read_string<P: AsRef<Path>>(file: P) -> crate::api::Result<String> {
|
||||
fs::read_to_string(file).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Reads the entire contents of a file into a bytes vector.
|
||||
pub fn read_binary<P: AsRef<Path>>(file: P) -> crate::api::Result<Vec<u8>> {
|
||||
fs::read(file).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[cfg(not(windows))]
|
||||
use crate::api::Error;
|
||||
|
||||
#[test]
|
||||
fn check_read_string() {
|
||||
let file = String::from("test/api/test.txt");
|
||||
|
||||
let res = read_string(file);
|
||||
|
||||
assert!(res.is_ok());
|
||||
|
||||
if let Ok(s) = res {
|
||||
assert_eq!(s, "This is a test doc!".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_read_string_fail() {
|
||||
let file = String::from("test/api/");
|
||||
|
||||
let res = read_string(file);
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
#[cfg(not(windows))]
|
||||
if let Error::Io(e) = res.unwrap_err() {
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(e.to_string(), "Is a directory (os error 21)".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_read_binary() {
|
||||
let file = String::from("test/api/test_binary");
|
||||
|
||||
let expected_vec = vec![
|
||||
71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 128, 0, 0, 255, 255, 255, 0, 0, 0, 33, 249, 4, 1, 0, 0,
|
||||
0, 0, 44, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 2, 68, 1, 0, 59,
|
||||
];
|
||||
|
||||
let res = read_binary(file);
|
||||
|
||||
assert!(res.is_ok());
|
||||
|
||||
if let Ok(vec) = res {
|
||||
assert_eq!(vec, expected_vec);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_read_binary_fail() {
|
||||
let file = String::from("test/api/");
|
||||
|
||||
let res = read_binary(file);
|
||||
|
||||
assert!(res.is_err());
|
||||
|
||||
#[cfg(not(windows))]
|
||||
if let Error::Io(e) = res.unwrap_err() {
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(e.to_string(), "Is a directory (os error 21)".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,11 @@
|
||||
|
||||
//! The Tauri API interface.
|
||||
|
||||
pub mod dir;
|
||||
pub mod file;
|
||||
pub mod ipc;
|
||||
pub mod version;
|
||||
|
||||
mod error;
|
||||
|
||||
/// The error type of Tauri API module.
|
||||
pub use error::Error;
|
||||
/// The result type of Tauri API module.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
// Not public API
|
||||
#[doc(hidden)]
|
||||
pub mod private {
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Compare two semantic versions.
|
||||
//!
|
||||
//! [Semantic Versioning](https://semver.org) is a guideline for how version numbers are assigned and incremented.
|
||||
//! The functions on this module are helpers around [semver](https://docs.rs/semver/latest/semver/).
|
||||
|
||||
use semver::Version;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
/// Compare two semver versions.
|
||||
///
|
||||
/// If the `first` semver is greater, returns -1.
|
||||
/// If the `second` semver is greater, returns 1.
|
||||
/// If they are equal, returns 0.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::compare;
|
||||
/// assert_eq!(compare("0.15.0", "0.15.5").unwrap(), 1);
|
||||
/// assert_eq!(compare("0.15.10", "0.15.9").unwrap(), -1);
|
||||
/// assert_eq!(compare("0.15.10", "0.16.10").unwrap(), 1);
|
||||
/// assert_eq!(compare("1.57.0", "2.17.4").unwrap(), 1);
|
||||
/// assert_eq!(compare("0.0.0", "0.0.0").unwrap(), 0);
|
||||
/// ```
|
||||
pub fn compare(first: &str, second: &str) -> crate::api::Result<i8> {
|
||||
let v1 = Version::parse(first)?;
|
||||
let v2 = Version::parse(second)?;
|
||||
match v1.cmp(&v2) {
|
||||
Ordering::Greater => Ok(-1),
|
||||
Ordering::Less => Ok(1),
|
||||
Ordering::Equal => Ok(0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the "second" semver is compatible with the "first".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::is_compatible;
|
||||
/// assert!(is_compatible("0.15.0", "0.15.5").unwrap());
|
||||
/// assert!(!is_compatible("0.15.0", "0.16.5").unwrap());
|
||||
///
|
||||
/// assert!(is_compatible("1.5.0", "1.5.10").unwrap());
|
||||
/// assert!(is_compatible("1.54.0", "1.55.0").unwrap());
|
||||
/// assert!(!is_compatible("2.17.0", "3.17.0").unwrap());
|
||||
/// ```
|
||||
pub fn is_compatible(first: &str, second: &str) -> crate::api::Result<bool> {
|
||||
let first = Version::parse(first)?;
|
||||
let second = Version::parse(second)?;
|
||||
Ok(if second.major == 0 && first.major == 0 {
|
||||
first.minor == second.minor && second.patch > first.patch
|
||||
} else if second.major > 0 {
|
||||
first.major == second.major
|
||||
&& ((second.minor > first.minor)
|
||||
|| (first.minor == second.minor && second.patch > first.patch))
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if a the "other" version is a major bump from the "current".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::is_major;
|
||||
/// assert!(is_major("1.0.0", "2.0.0").unwrap());
|
||||
/// assert!(is_major("1.5.0", "2.17.10").unwrap());
|
||||
/// assert!(is_major("0.5.0", "2.17.10").unwrap());
|
||||
/// assert!(!is_major("1.1.5", "1.2.5").unwrap());
|
||||
/// assert!(!is_major("0.14.0", "0.15.0").unwrap());
|
||||
/// ```
|
||||
pub fn is_major(current: &str, other: &str) -> crate::api::Result<bool> {
|
||||
let current = Version::parse(current)?;
|
||||
let other = Version::parse(other)?;
|
||||
Ok(other.major > current.major)
|
||||
}
|
||||
|
||||
/// Check if a the "other" version is a minor bump from the "current".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::is_minor;
|
||||
/// assert!(is_minor("0.15.10", "0.16.110").unwrap());
|
||||
/// assert!(is_minor("1.0.0", "1.1.1").unwrap());
|
||||
/// assert!(!is_minor("2.1.9", "3.2.0").unwrap());
|
||||
/// assert!(!is_minor("1.0.0", "1.0.10").unwrap());
|
||||
/// ```
|
||||
pub fn is_minor(current: &str, other: &str) -> crate::api::Result<bool> {
|
||||
let current = Version::parse(current)?;
|
||||
let other = Version::parse(other)?;
|
||||
Ok(current.major == other.major && other.minor > current.minor)
|
||||
}
|
||||
|
||||
/// Check if a the "other" version is a patch bump from the "current".
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::is_patch;
|
||||
/// assert!(is_patch("0.15.0", "0.15.1").unwrap());
|
||||
/// assert!(is_patch("1.0.0", "1.0.1").unwrap());
|
||||
/// assert!(!is_patch("2.2.0", "2.3.1").unwrap());
|
||||
/// assert!(!is_patch("2.2.1", "1.1.0").unwrap());
|
||||
/// ```
|
||||
pub fn is_patch(current: &str, other: &str) -> crate::api::Result<bool> {
|
||||
let current = Version::parse(current)?;
|
||||
let other = Version::parse(other)?;
|
||||
Ok(current.major == other.major && current.minor == other.minor && other.patch > current.patch)
|
||||
}
|
||||
|
||||
/// Check if a version is greater than the current.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use tauri::api::version::is_greater;
|
||||
/// assert!(is_greater("0.15.10", "0.16.0").unwrap());
|
||||
/// assert!(is_greater("1.0.0", "1.0.1").unwrap());
|
||||
/// assert!(is_greater("1.1.9", "1.2.0").unwrap());
|
||||
/// assert!(is_greater("1.0.0", "2.0.0").unwrap());
|
||||
/// ```
|
||||
pub fn is_greater(current: &str, other: &str) -> crate::api::Result<bool> {
|
||||
Ok(Version::parse(other)? > Version::parse(current)?)
|
||||
}
|
||||
Reference in New Issue
Block a user