Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(fs): add the size method to get the size of a file or directory #2095

Merged
merged 8 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
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/add-fs-size.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fs: minor
---

Add the `size` method to get the size of a file or directory.
1 change: 1 addition & 0 deletions plugins/fs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const COMMANDS: &[(&str, &[&str])] = &[
("exists", &[]),
("watch", &[]),
("unwatch", &[]),
("size", &[]),
];

fn main() {
Expand Down
27 changes: 26 additions & 1 deletion plugins/fs/guest-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,30 @@ async function watchImmediate(
}
}

/**
* Get the size of a file or directory. For files, the `stat` functions can be used as well.
*
* If `path` is a directory, this function will recursively iterate over every file and every directory inside of `path` and therefore will be very time consuming if used on larger directories.
* @example
FabianLars marked this conversation as resolved.
Show resolved Hide resolved
* ```typescript
* import { size, BaseDirectory } from '@tauri-apps/plugin-fs';
* // Get the size of the `$APPDATA/tauri` directory.
* const dirSize = await size('tauri', { baseDir: BaseDirectory.AppData });
* console.log(dirSize); // 1024
* ```
*
* @since 2.1.0
*/
async function size(path: string | URL): Promise<number> {
if (path instanceof URL && path.protocol !== 'file:') {
throw new TypeError('Must be a file URL.')
}

return await invoke('plugin:fs|size', {
path: path instanceof URL ? path.toString() : path
})
}

export type {
CreateOptions,
OpenOptions,
Expand Down Expand Up @@ -1369,5 +1393,6 @@ export {
writeTextFile,
exists,
watch,
watchImmediate
watchImmediate,
size
}
13 changes: 13 additions & 0 deletions plugins/fs/permissions/autogenerated/commands/size.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!

"$schema" = "../../schemas/schema.json"

[[permission]]
identifier = "allow-size"
description = "Enables the size command without any pre-configured scope."
commands.allow = ["size"]

[[permission]]
identifier = "deny-size"
description = "Denies the size command without any pre-configured scope."
commands.deny = ["size"]
26 changes: 26 additions & 0 deletions plugins/fs/permissions/autogenerated/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -3410,6 +3410,32 @@ Denies the seek command without any pre-configured scope.
<tr>
<td>

`fs:allow-size`

</td>
<td>

Enables the size command without any pre-configured scope.

</td>
</tr>

<tr>
<td>

`fs:deny-size`

</td>
<td>

Denies the size command without any pre-configured scope.

</td>
</tr>

<tr>
<td>

`fs:allow-stat`

</td>
Expand Down
2 changes: 1 addition & 1 deletion plugins/fs/permissions/read-meta.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
[[permission]]
identifier = "read-meta"
description = "This enables all index or metadata related commands without any pre-configured accessible paths."
commands.allow = ["read_dir", "stat", "lstat", "fstat", "exists"]
commands.allow = ["read_dir", "stat", "lstat", "fstat", "exists", "size"]
10 changes: 10 additions & 0 deletions plugins/fs/permissions/schemas/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,16 @@
"type": "string",
"const": "deny-seek"
},
{
"description": "Enables the size command without any pre-configured scope.",
"type": "string",
"const": "allow-size"
},
{
"description": "Denies the size command without any pre-configured scope.",
"type": "string",
"const": "deny-size"
},
{
"description": "Enables the stat command without any pre-configured scope.",
"type": "string",
Expand Down
49 changes: 49 additions & 0 deletions plugins/fs/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,55 @@ pub fn exists<R: Runtime>(
Ok(resolved_path.exists())
}

#[tauri::command]
pub async fn size<R: Runtime>(
webview: Webview<R>,
global_scope: GlobalScope<Entry>,
command_scope: CommandScope<Entry>,
path: SafeFilePath,
options: Option<BaseOptions>,
) -> CommandResult<u64> {
let resolved_path = resolve_path(
&webview,
&global_scope,
&command_scope,
path,
options.as_ref().and_then(|o| o.base_dir),
)?;

let metadata = resolved_path.metadata()?;

if metadata.is_file() {
Ok(metadata.len())
} else {
let size = get_dir_size(&resolved_path).map_err(|e| {
format!(
"failed to get size at path: {} with error: {e}",
resolved_path.display()
)
})?;

Ok(size)
}
}

fn get_dir_size(path: &PathBuf) -> CommandResult<u64> {
let mut size = 0;

for entry in std::fs::read_dir(path)? {
let entry = entry?;
let metadata = entry.metadata()?;

if metadata.is_file() {
size += metadata.len();
} else if metadata.is_dir() {
size += get_dir_size(&entry.path())?;
}
}

Ok(size)
}

#[cfg(not(target_os = "android"))]
pub fn resolve_file<R: Runtime>(
webview: &Webview<R>,
Expand Down
Loading