You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by ps...@apache.org on 2026/08/10 14:37:11 UTC
(opendal-ofs) 01/03: refactor: reset legacy direct mount implementation
This is an automated email from the ASF dual-hosted git repository.
PsiACE pushed a commit to branch reset/direct-mount
in repository https://gitbox.apache.org/repos/asf/opendal-ofs.git
commit a5071b801f619d6e950d88d1c012aa8284bbd4a6
Author: PsiACE <ps...@apache.org>
AuthorDate: Mon Aug 10 22:29:39 2026 +0800
refactor: reset legacy direct mount implementation
---
.github/workflows/release.yml | 116 --
Cargo.lock | 3164 +-----------------------------
Cargo.toml | 48 +-
DEPENDENCIES.md | 3 -
DEPENDENCIES.rust.tsv | 233 ---
README.md | 65 +-
integrations/fuse3/.gitignore | 1 -
integrations/fuse3/Cargo.toml | 40 -
integrations/fuse3/DEPENDENCIES.rust.tsv | 192 --
integrations/fuse3/README.md | 69 -
integrations/fuse3/src/file.rs | 67 -
integrations/fuse3/src/file_system.rs | 836 --------
integrations/fuse3/src/lib.rs | 60 -
src/lib.rs | 21 +
src/main.rs | 106 -
tests/common/mod.rs | 106 -
tests/file.rs | 126 --
tests/file_system.rs | 95 -
tests/path.rs | 75 -
19 files changed, 62 insertions(+), 5361 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 9db2d0a..0000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,116 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-name: Ofs Release
-
-on:
- push:
- tags:
- - "v*"
- workflow_dispatch:
-
-permissions:
- contents: write
-
-env:
- CARGO_TERM_COLOR: always
- BIN_NAME: ofs
-
-jobs:
- build:
- name: Build ${{ matrix.target }}
- runs-on: ${{ matrix.os }}
- defaults:
- run:
- shell: bash
- strategy:
- fail-fast: false
- matrix:
- include:
- - os: ubuntu-latest
- target: x86_64-unknown-linux-gnu
- build-command: cargo
- use-cross: false
- - os: ubuntu-latest
- target: aarch64-unknown-linux-gnu
- build-command: cross
- use-cross: true
- steps:
- - uses: actions/checkout@v7
-
- - name: Setup Rust builder
- uses: ./.github/actions/setup
-
- - name: Install cross
- if: matrix.use-cross
- run: cargo install cross --locked
-
- - name: Build target
- env:
- BUILD_COMMAND: ${{ matrix.build-command }}
- CARGO_PROFILE_RELEASE_LTO: true
- run: '"${BUILD_COMMAND}" build --locked --release --target "${{ matrix.target }}"'
-
- - name: Package artifact (Unix)
- if: runner.os != 'Windows'
- env:
- TARGET: ${{ matrix.target }}
- run: |
- set -euo pipefail
- ARCHIVE_NAME="ofs-${GITHUB_REF_NAME}-${TARGET}"
- PACKAGE_DIR="${ARCHIVE_NAME}"
- mkdir -p "${PACKAGE_DIR}"
- cp "target/${TARGET}/release/${BIN_NAME}" "${PACKAGE_DIR}/"
- cp LICENSE NOTICE "${PACKAGE_DIR}/"
- mkdir -p dist
- tar -czf "dist/${ARCHIVE_NAME}.tar.gz" -C "${PACKAGE_DIR}" .
- rm -rf "${PACKAGE_DIR}"
-
- - name: Upload artifact
- uses: actions/upload-artifact@v7
- with:
- name: ofs-${{ github.ref_name }}-${{ matrix.target }}
- path: dist/ofs-*
- if-no-files-found: error
-
- release:
- name: Publish release
- needs: build
- if: startsWith(github.ref, 'refs/tags/')
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v7
-
- - name: Download all artifacts
- uses: actions/download-artifact@v8
- with:
- path: dist
- merge-multiple: true
-
- - name: Publish GitHub release
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
- with:
- files: |
- dist/*.tar.gz
- name: ${{ github.ref_name }}
- tag_name: ${{ github.ref_name }}
- generate_release_notes: true
-
- - name: Publish to crates.io
- run: cargo publish --locked --no-verify
- env:
- CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
diff --git a/Cargo.lock b/Cargo.lock
index 307f6e3..788d2d6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,3165 +3,5 @@
version = 4
[[package]]
-name = "anstream"
-version = "0.6.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
-dependencies = [
- "windows-sys 0.60.2",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
-dependencies = [
- "anstyle",
- "once_cell_polyfill",
- "windows-sys 0.60.2",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
-
-[[package]]
-name = "async-notify"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db96c36382f56ea91e5d012c4c7170046c7731449daa46655cbcabc594c8bee6"
-dependencies = [
- "event-listener",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "atomic-waker"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-
-[[package]]
-name = "autocfg"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
-
-[[package]]
-name = "aws-lc-rs"
-version = "1.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00"
-dependencies = [
- "aws-lc-sys",
- "zeroize",
-]
-
-[[package]]
-name = "aws-lc-sys"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4"
-dependencies = [
- "cc",
- "cmake",
- "dunce",
- "fs_extra",
-]
-
-[[package]]
-name = "backon"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef"
-dependencies = [
- "fastrand",
- "gloo-timers",
- "tokio",
-]
-
-[[package]]
-name = "base64"
-version = "0.22.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
-
-[[package]]
-name = "bincode"
-version = "1.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "bitflags"
-version = "2.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
-
-[[package]]
-name = "block-buffer"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be"
-dependencies = [
- "hybrid-array",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
-
-[[package]]
-name = "bytes"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
-
-[[package]]
-name = "cc"
-version = "1.2.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
-dependencies = [
- "find-msvc-tools",
- "jobserver",
- "libc",
- "shlex",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
-
-[[package]]
-name = "chacha20"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "rand_core",
-]
-
-[[package]]
-name = "clap"
-version = "4.5.48"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
-dependencies = [
- "clap_builder",
- "clap_derive",
-]
-
-[[package]]
-name = "clap_builder"
-version = "4.5.48"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
-dependencies = [
- "anstream",
- "anstyle",
- "clap_lex",
- "strsim",
-]
-
-[[package]]
-name = "clap_derive"
-version = "4.5.47"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "clap_lex"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
-
-[[package]]
-name = "cmake"
-version = "0.1.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
-dependencies = [
- "cc",
-]
-
-[[package]]
-name = "cmov"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
-
-[[package]]
-name = "colorchoice"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
-
-[[package]]
-name = "colored"
-version = "3.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "combine"
-version = "4.6.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
-dependencies = [
- "bytes",
- "memchr",
-]
-
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "const-oid"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
-
-[[package]]
-name = "const-random"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
-dependencies = [
- "const-random-macro",
-]
-
-[[package]]
-name = "const-random-macro"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
-dependencies = [
- "getrandom 0.2.16",
- "once_cell",
- "tiny-keccak",
-]
-
-[[package]]
-name = "core-foundation"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
-
-[[package]]
-name = "cpufeatures"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "crc32c"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47"
-dependencies = [
- "rustc_version",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
-
-[[package]]
-name = "crunchy"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
-
-[[package]]
-name = "crypto-common"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
-dependencies = [
- "hybrid-array",
-]
-
-[[package]]
-name = "ctor"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01334b89b69ff726750c5ce5073fc8bd860e99aa9a8fc5ca11b04730e3aee97a"
-dependencies = [
- "link-section",
- "linktime-proc-macro",
-]
-
-[[package]]
-name = "ctutils"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
-dependencies = [
- "cmov",
-]
-
-[[package]]
-name = "digest"
-version = "0.11.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
-dependencies = [
- "block-buffer",
- "const-oid",
- "crypto-common",
- "ctutils",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-[[package]]
-name = "dlv-list"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
-dependencies = [
- "const-random",
-]
-
-[[package]]
-name = "dotenvy"
-version = "0.15.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
-
-[[package]]
-name = "dunce"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
-
-[[package]]
-name = "either"
-version = "1.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "erased-serde"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec"
-dependencies = [
- "serde",
- "serde_core",
- "typeid",
-]
-
-[[package]]
-name = "errno"
-version = "0.3.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
-dependencies = [
- "libc",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "event-listener"
-version = "4.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
-
-[[package]]
-name = "find-msvc-tools"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "foldhash"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "fs_extra"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
-
-[[package]]
-name = "fuse3"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335dd07e2826edad49c2599ed8151c394d39d2f8efd62c07183816904414ac5c"
-dependencies = [
- "async-notify",
- "bincode",
- "bytes",
- "futures-channel",
- "futures-util",
- "libc",
- "nix 0.29.0",
- "serde",
- "slab",
- "tokio",
- "tracing",
- "trait-make",
- "which",
-]
-
-[[package]]
-name = "fuse3_opendal"
-version = "0.0.19"
-dependencies = [
- "bytes",
- "fuse3",
- "futures-util",
- "libc",
- "log",
- "opendal",
- "sharded-slab",
- "tokio",
-]
-
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
- "futures-sink",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-sink"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
-dependencies = [
- "cfg-if",
- "js-sys",
- "libc",
- "wasi 0.11.1+wasi-snapshot-preview1",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
-dependencies = [
- "cfg-if",
- "libc",
- "r-efi 5.3.0",
- "wasi 0.14.7+wasi-0.2.4",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
-dependencies = [
- "cfg-if",
- "js-sys",
- "libc",
- "r-efi 6.0.0",
- "rand_core",
- "wasip2",
- "wasip3",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "gloo-timers"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
-dependencies = [
- "futures-channel",
- "futures-core",
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.14.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
-
-[[package]]
-name = "hashbrown"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
-dependencies = [
- "foldhash",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.17.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
-
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "hmac"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
-dependencies = [
- "digest",
-]
-
-[[package]]
-name = "home"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "http"
-version = "1.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
-dependencies = [
- "bytes",
- "fnv",
- "itoa",
-]
-
-[[package]]
-name = "http-body"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
-dependencies = [
- "bytes",
- "http",
-]
-
-[[package]]
-name = "http-body-util"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
-dependencies = [
- "bytes",
- "futures-core",
- "http",
- "http-body",
- "pin-project-lite",
-]
-
-[[package]]
-name = "httparse"
-version = "1.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
-
-[[package]]
-name = "hybrid-array"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
-dependencies = [
- "typenum",
-]
-
-[[package]]
-name = "hyper"
-version = "1.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
-dependencies = [
- "atomic-waker",
- "bytes",
- "futures-channel",
- "futures-core",
- "http",
- "http-body",
- "httparse",
- "itoa",
- "pin-project-lite",
- "pin-utils",
- "smallvec",
- "tokio",
- "want",
-]
-
-[[package]]
-name = "hyper-rustls"
-version = "0.27.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
-dependencies = [
- "http",
- "hyper",
- "hyper-util",
- "rustls",
- "rustls-pki-types",
- "tokio",
- "tokio-rustls",
- "tower-service",
-]
-
-[[package]]
-name = "hyper-util"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
-dependencies = [
- "base64",
- "bytes",
- "futures-channel",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "hyper",
- "ipnet",
- "libc",
- "percent-encoding",
- "pin-project-lite",
- "socket2",
- "tokio",
- "tower-service",
- "tracing",
-]
-
-[[package]]
-name = "icu_collections"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
-
-[[package]]
-name = "icu_properties"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "potential_utf",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
-
-[[package]]
-name = "icu_provider"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "stable_deref_trait",
- "tinystr",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "id-arena"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
-
-[[package]]
-name = "idna"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
-dependencies = [
- "equivalent",
- "hashbrown 0.17.1",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "ipnet"
-version = "2.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
-
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
-[[package]]
-name = "itoa"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
-
-[[package]]
-name = "jiff"
-version = "0.2.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102"
-dependencies = [
- "jiff-static",
- "jiff-tzdb-platform",
- "js-sys",
- "log",
- "portable-atomic",
- "portable-atomic-util",
- "serde_core",
- "wasm-bindgen",
- "windows-link",
-]
-
-[[package]]
-name = "jiff-static"
-version = "0.2.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jiff-tzdb"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
-
-[[package]]
-name = "jiff-tzdb-platform"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
-dependencies = [
- "jiff-tzdb",
-]
-
-[[package]]
-name = "jni"
-version = "0.22.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
-dependencies = [
- "cfg-if",
- "combine",
- "jni-macros",
- "jni-sys",
- "log",
- "simd_cesu8",
- "thiserror",
- "walkdir",
- "windows-link",
-]
-
-[[package]]
-name = "jni-macros"
-version = "0.22.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
-dependencies = [
- "proc-macro2",
- "quote",
- "rustc_version",
- "simd_cesu8",
- "syn",
-]
-
-[[package]]
-name = "jni-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
-dependencies = [
- "jni-sys-macros",
-]
-
-[[package]]
-name = "jni-sys-macros"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
-dependencies = [
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jobserver"
-version = "0.1.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
-dependencies = [
- "getrandom 0.3.3",
- "libc",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
-dependencies = [
- "cfg-if",
- "futures-util",
- "once_cell",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
-[[package]]
-name = "libc"
-version = "0.2.176"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
-
-[[package]]
-name = "link-section"
-version = "0.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "014e440054ce8170890229eeef5bcda955305e056ec713de40ed366944483f09"
-
-[[package]]
-name = "linktime-proc-macro"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c7b0a3383c2a1002d11349c92c85a666a5fb679e96c79d782cf0dbe557fd6ee"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
-
-[[package]]
-name = "litemap"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
-
-[[package]]
-name = "log"
-version = "0.4.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5"
-dependencies = [
- "sval",
- "sval_ref",
- "value-bag",
-]
-
-[[package]]
-name = "logforth"
-version = "0.28.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd048889d633cac5c189eca703f5c5ed65210d358eb5910a478e233d42528d6e"
-dependencies = [
- "logforth-append-file",
- "logforth-bridge-log",
- "logforth-core",
- "logforth-layout-json",
- "logforth-layout-text",
-]
-
-[[package]]
-name = "logforth-append-file"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aeb66a16ac0f5cdd6a0e7005c6e1fa2744e915244941ac6cd01bd56de2995f48"
-dependencies = [
- "jiff",
- "logforth-core",
-]
-
-[[package]]
-name = "logforth-bridge-log"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "392ff9723d68a943ccffabe03b5272f7c93104f0008a6c7357ef888c21ab6297"
-dependencies = [
- "log",
- "logforth-core",
-]
-
-[[package]]
-name = "logforth-core"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7666819ed32e38aabb45959a632b0f9c25fc77e60c824b02a5fcd87ab626f6ed"
-dependencies = [
- "anyhow",
- "value-bag",
-]
-
-[[package]]
-name = "logforth-layout-json"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49e1db5d0f5b1bc57134ff9d1ed3889910d230545f3d249bde44bac0e8a8724f"
-dependencies = [
- "jiff",
- "logforth-core",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "logforth-layout-text"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c00c67d92539b26edbba5e43ce8f5b97d62412c1cfc9463400f50cfad2f1f1bf"
-dependencies = [
- "colored",
- "jiff",
- "logforth-core",
-]
-
-[[package]]
-name = "lru-slab"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
-
-[[package]]
-name = "md-5"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
-dependencies = [
- "cfg-if",
- "digest",
-]
-
-[[package]]
-name = "mea"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2640d335e7273dacdcf51044026139b2e269c3bb0dfc3f8cb3496b85e3f6a42c"
-dependencies = [
- "slab",
-]
-
-[[package]]
-name = "memchr"
-version = "2.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
-
-[[package]]
-name = "memoffset"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "mio"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
-dependencies = [
- "libc",
- "wasi 0.11.1+wasi-snapshot-preview1",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "nix"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
- "memoffset",
-]
-
-[[package]]
-name = "nix"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
-]
-
-[[package]]
-name = "ofs"
-version = "0.0.24"
-dependencies = [
- "anyhow",
- "clap",
- "fuse3",
- "fuse3_opendal",
- "libc",
- "log",
- "logforth",
- "nix 0.30.1",
- "opendal",
- "tempfile",
- "test-context",
- "tokio",
- "url",
- "walkdir",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "once_cell_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
-
-[[package]]
-name = "opendal"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96c9c85ce253ff87225e7669979d877a20c98a06604ec9d6dd5f4473e08f1ae1"
-dependencies = [
- "ctor",
- "opendal-core",
- "opendal-layer-concurrent-limit",
- "opendal-layer-logging",
- "opendal-layer-retry",
- "opendal-layer-timeout",
- "opendal-service-fs",
- "opendal-service-s3",
- "opendal-testkit",
-]
-
-[[package]]
-name = "opendal-core"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4f8607c90e2c963a91467f50fb49fbc7fb3d573f88cea219ca59ccd3740b309"
-dependencies = [
- "anyhow",
- "base64",
- "bytes",
- "futures",
- "http",
- "http-body",
- "jiff",
- "log",
- "md-5",
- "mea",
- "percent-encoding",
- "quick-xml 0.39.4",
- "reqsign-core",
- "reqwest",
- "serde",
- "serde_json",
- "tokio",
- "url",
- "uuid",
- "web-time",
-]
-
-[[package]]
-name = "opendal-layer-concurrent-limit"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d6f81ba6960e3fae1882f253b114b21d7e444e1534f209c7737a79f6243eb6f"
-dependencies = [
- "futures",
- "http",
- "mea",
- "opendal-core",
-]
-
-[[package]]
-name = "opendal-layer-logging"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58ada45c6d81d1aa4c9305d0c7d4bc317c59c85866a0908a2d75a7a978aa5ee2"
-dependencies = [
- "log",
- "opendal-core",
-]
-
-[[package]]
-name = "opendal-layer-retry"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b2a25a718afb81fad81cb9a0580a1cb989221fa2317f888c6a37f8dad408eb7"
-dependencies = [
- "backon",
- "log",
- "opendal-core",
-]
-
-[[package]]
-name = "opendal-layer-timeout"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e91f731724c213af81e9d03517859c8fc47b4578e64ad61ae4f099f10fe36e3"
-dependencies = [
- "opendal-core",
- "tokio",
-]
-
-[[package]]
-name = "opendal-service-fs"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22e89a665fef0e6bd249cf5ea47fc174b7ba892159bee4b9382528b1ca873a2c"
-dependencies = [
- "bytes",
- "log",
- "opendal-core",
- "serde",
- "tokio",
- "xattr",
-]
-
-[[package]]
-name = "opendal-service-s3"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "313d46c9f5ae70bca26b7c3e3fbb9b639292625f28af73aa016f47e788af9deb"
-dependencies = [
- "base64",
- "bytes",
- "crc32c",
- "http",
- "log",
- "md-5",
- "opendal-core",
- "quick-xml 0.39.4",
- "reqsign-aws-v4",
- "reqsign-core",
- "reqsign-file-read-tokio",
- "serde",
- "url",
-]
-
-[[package]]
-name = "opendal-testkit"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d59b873d34419de4c19393f72cae95f92ef9e065a18a5497a45126d98d84128"
-dependencies = [
- "bytes",
- "dotenvy",
- "opendal-core",
- "opendal-layer-logging",
- "opendal-layer-retry",
- "opendal-layer-timeout",
- "rand",
- "sha2",
- "tokio",
- "uuid",
-]
-
-[[package]]
-name = "openssl-probe"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
-
-[[package]]
-name = "ordered-multimap"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
-dependencies = [
- "dlv-list",
- "hashbrown 0.14.5",
-]
-
-[[package]]
-name = "parking"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "portable-atomic"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
-
-[[package]]
-name = "portable-atomic-util"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
-dependencies = [
- "portable-atomic",
-]
-
-[[package]]
-name = "potential_utf"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.101"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quick-xml"
-version = "0.39.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
-dependencies = [
- "memchr",
- "serde",
-]
-
-[[package]]
-name = "quick-xml"
-version = "0.41.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
-dependencies = [
- "memchr",
- "serde",
-]
-
-[[package]]
-name = "quinn"
-version = "0.11.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
-dependencies = [
- "bytes",
- "cfg_aliases",
- "pin-project-lite",
- "quinn-proto",
- "quinn-udp",
- "rustc-hash",
- "rustls",
- "socket2",
- "thiserror",
- "tokio",
- "tracing",
- "web-time",
-]
-
-[[package]]
-name = "quinn-proto"
-version = "0.11.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
-dependencies = [
- "aws-lc-rs",
- "bytes",
- "getrandom 0.4.2",
- "lru-slab",
- "rand",
- "rand_pcg",
- "ring",
- "rustc-hash",
- "rustls",
- "rustls-pki-types",
- "slab",
- "thiserror",
- "tinyvec",
- "tracing",
- "web-time",
-]
-
-[[package]]
-name = "quinn-udp"
-version = "0.5.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
-dependencies = [
- "cfg_aliases",
- "libc",
- "once_cell",
- "socket2",
- "tracing",
- "windows-sys 0.60.2",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "r-efi"
-version = "5.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
-
-[[package]]
-name = "r-efi"
-version = "6.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
-
-[[package]]
-name = "rand"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
-dependencies = [
- "chacha20",
- "getrandom 0.4.2",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
-
-[[package]]
-name = "rand_pcg"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "reqsign-aws-v4"
-version = "3.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc883bc56889f3e4a419265c87facea222a921debc5c6f15c7fd8b68ec4b36b2"
-dependencies = [
- "anyhow",
- "bytes",
- "form_urlencoded",
- "hex",
- "http",
- "log",
- "percent-encoding",
- "quick-xml 0.41.0",
- "reqsign-core",
- "rust-ini",
- "serde",
- "serde_json",
- "serde_urlencoded",
- "sha1",
-]
-
-[[package]]
-name = "reqsign-core"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e38b44697c60a823705ccef85cb04d8e0527c9d16ed7c58bf1c6395bdd24ceb"
-dependencies = [
- "anyhow",
- "base64",
- "bytes",
- "futures",
- "hex",
- "hmac",
- "http",
- "jiff",
- "log",
- "percent-encoding",
- "sha1",
- "sha2",
- "windows-sys 0.61.2",
-]
-
-[[package]]
-name = "reqsign-file-read-tokio"
-version = "3.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "688ff0ae421b8d4b92b53fdafaf53df2de28f428a9962edcf21702990b26f74b"
-dependencies = [
- "anyhow",
- "reqsign-core",
- "tokio",
-]
-
-[[package]]
-name = "reqwest"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3"
-dependencies = [
- "base64",
- "bytes",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "http-body-util",
- "hyper",
- "hyper-rustls",
- "hyper-util",
- "js-sys",
- "log",
- "percent-encoding",
- "pin-project-lite",
- "quinn",
- "rustls",
- "rustls-pki-types",
- "rustls-platform-verifier",
- "sync_wrapper",
- "tokio",
- "tokio-rustls",
- "tokio-util",
- "tower",
- "tower-http",
- "tower-service",
- "url",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "wasm-streams",
- "web-sys",
-]
-
-[[package]]
-name = "ring"
-version = "0.17.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
-dependencies = [
- "cc",
- "cfg-if",
- "getrandom 0.2.16",
- "libc",
- "untrusted",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rust-ini"
-version = "0.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7"
-dependencies = [
- "cfg-if",
- "ordered-multimap",
-]
-
-[[package]]
-name = "rustc-hash"
-version = "2.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
-
-[[package]]
-name = "rustc_version"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys 0.4.15",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustix"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys 0.11.0",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustls"
-version = "0.23.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40"
-dependencies = [
- "aws-lc-rs",
- "once_cell",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
-]
-
-[[package]]
-name = "rustls-native-certs"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
-dependencies = [
- "openssl-probe",
- "rustls-pki-types",
- "schannel",
- "security-framework",
-]
-
-[[package]]
-name = "rustls-pki-types"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
-dependencies = [
- "web-time",
- "zeroize",
-]
-
-[[package]]
-name = "rustls-platform-verifier"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
-dependencies = [
- "core-foundation",
- "core-foundation-sys",
- "jni",
- "log",
- "once_cell",
- "rustls",
- "rustls-native-certs",
- "rustls-platform-verifier-android",
- "rustls-webpki",
- "security-framework",
- "security-framework-sys",
- "webpki-root-certs",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "rustls-platform-verifier-android"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
-
-[[package]]
-name = "rustls-webpki"
-version = "0.103.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
-dependencies = [
- "aws-lc-rs",
- "ring",
- "rustls-pki-types",
- "untrusted",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
-
-[[package]]
-name = "ryu"
-version = "1.0.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "schannel"
-version = "0.1.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
-dependencies = [
- "windows-sys 0.61.2",
-]
-
-[[package]]
-name = "security-framework"
-version = "3.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
-dependencies = [
- "bitflags",
- "core-foundation",
- "core-foundation-sys",
- "libc",
- "security-framework-sys",
-]
-
-[[package]]
-name = "security-framework-sys"
-version = "2.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
-dependencies = [
- "core-foundation-sys",
- "libc",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
-
-[[package]]
-name = "serde"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
-dependencies = [
- "serde_core",
- "serde_derive",
-]
-
-[[package]]
-name = "serde_buf"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a86be9d6c7d34718d2ec6f56c8d6a4671d1a7357c2a6921f47fe5a3ee6056cc"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "serde_core"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.228"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_fmt"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
-dependencies = [
- "itoa",
- "memchr",
- "ryu",
- "serde",
- "serde_core",
-]
-
-[[package]]
-name = "serde_urlencoded"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
-dependencies = [
- "form_urlencoded",
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "sha2"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
-[[package]]
-name = "sharded-slab"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "shlex"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "simd_cesu8"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
-dependencies = [
- "rustc_version",
- "simdutf8",
-]
-
-[[package]]
-name = "simdutf8"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
-
-[[package]]
-name = "slab"
-version = "0.4.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "socket2"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
-name = "strsim"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
-
-[[package]]
-name = "subtle"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
-
-[[package]]
-name = "sval"
-version = "2.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb9efbae90f97301f4d25f3be63dfd99d6b7af9d088228a52ec960d649b2e7d"
-
-[[package]]
-name = "sval_buffer"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0f46e34b20a39e6a2bf02b926983149b3af6609fd1ee8a6e63f6f340f3e2164"
-dependencies = [
- "sval",
- "sval_ref",
-]
-
-[[package]]
-name = "sval_dynamic"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03d0970e53c92ab5381d3b2db1828da8af945954d4234225f6dd9c3afbcef3f5"
-dependencies = [
- "sval",
-]
-
-[[package]]
-name = "sval_fmt"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43e5e6e1613e1e7fc2e1a9fdd709622e54c122ceb067a60d170d75efd491a839"
-dependencies = [
- "itoa",
- "ryu",
- "sval",
-]
-
-[[package]]
-name = "sval_json"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aec382f7bfa6e367b23c9611f129b94eb7daaf3d8fae45a8d0a0211eb4d4c8e6"
-dependencies = [
- "itoa",
- "ryu",
- "sval",
-]
-
-[[package]]
-name = "sval_nested"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3049d0f99ce6297f8f7d9953b35a0103b7584d8f638de40e64edb7105fa578ae"
-dependencies = [
- "sval",
- "sval_buffer",
- "sval_ref",
-]
-
-[[package]]
-name = "sval_ref"
-version = "2.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54ef5ffec8bc52ded04ee424ab8d959e25e64fd40a48a16d21f8991ce824c1bb"
-dependencies = [
- "sval",
-]
-
-[[package]]
-name = "sval_serde"
-version = "2.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f579fd7254f4be6cd7b450034f856b78523404655848789c451bacc6aa8b387d"
-dependencies = [
- "serde_core",
- "sval",
- "sval_nested",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.106"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "sync_wrapper"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
-dependencies = [
- "futures-core",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.23.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
-dependencies = [
- "fastrand",
- "getrandom 0.3.3",
- "once_cell",
- "rustix 1.1.2",
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "test-context"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb69cce03e432993e2dc1f93f7899b952300fcb6dc44191a1b830b60b8c3c8aa"
-dependencies = [
- "futures",
- "test-context-macros",
-]
-
-[[package]]
-name = "test-context-macros"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97e0639209021e54dbe19cafabfc0b5574b078c37358945e6d473eabe39bb974"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thiserror"
-version = "2.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "2.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tiny-keccak"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
-dependencies = [
- "crunchy",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "tinyvec"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
-dependencies = [
- "tinyvec_macros",
-]
-
-[[package]]
-name = "tinyvec_macros"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
-
-[[package]]
-name = "tokio"
-version = "1.50.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
-dependencies = [
- "bytes",
- "libc",
- "mio",
- "pin-project-lite",
- "signal-hook-registry",
- "socket2",
- "tokio-macros",
- "windows-sys 0.61.2",
-]
-
-[[package]]
-name = "tokio-macros"
-version = "2.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tokio-rustls"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
-dependencies = [
- "rustls",
- "tokio",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.7.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
-dependencies = [
- "bytes",
- "futures-core",
- "futures-sink",
- "pin-project-lite",
- "tokio",
-]
-
-[[package]]
-name = "tower"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
-dependencies = [
- "futures-core",
- "futures-util",
- "pin-project-lite",
- "sync_wrapper",
- "tokio",
- "tower-layer",
- "tower-service",
-]
-
-[[package]]
-name = "tower-http"
-version = "0.6.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
-dependencies = [
- "bitflags",
- "bytes",
- "futures-util",
- "http",
- "http-body",
- "pin-project-lite",
- "tower",
- "tower-layer",
- "tower-service",
- "url",
-]
-
-[[package]]
-name = "tower-layer"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
-
-[[package]]
-name = "tower-service"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
-
-[[package]]
-name = "tracing"
-version = "0.1.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
-dependencies = [
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "trait-make"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96cbd06a7b648f1603e60d75d9ed295d096b340d30e9f9324f4b512b5d40cd92"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "try-lock"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
-
-[[package]]
-name = "typeid"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
-
-[[package]]
-name = "typenum"
-version = "1.20.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
-
-[[package]]
-name = "untrusted"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
-
-[[package]]
-name = "url"
-version = "2.5.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "utf8parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
-
-[[package]]
-name = "uuid"
-version = "1.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
-dependencies = [
- "getrandom 0.3.3",
- "js-sys",
- "serde",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "value-bag"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0"
-dependencies = [
- "value-bag-serde1",
- "value-bag-sval2",
-]
-
-[[package]]
-name = "value-bag-serde1"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16530907bfe2999a1773ca5900a65101e092c70f642f25cc23ca0c43573262c5"
-dependencies = [
- "erased-serde",
- "serde_buf",
- "serde_core",
- "serde_fmt",
-]
-
-[[package]]
-name = "value-bag-sval2"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d00ae130edd690eaa877e4f40605d534790d1cf1d651e7685bd6a144521b251f"
-dependencies = [
- "sval",
- "sval_buffer",
- "sval_dynamic",
- "sval_fmt",
- "sval_json",
- "sval_ref",
- "sval_serde",
-]
-
-[[package]]
-name = "walkdir"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
-dependencies = [
- "same-file",
- "winapi-util",
-]
-
-[[package]]
-name = "want"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
-dependencies = [
- "try-lock",
-]
-
-[[package]]
-name = "wasi"
-version = "0.11.1+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
-
-[[package]]
-name = "wasi"
-version = "0.14.7+wasi-0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
-dependencies = [
- "wasip2",
-]
-
-[[package]]
-name = "wasip2"
-version = "1.0.1+wasi-0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
-dependencies = [
- "wit-bindgen 0.46.0",
-]
-
-[[package]]
-name = "wasip3"
-version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
-dependencies = [
- "wit-bindgen 0.51.0",
-]
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.122"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
-dependencies = [
- "cfg-if",
- "once_cell",
- "rustversion",
- "wasm-bindgen-macro",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.72"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.122"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.122"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
-dependencies = [
- "bumpalo",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.122"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "wasm-encoder"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
-dependencies = [
- "leb128fmt",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
-dependencies = [
- "anyhow",
- "indexmap",
- "wasm-encoder",
- "wasmparser",
-]
-
-[[package]]
-name = "wasm-streams"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb"
-dependencies = [
- "futures-util",
- "js-sys",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
-dependencies = [
- "bitflags",
- "hashbrown 0.15.5",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.99"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "web-time"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "webpki-root-certs"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
-dependencies = [
- "rustls-pki-types",
-]
-
-[[package]]
-name = "which"
-version = "6.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f"
-dependencies = [
- "either",
- "home",
- "rustix 0.38.44",
- "winsafe",
-]
-
-[[package]]
-name = "winapi-util"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
-name = "windows-link"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
-
-[[package]]
-name = "windows-sys"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.60.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
-dependencies = [
- "windows-targets 0.53.5",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.61.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
-dependencies = [
- "windows-link",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
- "windows_i686_gnullvm 0.52.6",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.53.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
-dependencies = [
- "windows-link",
- "windows_aarch64_gnullvm 0.53.1",
- "windows_aarch64_msvc 0.53.1",
- "windows_i686_gnu 0.53.1",
- "windows_i686_gnullvm 0.53.1",
- "windows_i686_msvc 0.53.1",
- "windows_x86_64_gnu 0.53.1",
- "windows_x86_64_gnullvm 0.53.1",
- "windows_x86_64_msvc 0.53.1",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.53.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
-
-[[package]]
-name = "winsafe"
-version = "0.0.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
-
-[[package]]
-name = "wit-bindgen"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
-
-[[package]]
-name = "wit-bindgen"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
-dependencies = [
- "wit-bindgen-rust-macro",
-]
-
-[[package]]
-name = "wit-bindgen-core"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
-dependencies = [
- "anyhow",
- "bitflags",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser",
- "wit-parser",
-]
-
-[[package]]
-name = "wit-parser"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
-dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
- "log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
-
-[[package]]
-name = "xattr"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
-dependencies = [
- "libc",
- "rustix 1.1.2",
-]
-
-[[package]]
-name = "yoke"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
-
-[[package]]
-name = "zerotrie"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+name = "ofs"
+version = "0.0.24"
diff --git a/Cargo.toml b/Cargo.toml
index f746582..64137d7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,8 +17,8 @@
[package]
categories = ["filesystem"]
-description = "OpenDAL File System"
-keywords = ["storage", "data", "s3", "fs", "azblob"]
+description = "Apache OpenDAL File System"
+keywords = ["storage", "filesystem"]
name = "ofs"
version = "0.0.24"
@@ -26,37 +26,23 @@ authors = ["Apache OpenDAL <de...@opendal.apache.org>"]
edition = "2024"
homepage = "https://opendal.apache.org/"
license = "Apache-2.0"
-repository = "https://github.com/apache/opendal"
+publish = false
+repository = "https://github.com/apache/opendal-ofs"
rust-version = "1.85"
-[dependencies]
-anyhow = { version = "1" }
-clap = { version = "4.5.40", features = ["derive", "env"] }
-log = { version = "0.4.22" }
-logforth = { version = "0.28.1", features = ["starter-log"] }
-opendal = { version = "0.57.0" }
-tokio = { version = "1.47.0", features = [
- "fs",
- "macros",
- "rt-multi-thread",
- "io-std",
- "signal",
-] }
-url = { version = "2.5.4" }
+[workspace]
+members = ["."]
+resolver = "3"
-[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))'.dependencies]
-fuse3 = { version = "0.8.1", "features" = ["tokio-runtime", "unprivileged"] }
-fuse3_opendal = { version = "0.0.19", path = "integrations/fuse3" }
-libc = "0.2.154"
-nix = { version = "0.30.1", features = ["user"] }
+[workspace.lints.rust]
+unknown_lints = "deny"
+unsafe_code = "deny"
+unused_must_use = "deny"
-[features]
-default = ["services-fs", "services-s3"]
-services-fs = ["opendal/services-fs"]
-services-s3 = ["opendal/services-s3"]
+[workspace.lints.clippy]
+dbg_macro = "deny"
+too_many_arguments = "allow"
+type_complexity = "allow"
-[dev-dependencies]
-opendal = { version = "0.57.0", features = ["tests"] }
-tempfile = "3.23.0"
-test-context = "0.4.1"
-walkdir = "2.5.0"
+[lints]
+workspace = true
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
deleted file mode 100644
index 249686f..0000000
--- a/DEPENDENCIES.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Dependencies
-
-Refer to [DEPENDENCIES.rust.tsv](DEPENDENCIES.rust.tsv) for full list.
diff --git a/DEPENDENCIES.rust.tsv b/DEPENDENCIES.rust.tsv
deleted file mode 100644
index 518e264..0000000
--- a/DEPENDENCIES.rust.tsv
+++ /dev/null
@@ -1,233 +0,0 @@
-crate 0BSD Apache-2.0 Apache-2.0 WITH LLVM-exception BSD-2-Clause BSD-3-Clause BSL-1.0 CDLA-Permissive-2.0 ISC LGPL-2.1-or-later MIT Unicode-3.0 Unlicense Zlib
-addr2line@0.24.2 X X
-adler2@2.0.0 X X X
-aho-corasick@1.1.3 X X
-android-tzdata@0.1.1 X X
-android_system_properties@0.1.5 X X
-anstream@0.6.18 X X
-anstyle@1.0.10 X X
-anstyle-parse@0.2.6 X X
-anstyle-query@1.1.2 X X
-anstyle-wincon@3.0.7 X X
-anyhow@1.0.98 X X
-async-notify@0.3.0 X
-async-trait@0.1.88 X X
-autocfg@1.4.0 X X
-backon@1.5.0 X
-backtrace@0.3.75 X X
-base64@0.22.1 X X
-bincode@1.3.3 X
-bitflags@2.9.1 X X
-block-buffer@0.10.4 X X
-bumpalo@3.17.0 X X
-bytes@1.10.1 X
-cc@1.2.23 X X
-cfg-if@1.0.0 X X
-cfg_aliases@0.2.1 X
-clap@4.5.40 X X
-clap_builder@4.5.40 X X
-clap_derive@4.5.40 X X
-clap_lex@0.7.4 X X
-colorchoice@1.0.3 X X
-concurrent-queue@2.5.0 X X
-const-oid@0.9.6 X X
-core-foundation-sys@0.8.7 X X
-cpufeatures@0.2.17 X X
-crc32c@0.6.8 X X
-crossbeam-utils@0.8.21 X X
-crypto-common@0.1.6 X X
-digest@0.10.7 X X
-displaydoc@0.2.5 X X
-dotenvy@0.15.7 X
-either@1.15.0 X X
-env_filter@0.1.3 X X
-errno@0.3.12 X X
-event-listener@4.0.3 X X
-fastrand@2.3.0 X X
-fnv@1.0.7 X X
-form_urlencoded@1.2.1 X X
-fuse3@0.8.1 X
-fuse3_opendal@0.0.19 X
-futures@0.3.31 X X
-futures-channel@0.3.31 X X
-futures-core@0.3.31 X X
-futures-executor@0.3.31 X X
-futures-io@0.3.31 X X
-futures-macro@0.3.31 X X
-futures-sink@0.3.31 X X
-futures-task@0.3.31 X X
-futures-util@0.3.31 X X
-generic-array@0.14.7 X
-getrandom@0.2.16 X X
-getrandom@0.3.3 X X
-gimli@0.31.1 X X
-gloo-timers@0.3.0 X X
-heck@0.5.0 X X
-hex@0.4.3 X X
-hmac@0.12.1 X X
-home@0.5.11 X X
-http@1.3.1 X X
-http-body@1.0.1 X
-http-body-util@0.1.3 X
-httparse@1.10.1 X X
-hyper@1.6.0 X
-hyper-rustls@0.27.5 X X X
-hyper-util@0.1.12 X
-iana-time-zone@0.1.63 X X
-iana-time-zone-haiku@0.1.2 X X
-icu_collections@2.0.0 X
-icu_locale_core@2.0.0 X
-icu_normalizer@2.0.0 X
-icu_normalizer_data@2.0.0 X
-icu_properties@2.0.1 X
-icu_properties_data@2.0.1 X
-icu_provider@2.0.0 X
-idna@1.0.3 X X
-idna_adapter@1.2.1 X X
-io-uring@0.7.8 X X
-ipnet@2.11.0 X X
-iri-string@0.7.8 X X
-is_terminal_polyfill@1.70.1 X X
-itoa@1.0.15 X X
-jiff@0.2.14 X X
-jiff-tzdb@0.1.4 X X
-jiff-tzdb-platform@0.1.3 X X
-js-sys@0.3.77 X X
-lazy_static@1.5.0 X X
-libc@0.2.172 X X
-linux-raw-sys@0.4.15 X X X
-litemap@0.8.0 X
-log@0.4.27 X X
-logforth@0.27.0 X
-md-5@0.10.6 X X
-memchr@2.7.4 X X
-memoffset@0.9.1 X
-miniz_oxide@0.8.8 X X X
-mio@1.0.3 X
-nix@0.29.0 X
-nix@0.30.1 X
-object@0.36.7 X X
-ofs@0.0.24 X
-once_cell@1.21.3 X X
-opendal@0.54.1 X
-parking@2.2.1 X X
-percent-encoding@2.3.1 X X
-pin-project-lite@0.2.16 X X
-pin-utils@0.1.0 X X
-portable-atomic@1.11.0 X X
-portable-atomic-util@0.2.4 X X
-potential_utf@0.1.2 X
-ppv-lite86@0.2.21 X X
-proc-macro2@1.0.95 X X
-quick-xml@0.37.5 X
-quick-xml@0.38.0 X
-quote@1.0.40 X X
-r-efi@5.2.0 X X X
-rand@0.8.5 X X
-rand_chacha@0.3.1 X X
-rand_core@0.6.4 X X
-regex@1.11.1 X X
-regex-automata@0.4.9 X X
-regex-syntax@0.8.5 X X
-reqsign@0.16.5 X
-reqwest@0.12.22 X X
-ring@0.17.14 X X
-rustc-demangle@0.1.24 X X
-rustc_version@0.4.1 X X
-rustix@0.38.44 X X X
-rustls@0.23.27 X X X
-rustls-pki-types@1.12.0 X X
-rustls-webpki@0.103.3 X
-rustversion@1.0.20 X X
-ryu@1.0.20 X X
-semver@1.0.26 X X
-serde@1.0.219 X X
-serde_derive@1.0.219 X X
-serde_json@1.0.140 X X
-serde_urlencoded@0.7.1 X X
-sha1@0.10.6 X X
-sha2@0.10.9 X X
-sharded-slab@0.1.7 X
-shlex@1.3.0 X X
-signal-hook-registry@1.4.5 X X
-slab@0.4.9 X
-smallvec@1.15.0 X X
-socket2@0.5.9 X X
-socket2@0.6.0 X X
-stable_deref_trait@1.2.0 X X
-strsim@0.11.1 X
-subtle@2.6.1 X
-syn@2.0.101 X X
-sync_wrapper@1.0.2 X
-synstructure@0.13.2 X
-tinystr@0.8.1 X
-tokio@1.47.0 X
-tokio-macros@2.5.0 X
-tokio-rustls@0.26.2 X X
-tokio-util@0.7.15 X
-tower@0.5.2 X
-tower-http@0.6.6 X
-tower-layer@0.3.3 X
-tower-service@0.3.3 X
-tracing@0.1.41 X
-tracing-attributes@0.1.28 X
-tracing-core@0.1.33 X
-trait-make@0.1.0 X X
-try-lock@0.2.5 X
-typenum@1.18.0 X X
-unicode-ident@1.0.18 X X X
-untrusted@0.9.0 X
-url@2.5.4 X X
-utf8_iter@1.0.4 X X
-utf8parse@0.2.2 X X
-uuid@1.17.0 X X
-version_check@0.9.5 X X
-want@0.3.1 X
-wasi@0.11.0+wasi-snapshot-preview1 X X X
-wasi@0.14.2+wasi-0.2.4 X X X
-wasm-bindgen@0.2.100 X X
-wasm-bindgen-backend@0.2.100 X X
-wasm-bindgen-futures@0.4.50 X X
-wasm-bindgen-macro@0.2.100 X X
-wasm-bindgen-macro-support@0.2.100 X X
-wasm-bindgen-shared@0.2.100 X X
-wasm-streams@0.4.2 X X
-web-sys@0.3.77 X X
-webpki-roots@0.26.11 X
-webpki-roots@1.0.0 X
-which@6.0.3 X
-windows-link@0.2.1 X X
-windows-sys@0.52.0 X X
-windows-sys@0.59.0 X X
-windows-sys@0.60.2 X X
-windows-sys@0.61.2 X X
-windows-targets@0.52.6 X X
-windows-targets@0.53.5 X X
-windows_aarch64_gnullvm@0.52.6 X X
-windows_aarch64_gnullvm@0.53.1 X X
-windows_aarch64_msvc@0.52.6 X X
-windows_aarch64_msvc@0.53.1 X X
-windows_i686_gnu@0.52.6 X X
-windows_i686_gnu@0.53.1 X X
-windows_i686_gnullvm@0.52.6 X X
-windows_i686_gnullvm@0.53.1 X X
-windows_i686_msvc@0.52.6 X X
-windows_i686_msvc@0.53.1 X X
-windows_x86_64_gnu@0.52.6 X X
-windows_x86_64_gnu@0.53.1 X X
-windows_x86_64_gnullvm@0.52.6 X X
-windows_x86_64_gnullvm@0.53.1 X X
-windows_x86_64_msvc@0.52.6 X X
-windows_x86_64_msvc@0.53.1 X X
-winsafe@0.0.19 X
-wit-bindgen-rt@0.39.0 X X X
-writeable@0.6.1 X
-yoke@0.8.0 X
-yoke-derive@0.8.0 X
-zerocopy@0.8.25 X X X
-zerofrom@0.1.6 X
-zerofrom-derive@0.1.6 X
-zeroize@1.8.1 X X
-zerotrie@0.2.2 X
-zerovec@0.11.2 X
-zerovec-derive@0.11.1 X
diff --git a/README.md b/README.md
index 397116f..199cceb 100644
--- a/README.md
+++ b/README.md
@@ -1,66 +1,45 @@
-# Apache OpenDAL™ ofs
+# Apache OpenDAL™ File System
-[![Build Status]][actions] [![Latest Version]][crates.io] [![Crate Downloads]][crates.io] [![chat]][discord]
+[![Build Status]][actions]
[build status]: https://img.shields.io/github/actions/workflow/status/apache/opendal-ofs/ci.yml?branch=main
[actions]: https://github.com/apache/opendal-ofs/actions?query=branch%3Amain
-[latest version]: https://img.shields.io/crates/v/ofs.svg
-[crates.io]: https://crates.io/crates/ofs
-[crate downloads]: https://img.shields.io/crates/d/ofs.svg
-[chat]: https://img.shields.io/discord/1081052318650339399
-[discord]: https://opendal.apache.org/discord
-`ofs` is a userspace filesystem backing by OpenDAL.
+`ofs` is the Apache OpenDAL filesystem project.
## Status
-`ofs` is a work in progress. we only support `fs` and `s3` as backend on `Linux` currently.
+The previous OpenDAL-to-FUSE Direct Mount implementation has been removed. It
+predated the filesystem contracts in [RFC-0016] and did not implement their
+required staging, conflict, naming, durability, or capability semantics.
-## How to use `ofs`
+The runtime is being redesigned. There is currently no supported `ofs` mount
+command or published runtime API. The crate remains unpublished until the new
+contracts are ready for implementation.
-### Install `FUSE` on Linux
+[rfc-0016]: rfcs/0016_filesystem_architecture.md
-```shell
-sudo pacman -S fuse3 --noconfirm # archlinux
-sudo apt-get -y install fuse3 # debian/ubuntu
-```
-
-### Load `FUSE` kernel module on FreeBSD
-
-```shell
-kldload fuse
-```
-
-### Install `ofs`
-
-`ofs` could be installed by `cargo`:
-
-```shell
-cargo install ofs
-```
-
-> `cargo` is the Rust package manager. `cargo` could be installed by following the [Installation](https://www.rust-lang.org/tools/install) from Rust official website.
-
-### Mount directory
-
-```shell
-ofs <mount-point> 'fs://?root=<directory>'
-```
+## Development
-### Mount S3 bucket
+The repository currently provides a minimal, buildable Rust project for the
+redesign work:
```shell
-ofs <mount-point> 's3://?root=<path>&bucket=<bucket>&endpoint=<endpoint>®ion=<region>&access_key_id=<access-key-id>&secret_access_key=<secret-access-key>'
+cargo fmt --all --check
+cargo clippy --all-targets -- -D warnings
+cargo test --all-targets
```
## Branding
-The first and most prominent mentions must use the full form: **Apache OpenDAL™** of the name for any individual usage (webpage, handout, slides, etc.) Depending on the context and writing style, you should use the full form of the name sufficiently often to ensure that readers clearly understand the association of both the OpenDAL project and the OpenDAL software product to the ASF as the parent organization.
+The first and most prominent mentions must use the full form: **Apache
+OpenDAL™**. For more details, see the [Apache Product Name Usage Guide].
-For more details, see the [Apache Product Name Usage Guide](https://www.apache.org/foundation/marks/guide).
+[apache product name usage guide]: https://www.apache.org/foundation/marks/guide
## License and Trademarks
-Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
+Licensed under the Apache License, Version 2.0.
-Apache OpenDAL, OpenDAL, and Apache are either registered trademarks or trademarks of the Apache Software Foundation.
+Apache OpenDAL, OpenDAL, and Apache are either registered trademarks or
+trademarks of the Apache Software Foundation.
diff --git a/integrations/fuse3/.gitignore b/integrations/fuse3/.gitignore
deleted file mode 100644
index 03314f7..0000000
--- a/integrations/fuse3/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-Cargo.lock
diff --git a/integrations/fuse3/Cargo.toml b/integrations/fuse3/Cargo.toml
deleted file mode 100644
index 245aa61..0000000
--- a/integrations/fuse3/Cargo.toml
+++ /dev/null
@@ -1,40 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-[package]
-description = "fuse3 integration for Apache OpenDAL"
-name = "fuse3_opendal"
-
-authors = ["Apache OpenDAL <de...@opendal.apache.org>"]
-edition = "2024"
-homepage = "https://opendal.apache.org/"
-license = "Apache-2.0"
-repository = "https://github.com/apache/opendal"
-rust-version = "1.85"
-version = "0.0.19"
-
-[dependencies]
-bytes = "1.6.0"
-fuse3 = { version = "0.8.1", "features" = ["tokio-runtime", "unprivileged"] }
-futures-util = "0.3.30"
-libc = "0.2.155"
-log = "0.4.21"
-opendal = { version = "0.57.0" }
-sharded-slab = "0.1.7"
-tokio = "1.38.0"
-
-[dev-dependencies]
diff --git a/integrations/fuse3/DEPENDENCIES.rust.tsv b/integrations/fuse3/DEPENDENCIES.rust.tsv
deleted file mode 100644
index 1067d5a..0000000
--- a/integrations/fuse3/DEPENDENCIES.rust.tsv
+++ /dev/null
@@ -1,192 +0,0 @@
-crate 0BSD Apache-2.0 Apache-2.0 WITH LLVM-exception BSD-3-Clause BSL-1.0 CDLA-Permissive-2.0 ISC LGPL-2.1-or-later MIT Unicode-3.0 Unlicense Zlib
-addr2line@0.24.2 X X
-adler2@2.0.1 X X X
-android-tzdata@0.1.1 X X
-android_system_properties@0.1.5 X X
-anyhow@1.0.98 X X
-async-notify@0.3.0 X
-autocfg@1.5.0 X X
-backon@1.5.1 X
-backtrace@0.3.75 X X
-base64@0.22.1 X X
-bincode@1.3.3 X
-bitflags@2.9.1 X X
-block-buffer@0.10.4 X X
-bumpalo@3.19.0 X X
-bytes@1.10.1 X
-cc@1.2.29 X X
-cfg-if@1.0.1 X X
-cfg_aliases@0.2.1 X
-chrono@0.4.41 X X
-concurrent-queue@2.5.0 X X
-core-foundation-sys@0.8.7 X X
-crossbeam-utils@0.8.21 X X
-crypto-common@0.1.6 X X
-digest@0.10.7 X X
-displaydoc@0.2.5 X X
-either@1.15.0 X X
-errno@0.3.13 X X
-event-listener@4.0.3 X X
-fastrand@2.3.0 X X
-fnv@1.0.7 X X
-form_urlencoded@1.2.1 X X
-fuse3@0.8.1 X
-fuse3_opendal@0.0.19 X
-futures@0.3.31 X X
-futures-channel@0.3.31 X X
-futures-core@0.3.31 X X
-futures-io@0.3.31 X X
-futures-macro@0.3.31 X X
-futures-sink@0.3.31 X X
-futures-task@0.3.31 X X
-futures-util@0.3.31 X X
-generic-array@0.14.7 X
-getrandom@0.2.16 X X
-getrandom@0.3.3 X X
-gimli@0.31.1 X X
-gloo-timers@0.3.0 X X
-home@0.5.11 X X
-http@1.3.1 X X
-http-body@1.0.1 X
-http-body-util@0.1.3 X
-httparse@1.10.1 X X
-hyper@1.6.0 X
-hyper-rustls@0.27.7 X X X
-hyper-util@0.1.15 X
-iana-time-zone@0.1.63 X X
-iana-time-zone-haiku@0.1.2 X X
-icu_collections@2.0.0 X
-icu_locale_core@2.0.0 X
-icu_normalizer@2.0.0 X
-icu_normalizer_data@2.0.0 X
-icu_properties@2.0.1 X
-icu_properties_data@2.0.1 X
-icu_provider@2.0.0 X
-idna@1.0.3 X X
-idna_adapter@1.2.1 X X
-io-uring@0.7.8 X X
-ipnet@2.11.0 X X
-iri-string@0.7.8 X X
-itoa@1.0.15 X X
-js-sys@0.3.77 X X
-lazy_static@1.5.0 X X
-libc@0.2.174 X X
-linux-raw-sys@0.4.15 X X X
-litemap@0.8.0 X
-log@0.4.27 X X
-md-5@0.10.6 X X
-memchr@2.7.5 X X
-memoffset@0.9.1 X
-miniz_oxide@0.8.9 X X X
-mio@1.0.4 X
-nix@0.29.0 X
-num-traits@0.2.19 X X
-object@0.36.7 X X
-once_cell@1.21.3 X X
-opendal@0.54.1 X
-parking@2.2.1 X X
-percent-encoding@2.3.1 X X
-pin-project-lite@0.2.16 X X
-pin-utils@0.1.0 X X
-potential_utf@0.1.2 X
-proc-macro2@1.0.95 X X
-quick-xml@0.38.3 X
-quote@1.0.40 X X
-r-efi@5.3.0 X X X
-reqwest@0.12.22 X X
-ring@0.17.14 X X
-rustc-demangle@0.1.25 X X
-rustix@0.38.44 X X X
-rustls@0.23.29 X X X
-rustls-pki-types@1.12.0 X X
-rustls-webpki@0.103.4 X
-rustversion@1.0.21 X X
-ryu@1.0.20 X X
-serde@1.0.219 X X
-serde_derive@1.0.219 X X
-serde_json@1.0.140 X X
-serde_urlencoded@0.7.1 X X
-sharded-slab@0.1.7 X
-shlex@1.3.0 X X
-signal-hook-registry@1.4.5 X X
-slab@0.4.10 X
-smallvec@1.15.1 X X
-socket2@0.5.10 X X
-socket2@0.6.0 X X
-stable_deref_trait@1.2.0 X X
-subtle@2.6.1 X
-syn@2.0.104 X X
-sync_wrapper@1.0.2 X
-synstructure@0.13.2 X
-tinystr@0.8.1 X
-tokio@1.47.1 X
-tokio-macros@2.5.0 X
-tokio-rustls@0.26.2 X X
-tokio-util@0.7.15 X
-tower@0.5.2 X
-tower-http@0.6.6 X
-tower-layer@0.3.3 X
-tower-service@0.3.3 X
-tracing@0.1.41 X
-tracing-attributes@0.1.30 X
-tracing-core@0.1.34 X
-trait-make@0.1.0 X X
-try-lock@0.2.5 X
-typenum@1.18.0 X X
-unicode-ident@1.0.18 X X X
-untrusted@0.9.0 X
-url@2.5.4 X X
-utf8_iter@1.0.4 X X
-uuid@1.17.0 X X
-version_check@0.9.5 X X
-want@0.3.1 X
-wasi@0.11.1+wasi-snapshot-preview1 X X X
-wasi@0.14.2+wasi-0.2.4 X X X
-wasm-bindgen@0.2.100 X X
-wasm-bindgen-backend@0.2.100 X X
-wasm-bindgen-futures@0.4.50 X X
-wasm-bindgen-macro@0.2.100 X X
-wasm-bindgen-macro-support@0.2.100 X X
-wasm-bindgen-shared@0.2.100 X X
-wasm-streams@0.4.2 X X
-web-sys@0.3.77 X X
-webpki-roots@1.0.1 X
-which@6.0.3 X
-windows-core@0.61.2 X X
-windows-implement@0.60.0 X X
-windows-interface@0.59.1 X X
-windows-link@0.1.3 X X
-windows-result@0.3.4 X X
-windows-strings@0.4.2 X X
-windows-sys@0.52.0 X X
-windows-sys@0.59.0 X X
-windows-sys@0.60.2 X X
-windows-targets@0.52.6 X X
-windows-targets@0.53.2 X X
-windows_aarch64_gnullvm@0.52.6 X X
-windows_aarch64_gnullvm@0.53.0 X X
-windows_aarch64_msvc@0.52.6 X X
-windows_aarch64_msvc@0.53.0 X X
-windows_i686_gnu@0.52.6 X X
-windows_i686_gnu@0.53.0 X X
-windows_i686_gnullvm@0.52.6 X X
-windows_i686_gnullvm@0.53.0 X X
-windows_i686_msvc@0.52.6 X X
-windows_i686_msvc@0.53.0 X X
-windows_x86_64_gnu@0.52.6 X X
-windows_x86_64_gnu@0.53.0 X X
-windows_x86_64_gnullvm@0.52.6 X X
-windows_x86_64_gnullvm@0.53.0 X X
-windows_x86_64_msvc@0.52.6 X X
-windows_x86_64_msvc@0.53.0 X X
-winsafe@0.0.19 X
-wit-bindgen-rt@0.39.0 X X X
-writeable@0.6.1 X
-yoke@0.8.0 X
-yoke-derive@0.8.0 X
-zerofrom@0.1.6 X
-zerofrom-derive@0.1.6 X
-zeroize@1.8.1 X X
-zerotrie@0.2.2 X
-zerovec@0.11.2 X
-zerovec-derive@0.11.1 X
diff --git a/integrations/fuse3/README.md b/integrations/fuse3/README.md
deleted file mode 100644
index e4e25a2..0000000
--- a/integrations/fuse3/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# Apache OpenDAL™ fuse3 integration
-
-[![Build Status]][actions] [![Latest Version]][crates.io] [![Crate Downloads]][crates.io] [![chat]][discord]
-
-[build status]: https://img.shields.io/github/actions/workflow/status/apache/opendal/ci_integration_fuse3.yml?branch=main
-[actions]: https://github.com/apache/opendal/actions?query=branch%3Amain
-[latest version]: https://img.shields.io/crates/v/fuse3_opendal.svg
-[crates.io]: https://crates.io/crates/fuse3_opendal
-[crate downloads]: https://img.shields.io/crates/d/fuse3_opendal.svg
-[chat]: https://img.shields.io/discord/1081052318650339399
-[discord]: https://opendal.apache.org/discord
-
-`fuse3_opendal` is an [`fuse3`](https://github.com/Sherlock-Holo/fuse3) implementation using opendal.
-
-This crate can help you to access ANY storage services by mounting locally by [`FUSE`](https://www.kernel.org/doc/html/next/filesystems/fuse.html).
-
-## Useful Links
-
-- Documentation: [release](https://docs.rs/fuse3_opendal/) | [dev](https://opendal.apache.org/docs/fuse3-opendal/fuse3_opendal/)
-
-## Examples
-
-```rust
-use fuse3::path::Session;
-use fuse3::MountOptions;
-use fuse3::Result;
-use fuse3_opendal::Filesystem;
-use opendal::services::Memory;
-use opendal::Operator;
-
-#[tokio::test]
-async fn test() -> Result<()> {
- // Build opendal Operator.
- let op = Operator::new(Memory::default())?.finish();
-
- // Build fuse3 file system.
- let fs = Filesystem::new(op, 1000, 1000);
-
- // Configure mount options.
- let mount_options = MountOptions::default();
-
- // Start a fuse3 session and mount it.
- let mut mount_handle = Session::new(mount_options)
- .mount_with_unprivileged(fs, "/tmp/mount_test")
- .await?;
- let handle = &mut mount_handle;
-
- tokio::select! {
- res = handle => res?,
- _ = tokio::signal::ctrl_c() => {
- mount_handle.unmount().await?
- }
- }
-
- Ok(())
-}
-```
-
-## Branding
-
-The first and most prominent mentions must use the full form: **Apache OpenDAL™** of the name for any individual usage (webpage, handout, slides, etc.) Depending on the context and writing style, you should use the full form of the name sufficiently often to ensure that readers clearly understand the association of both the OpenDAL project and the OpenDAL software product to the ASF as the parent organization.
-
-For more details, see the [Apache Product Name Usage Guide](https://www.apache.org/foundation/marks/guide).
-
-## License and Trademarks
-
-Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
-
-Apache OpenDAL, OpenDAL, and Apache are either registered trademarks or trademarks of the Apache Software Foundation.
diff --git a/integrations/fuse3/src/file.rs b/integrations/fuse3/src/file.rs
deleted file mode 100644
index 58a1780..0000000
--- a/integrations/fuse3/src/file.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::ffi::OsString;
-use std::sync::Arc;
-
-use fuse3::Errno;
-use opendal::Writer;
-use tokio::sync::Mutex;
-
-/// Opened file represents file that opened in memory.
-///
-/// # FIXME
-///
-/// We should remove the `pub` filed to avoid unexpected changes.
-pub struct OpenedFile {
- pub path: OsString,
- pub is_read: bool,
- pub inner_writer: Option<Arc<Mutex<InnerWriter>>>,
-}
-
-/// # FIXME
-///
-/// We need better naming and API for this struct.
-pub struct InnerWriter {
- pub writer: Option<Writer>,
- pub written: u64,
-}
-
-/// File key is the key of opened file.
-///
-/// # FIXME
-///
-/// We should remove the `pub` filed to avoid unexpected changes.
-#[derive(Debug, Clone, Copy)]
-pub struct FileKey(pub usize);
-
-impl TryFrom<u64> for FileKey {
- type Error = Errno;
-
- fn try_from(value: u64) -> std::result::Result<Self, Self::Error> {
- match value {
- 0 => Err(Errno::from(libc::EBADF)),
- _ => Ok(FileKey(value as usize - 1)),
- }
- }
-}
-
-impl FileKey {
- pub fn to_fh(self) -> u64 {
- self.0 as u64 + 1 // ensure fh is not 0
- }
-}
diff --git a/integrations/fuse3/src/file_system.rs b/integrations/fuse3/src/file_system.rs
deleted file mode 100644
index 7419f2a..0000000
--- a/integrations/fuse3/src/file_system.rs
+++ /dev/null
@@ -1,836 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::ffi::OsStr;
-use std::num::NonZeroU32;
-use std::path::PathBuf;
-use std::sync::Arc;
-use std::time::Duration;
-use std::time::SystemTime;
-
-use bytes::Bytes;
-use fuse3::Errno;
-use fuse3::Result;
-use fuse3::path::prelude::*;
-use futures_util::StreamExt;
-use futures_util::stream;
-use futures_util::stream::BoxStream;
-use opendal::EntryMode;
-use opendal::ErrorKind;
-use opendal::Metadata;
-use opendal::Operator;
-use opendal::raw::normalize_path;
-use sharded_slab::Slab;
-use tokio::sync::Mutex;
-
-use super::file::FileKey;
-use super::file::InnerWriter;
-use super::file::OpenedFile;
-
-const TTL: Duration = Duration::from_secs(1); // 1 second
-
-/// `Filesystem` represents the filesystem that implements [`PathFilesystem`] by opendal.
-///
-/// `Filesystem` must be used along with `fuse3`'s `Session` like the following:
-///
-/// ```
-/// use fuse3::path::Session;
-/// use fuse3::MountOptions;
-/// use fuse3::Result;
-/// use fuse3_opendal::Filesystem;
-/// use opendal::services::Memory;
-/// use opendal::Operator;
-///
-/// #[tokio::test]
-/// async fn test() -> Result<()> {
-/// // Build opendal Operator.
-/// let op = Operator::new(Memory::default())?.finish();
-///
-/// // Build fuse3 file system.
-/// let fs = Filesystem::new(op, 1000, 1000);
-///
-/// // Configure mount options.
-/// let mount_options = MountOptions::default();
-///
-/// // Start a fuse3 session and mount it.
-/// let mut mount_handle = Session::new(mount_options)
-/// .mount_with_unprivileged(fs, "/tmp/mount_test")
-/// .await?;
-/// let handle = &mut mount_handle;
-///
-/// tokio::select! {
-/// res = handle => res?,
-/// _ = tokio::signal::ctrl_c() => {
-/// mount_handle.unmount().await?
-/// }
-/// }
-///
-/// Ok(())
-/// }
-/// ```
-pub struct Filesystem {
- op: Operator,
- gid: u32,
- uid: u32,
-
- opened_files: Slab<OpenedFile>,
-}
-
-impl Filesystem {
- /// Create a new filesystem with given operator, uid and gid.
- pub fn new(op: Operator, uid: u32, gid: u32) -> Self {
- Self {
- op,
- uid,
- gid,
- opened_files: Slab::new(),
- }
- }
-
- fn check_flags(&self, flags: u32) -> Result<(bool, bool, bool)> {
- let is_trunc = flags & libc::O_TRUNC as u32 != 0 || flags & libc::O_CREAT as u32 != 0;
- let is_append = flags & libc::O_APPEND as u32 != 0;
-
- let mode = flags & libc::O_ACCMODE as u32;
- let is_read = mode == libc::O_RDONLY as u32 || mode == libc::O_RDWR as u32;
- let is_write = mode == libc::O_WRONLY as u32 || mode == libc::O_RDWR as u32 || is_append;
- if !is_read && !is_write {
- Err(Errno::from(libc::EINVAL))?;
- }
- // OpenDAL only supports truncate write and append write,
- // so O_TRUNC or O_APPEND needs to be specified explicitly
- if (is_write && !is_trunc && !is_append) || is_trunc && !is_write {
- Err(Errno::from(libc::EINVAL))?;
- }
-
- let capability = self.op.info().full_capability();
- if is_read && !capability.read {
- Err(Errno::from(libc::EACCES))?;
- }
- if is_trunc && !capability.write {
- Err(Errno::from(libc::EACCES))?;
- }
- if is_append && !capability.write_can_append {
- Err(Errno::from(libc::EACCES))?;
- }
-
- log::trace!(
- "check_flags: is_read={is_read}, is_write={is_write}, is_trunc={is_trunc}, is_append={is_append}"
- );
- Ok((is_read, is_trunc, is_append))
- }
-
- // Get opened file and check given path
- fn get_opened_file(
- &self,
- key: FileKey,
- path: Option<&OsStr>,
- ) -> Result<sharded_slab::Entry<'_, OpenedFile>> {
- let file = self
- .opened_files
- .get(key.0)
- .ok_or(Errno::from(libc::ENOENT))?;
-
- if matches!(path, Some(path) if path != file.path) {
- log::trace!(
- "get_opened_file: path not match: path={:?}, file={:?}",
- path,
- file.path
- );
- Err(Errno::from(libc::EBADF))?;
- }
-
- Ok(file)
- }
-
- async fn finish_writer(inner_writer: Option<Arc<Mutex<InnerWriter>>>) -> Result<()> {
- if let Some(inner_writer) = inner_writer {
- let mut inner = inner_writer.lock().await;
- if let Some(mut writer) = inner.writer.take() {
- writer.close().await.map_err(opendal_error2errno)?;
- }
- }
-
- Ok(())
- }
-}
-
-impl PathFilesystem for Filesystem {
- // Init a fuse filesystem
- async fn init(&self, _req: Request) -> Result<ReplyInit> {
- Ok(ReplyInit {
- max_write: NonZeroU32::new(16 * 1024).unwrap(),
- })
- }
-
- // Callback when fs is being destroyed
- async fn destroy(&self, _req: Request) {}
-
- async fn lookup(&self, _req: Request, parent: &OsStr, name: &OsStr) -> Result<ReplyEntry> {
- log::debug!("lookup(parent={parent:?}, name={name:?})");
-
- let path = PathBuf::from(parent).join(name);
- let metadata = self
- .op
- .stat(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- let now = SystemTime::now();
- let attr = metadata2file_attr(&metadata, now, self.uid, self.gid);
-
- Ok(ReplyEntry { ttl: TTL, attr })
- }
-
- async fn getattr(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: Option<u64>,
- flags: u32,
- ) -> Result<ReplyAttr> {
- log::debug!("getattr(path={path:?}, fh={fh:?}, flags={flags:?})");
-
- let fh_path = fh.and_then(|fh| {
- self.opened_files
- .get(FileKey::try_from(fh).ok()?.0)
- .map(|f| f.path.clone())
- });
-
- let file_path = match (path.map(Into::into), fh_path) {
- (Some(a), Some(b)) => {
- if a != b {
- Err(Errno::from(libc::EBADF))?;
- }
- Some(a)
- }
- (a, b) => a.or(b),
- };
-
- let metadata = self
- .op
- .stat(&file_path.unwrap_or_default().to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- let now = SystemTime::now();
- let attr = metadata2file_attr(&metadata, now, self.uid, self.gid);
-
- Ok(ReplyAttr { ttl: TTL, attr })
- }
-
- async fn setattr(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: Option<u64>,
- set_attr: SetAttr,
- ) -> Result<ReplyAttr> {
- log::debug!("setattr(path={path:?}, fh={fh:?}, set_attr={set_attr:?})");
-
- self.getattr(_req, path, fh, 0).await
- }
-
- async fn symlink(
- &self,
- _req: Request,
- parent: &OsStr,
- name: &OsStr,
- link_path: &OsStr,
- ) -> Result<ReplyEntry> {
- log::debug!("symlink(parent={parent:?}, name={name:?}, link_path={link_path:?})");
- Err(libc::EOPNOTSUPP.into())
- }
-
- async fn mknod(
- &self,
- _req: Request,
- parent: &OsStr,
- name: &OsStr,
- mode: u32,
- _rdev: u32,
- ) -> Result<ReplyEntry> {
- log::debug!("mknod(parent={parent:?}, name={name:?}, mode=0o{mode:o})");
- Err(libc::EOPNOTSUPP.into())
- }
-
- async fn mkdir(
- &self,
- _req: Request,
- parent: &OsStr,
- name: &OsStr,
- mode: u32,
- _umask: u32,
- ) -> Result<ReplyEntry> {
- log::debug!("mkdir(parent={parent:?}, name={name:?}, mode=0o{mode:o})");
-
- let mut path = PathBuf::from(parent).join(name);
- path.push(""); // ref https://users.rust-lang.org/t/trailing-in-paths/43166
- self.op
- .create_dir(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- let now = SystemTime::now();
- let attr = dummy_file_attr(FileType::Directory, now, self.uid, self.gid);
-
- Ok(ReplyEntry { ttl: TTL, attr })
- }
-
- async fn unlink(&self, _req: Request, parent: &OsStr, name: &OsStr) -> Result<()> {
- log::debug!("unlink(parent={parent:?}, name={name:?})");
-
- let path = PathBuf::from(parent).join(name);
- self.op
- .delete(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- Ok(())
- }
-
- async fn rmdir(&self, _req: Request, parent: &OsStr, name: &OsStr) -> Result<()> {
- log::debug!("rmdir(parent={parent:?}, name={name:?})");
-
- let path = PathBuf::from(parent).join(name);
- self.op
- .delete(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- Ok(())
- }
-
- async fn rename(
- &self,
- _req: Request,
- origin_parent: &OsStr,
- origin_name: &OsStr,
- parent: &OsStr,
- name: &OsStr,
- ) -> Result<()> {
- log::debug!(
- "rename(p={origin_parent:?}, name={origin_name:?}, newp={parent:?}, newname={name:?})"
- );
-
- if !self.op.info().full_capability().rename {
- return Err(Errno::from(libc::ENOTSUP))?;
- }
-
- let origin_path = PathBuf::from(origin_parent).join(origin_name);
- let path = PathBuf::from(parent).join(name);
-
- self.op
- .rename(&origin_path.to_string_lossy(), &path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- Ok(())
- }
-
- async fn link(
- &self,
- _req: Request,
- path: &OsStr,
- new_parent: &OsStr,
- new_name: &OsStr,
- ) -> Result<ReplyEntry> {
- log::debug!("link(path={path:?}, new_parent={new_parent:?}, new_name={new_name:?})");
- Err(libc::EOPNOTSUPP.into())
- }
-
- async fn opendir(&self, _req: Request, path: &OsStr, flags: u32) -> Result<ReplyOpen> {
- log::debug!("opendir(path={path:?}, flags=0x{flags:x})");
- Ok(ReplyOpen { fh: 0, flags })
- }
-
- async fn open(&self, _req: Request, path: &OsStr, flags: u32) -> Result<ReplyOpen> {
- log::debug!("open(path={path:?}, flags=0x{flags:x})");
-
- let (is_read, is_trunc, is_append) = self.check_flags(flags)?;
- if flags & libc::O_CREAT as u32 != 0 {
- self.op
- .write(&path.to_string_lossy(), Bytes::new())
- .await
- .map_err(opendal_error2errno)?;
- }
-
- let inner_writer = if is_trunc || is_append {
- let writer = self
- .op
- .writer_with(&path.to_string_lossy())
- .append(is_append)
- .await
- .map_err(opendal_error2errno)?;
- let written = if is_append {
- self.op
- .stat(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?
- .content_length()
- } else {
- 0
- };
- Some(Arc::new(Mutex::new(InnerWriter {
- writer: Some(writer),
- written,
- })))
- } else {
- None
- };
-
- let key = self
- .opened_files
- .insert(OpenedFile {
- path: path.into(),
- is_read,
- inner_writer,
- })
- .ok_or(Errno::from(libc::EBUSY))?;
-
- Ok(ReplyOpen {
- fh: FileKey(key).to_fh(),
- flags,
- })
- }
-
- async fn read(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: u64,
- offset: u64,
- size: u32,
- ) -> Result<ReplyData> {
- log::debug!("read(path={path:?}, fh={fh}, offset={offset}, size={size})");
-
- let file_path = {
- let file = self.get_opened_file(FileKey::try_from(fh)?, path)?;
- if !file.is_read {
- Err(Errno::from(libc::EACCES))?;
- }
- file.path.to_string_lossy().to_string()
- };
-
- let data = self
- .op
- .read_with(&file_path)
- .range(offset..)
- .await
- .map_err(opendal_error2errno)?;
-
- Ok(ReplyData {
- data: data.to_bytes(),
- })
- }
-
- async fn write(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: u64,
- offset: u64,
- data: &[u8],
- _write_flags: u32,
- flags: u32,
- ) -> Result<ReplyWrite> {
- log::debug!(
- "write(path={:?}, fh={}, offset={}, data_len={}, flags=0x{:x})",
- path,
- fh,
- offset,
- data.len(),
- flags
- );
-
- let Some(inner_writer) = ({
- self.get_opened_file(FileKey::try_from(fh)?, path)?
- .inner_writer
- .clone()
- }) else {
- Err(Errno::from(libc::EACCES))?
- };
-
- let mut inner = inner_writer.lock().await;
- // OpenDAL doesn't support random write
- if offset != inner.written {
- Err(Errno::from(libc::EINVAL))?;
- }
-
- inner
- .writer
- .as_mut()
- .ok_or(Errno::from(libc::EBADF))?
- .write_from(data)
- .await
- .map_err(opendal_error2errno)?;
- inner.written += data.len() as u64;
-
- Ok(ReplyWrite {
- written: data.len() as _,
- })
- }
-
- async fn release(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: u64,
- flags: u32,
- lock_owner: u64,
- flush: bool,
- ) -> Result<()> {
- log::debug!(
- "release(path={path:?}, fh={fh}, flags=0x{flags:x}, lock_owner={lock_owner}, flush={flush})"
- );
-
- let Some(file) = self.opened_files.take(FileKey::try_from(fh)?.0) else {
- return Ok(());
- };
-
- Self::finish_writer(file.inner_writer).await
- }
-
- /// FUSE can call flush multiple times or omit it. The first flush finalizes the writer, while
- /// release provides the fallback when flush is omitted.
- async fn flush(
- &self,
- _req: Request,
- path: Option<&OsStr>,
- fh: u64,
- lock_owner: u64,
- ) -> Result<()> {
- log::debug!("flush(path={path:?}, fh={fh}, lock_owner={lock_owner})");
-
- let inner_writer = {
- let file = self.get_opened_file(FileKey::try_from(fh)?, path)?;
- file.inner_writer.clone()
- };
-
- Self::finish_writer(inner_writer).await?;
- Ok(())
- }
-
- type DirEntryStream<'a> = BoxStream<'a, Result<DirectoryEntry>>;
-
- async fn readdir<'a>(
- &'a self,
- _req: Request,
- path: &'a OsStr,
- fh: u64,
- offset: i64,
- ) -> Result<ReplyDirectory<Self::DirEntryStream<'a>>> {
- log::debug!("readdir(path={path:?}, fh={fh}, offset={offset})");
-
- let mut current_dir = PathBuf::from(path);
- current_dir.push(""); // ref https://users.rust-lang.org/t/trailing-in-paths/43166
- let path = current_dir.to_string_lossy().to_string();
- let children = self
- .op
- .lister(¤t_dir.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?
- .filter_map(move |entry| {
- let dir = normalize_path(path.as_str());
- async move {
- match entry {
- Ok(e) if e.path() == dir => None,
- _ => Some(entry),
- }
- }
- })
- .enumerate()
- .map(|(i, entry)| {
- entry
- .map(|e| DirectoryEntry {
- kind: entry_mode2file_type(e.metadata().mode()),
- name: e.name().trim_matches('/').into(),
- offset: (i + 3) as i64,
- })
- .map_err(opendal_error2errno)
- });
-
- let relative_paths = stream::iter([
- Result::Ok(DirectoryEntry {
- kind: FileType::Directory,
- name: ".".into(),
- offset: 1,
- }),
- Result::Ok(DirectoryEntry {
- kind: FileType::Directory,
- name: "..".into(),
- offset: 2,
- }),
- ]);
-
- Ok(ReplyDirectory {
- entries: relative_paths.chain(children).skip(offset as usize).boxed(),
- })
- }
-
- async fn access(&self, _req: Request, path: &OsStr, mask: u32) -> Result<()> {
- log::debug!("access(path={path:?}, mask=0x{mask:x})");
-
- self.op
- .stat(&path.to_string_lossy())
- .await
- .map_err(opendal_error2errno)?;
-
- Ok(())
- }
-
- async fn create(
- &self,
- _req: Request,
- parent: &OsStr,
- name: &OsStr,
- mode: u32,
- flags: u32,
- ) -> Result<ReplyCreated> {
- log::debug!("create(parent={parent:?}, name={name:?}, mode=0o{mode:o}, flags=0x{flags:x})");
-
- let (is_read, is_trunc, is_append) = self.check_flags(flags | libc::O_CREAT as u32)?;
-
- let path = PathBuf::from(parent).join(name);
-
- let inner_writer = if is_trunc || is_append {
- let writer = self
- .op
- .writer_with(&path.to_string_lossy())
- .chunk(4 * 1024 * 1024)
- .append(is_append)
- .await
- .map_err(opendal_error2errno)?;
- Some(Arc::new(Mutex::new(InnerWriter {
- writer: Some(writer),
- written: 0,
- })))
- } else {
- None
- };
-
- let now = SystemTime::now();
- let attr = dummy_file_attr(FileType::RegularFile, now, self.uid, self.gid);
-
- let key = self
- .opened_files
- .insert(OpenedFile {
- path: path.into(),
- is_read,
- inner_writer,
- })
- .ok_or(Errno::from(libc::EBUSY))?;
-
- Ok(ReplyCreated {
- ttl: TTL,
- attr,
- generation: 0,
- fh: FileKey(key).to_fh(),
- flags,
- })
- }
-
- type DirEntryPlusStream<'a> = BoxStream<'a, Result<DirectoryEntryPlus>>;
-
- async fn readdirplus<'a>(
- &'a self,
- _req: Request,
- parent: &'a OsStr,
- fh: u64,
- offset: u64,
- _lock_owner: u64,
- ) -> Result<ReplyDirectoryPlus<Self::DirEntryPlusStream<'a>>> {
- log::debug!("readdirplus(parent={parent:?}, fh={fh}, offset={offset})");
-
- let now = SystemTime::now();
- let mut current_dir = PathBuf::from(parent);
- current_dir.push(""); // ref https://users.rust-lang.org/t/trailing-in-paths/43166
- let uid = self.uid;
- let gid = self.gid;
-
- let path = current_dir.to_string_lossy().to_string();
- let children = self
- .op
- .lister_with(&path)
- .await
- .map_err(opendal_error2errno)?
- .filter_map(move |entry| {
- let dir = normalize_path(path.as_str());
- async move {
- match entry {
- Ok(e) if e.path() == dir => None,
- _ => Some(entry),
- }
- }
- })
- .enumerate()
- .map(move |(i, entry)| {
- entry
- .map(|e| {
- let metadata = e.metadata();
- DirectoryEntryPlus {
- kind: entry_mode2file_type(metadata.mode()),
- name: e.name().trim_matches('/').into(),
- offset: (i + 3) as i64,
- attr: metadata2file_attr(metadata, now, uid, gid),
- entry_ttl: TTL,
- attr_ttl: TTL,
- }
- })
- .map_err(opendal_error2errno)
- });
-
- let relative_path_attr = dummy_file_attr(FileType::Directory, now, uid, gid);
- let relative_paths = stream::iter([
- Result::Ok(DirectoryEntryPlus {
- kind: FileType::Directory,
- name: ".".into(),
- offset: 1,
- attr: relative_path_attr,
- entry_ttl: TTL,
- attr_ttl: TTL,
- }),
- Result::Ok(DirectoryEntryPlus {
- kind: FileType::Directory,
- name: "..".into(),
- offset: 2,
- attr: relative_path_attr,
- entry_ttl: TTL,
- attr_ttl: TTL,
- }),
- ]);
-
- Ok(ReplyDirectoryPlus {
- entries: relative_paths.chain(children).skip(offset as usize).boxed(),
- })
- }
-
- async fn rename2(
- &self,
- req: Request,
- origin_parent: &OsStr,
- origin_name: &OsStr,
- parent: &OsStr,
- name: &OsStr,
- _flags: u32,
- ) -> Result<()> {
- log::debug!(
- "rename2(origin_parent={origin_parent:?}, origin_name={origin_name:?}, parent={parent:?}, name={name:?})"
- );
- self.rename(req, origin_parent, origin_name, parent, name)
- .await
- }
-
- async fn copy_file_range(
- &self,
- req: Request,
- from_path: Option<&OsStr>,
- fh_in: u64,
- offset_in: u64,
- to_path: Option<&OsStr>,
- fh_out: u64,
- offset_out: u64,
- length: u64,
- flags: u64,
- ) -> Result<ReplyCopyFileRange> {
- log::debug!(
- "copy_file_range(from_path={from_path:?}, fh_in={fh_in}, offset_in={offset_in}, to_path={to_path:?}, fh_out={fh_out}, offset_out={offset_out}, length={length}, flags={flags})"
- );
- let data = self
- .read(req, from_path, fh_in, offset_in, length as _)
- .await?;
-
- let ReplyWrite { written } = self
- .write(req, to_path, fh_out, offset_out, &data.data, 0, flags as _)
- .await?;
-
- Ok(ReplyCopyFileRange {
- copied: u64::from(written),
- })
- }
-
- async fn statfs(&self, _req: Request, path: &OsStr) -> Result<ReplyStatFs> {
- log::debug!("statfs(path={path:?})");
- Ok(ReplyStatFs {
- blocks: 1,
- bfree: 0,
- bavail: 0,
- files: 1,
- ffree: 0,
- bsize: 4096,
- namelen: u32::MAX,
- frsize: 0,
- })
- }
-}
-
-const fn entry_mode2file_type(mode: EntryMode) -> FileType {
- match mode {
- EntryMode::DIR => FileType::Directory,
- _ => FileType::RegularFile,
- }
-}
-
-fn metadata2file_attr(metadata: &Metadata, atime: SystemTime, uid: u32, gid: u32) -> FileAttr {
- let last_modified = match metadata.last_modified() {
- None => atime,
- Some(ts) => ts.into(),
- };
- let kind = entry_mode2file_type(metadata.mode());
- FileAttr {
- size: metadata.content_length(),
- mtime: last_modified,
- ctime: last_modified,
- ..dummy_file_attr(kind, atime, uid, gid)
- }
-}
-
-const fn dummy_file_attr(kind: FileType, now: SystemTime, uid: u32, gid: u32) -> FileAttr {
- FileAttr {
- size: 0,
- blocks: 0,
- atime: now,
- mtime: now,
- ctime: now,
- kind,
- perm: fuse3::perm_from_mode_and_kind(kind, 0o775),
- nlink: 0,
- uid,
- gid,
- rdev: 0,
- blksize: 4096,
- #[cfg(target_os = "macos")]
- crtime: now,
- #[cfg(target_os = "macos")]
- flags: 0,
- }
-}
-
-fn opendal_error2errno(err: opendal::Error) -> fuse3::Errno {
- log::trace!("opendal_error2errno: {err:?}");
- match err.kind() {
- ErrorKind::Unsupported => Errno::from(libc::EOPNOTSUPP),
- ErrorKind::IsADirectory => Errno::from(libc::EISDIR),
- ErrorKind::NotFound => Errno::from(libc::ENOENT),
- ErrorKind::PermissionDenied => Errno::from(libc::EACCES),
- ErrorKind::AlreadyExists => Errno::from(libc::EEXIST),
- ErrorKind::NotADirectory => Errno::from(libc::ENOTDIR),
- ErrorKind::RangeNotSatisfied => Errno::from(libc::EINVAL),
- ErrorKind::RateLimited => Errno::from(libc::EBUSY),
- _ => Errno::from(libc::ENOENT),
- }
-}
diff --git a/integrations/fuse3/src/lib.rs b/integrations/fuse3/src/lib.rs
deleted file mode 100644
index a3f9d88..0000000
--- a/integrations/fuse3/src/lib.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-//! `fuse3_opendal` is an [`fuse3`](https://github.com/Sherlock-Holo/fuse3) implementation using opendal.
-//!
-//! This crate can help you to access ANY storage services by mounting locally by [`FUSE`](https://www.kernel.org/doc/html/next/filesystems/fuse.html).
-//!
-//! ```
-//! use fuse3::path::Session;
-//! use fuse3::MountOptions;
-//! use fuse3::Result;
-//! use fuse3_opendal::Filesystem;
-//! use opendal::services::Memory;
-//! use opendal::Operator;
-//!
-//! #[tokio::test]
-//! async fn test() -> Result<()> {
-//! // Build opendal Operator.
-//! let op = Operator::new(Memory::default())?.finish();
-//!
-//! // Build fuse3 file system.
-//! let fs = Filesystem::new(op, 1000, 1000);
-//!
-//! // Configure mount options.
-//! let mount_options = MountOptions::default();
-//!
-//! // Start a fuse3 session and mount it.
-//! let mut mount_handle = Session::new(mount_options)
-//! .mount_with_unprivileged(fs, "/tmp/mount_test")
-//! .await?;
-//! let handle = &mut mount_handle;
-//!
-//! tokio::select! {
-//! res = handle => res?,
-//! _ = tokio::signal::ctrl_c() => {
-//! mount_handle.unmount().await?
-//! }
-//! }
-//!
-//! Ok(())
-//! }
-//! ```
-
-mod file;
-mod file_system;
-pub use file_system::Filesystem;
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..825882b
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,21 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Apache OpenDAL™ File System.
+//!
+//! The filesystem architecture is being redesigned. This crate intentionally
+//! exposes no runtime API until the new contracts are ready for implementation.
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 0b01e0e..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use anyhow::Result;
-use anyhow::anyhow;
-use clap::Parser;
-use url::Url;
-
-#[derive(Parser, Debug)]
-#[command(version, about)]
-struct Config {
- /// fuse mount path
- #[arg(env = "OFS_MOUNT_PATH", index = 1)]
- mount_path: String,
-
- /// location of opendal service
- /// format: <scheme>://?<key>=<value>&<key>=<value>
- /// example: fs://?root=/tmp
- #[arg(env = "OFS_BACKEND", index = 2)]
- backend: Url,
-}
-
-#[tokio::main(flavor = "multi_thread")]
-async fn main() -> Result<()> {
- let cfg = Config::parse();
-
- logforth::starter_log::stderr().apply();
- execute(cfg).await
-}
-
-#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
-async fn execute(cfg: Config) -> Result<()> {
- use fuse3::MountOptions;
- use fuse3::path::Session;
- use opendal::Operator;
- use std::env;
-
- if cfg.backend.has_host() {
- log::warn!("backend host will be ignored");
- }
-
- let scheme_str = cfg.backend.scheme();
- let op_args = cfg.backend.query_pairs().into_owned();
-
- let backend = Operator::via_iter(scheme_str, op_args)
- .map_err(|err| anyhow!("invalid scheme or arguments for {scheme_str}: {err}"))?;
-
- let mut mount_options = MountOptions::default();
- let mut gid = nix::unistd::getgid().into();
- mount_options.gid(gid);
- let mut uid = nix::unistd::getuid().into();
- mount_options.uid(uid);
-
- #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
- let mut mount_handle = if nix::unistd::getuid().is_root() {
- if let Some(sudo_gid) = env::var("SUDO_GID")
- .ok()
- .and_then(|gid_str| gid_str.parse::<u32>().ok())
- {
- mount_options.gid(sudo_gid);
- gid = sudo_gid;
- }
-
- if let Some(sudo_uid) = env::var("SUDO_UID")
- .ok()
- .and_then(|gid_str| gid_str.parse::<u32>().ok())
- {
- mount_options.uid(uid);
- uid = sudo_uid;
- }
-
- let fs = fuse3_opendal::Filesystem::new(backend, uid, gid);
- Session::new(mount_options)
- .mount(fs, cfg.mount_path)
- .await?
- } else {
- let fs = fuse3_opendal::Filesystem::new(backend, uid, gid);
- Session::new(mount_options)
- .mount_with_unprivileged(fs, cfg.mount_path)
- .await?
- };
-
- let handle = &mut mount_handle;
- tokio::select! {
- res = handle => res?,
- _ = tokio::signal::ctrl_c() => {
- mount_handle.unmount().await?
- }
- }
-
- Ok(())
-}
diff --git a/tests/common/mod.rs b/tests/common/mod.rs
deleted file mode 100644
index 59f41ec..0000000
--- a/tests/common/mod.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-use std::sync::OnceLock;
-
-use opendal::Capability;
-use opendal::Operator;
-use opendal::services;
-use opendal::tests;
-use tempfile::TempDir;
-use test_context::TestContext;
-use tokio::runtime::Runtime;
-use tokio::runtime::{self};
-
-static INIT_LOGGER: OnceLock<()> = OnceLock::new();
-static RUNTIME: OnceLock<Runtime> = OnceLock::new();
-
-#[cfg(any(target_os = "linux", target_os = "freebsd"))]
-pub struct OfsTestContext {
- pub mount_point: TempDir,
- // Keep backend root alive for the fs-based fallback backend.
- #[allow(dead_code)]
- backend_root: Option<TempDir>,
- // This is a false positive, the field is used in the test.
- #[allow(dead_code)]
- pub capability: Capability,
- mount_handle: fuse3::raw::MountHandle,
-}
-
-#[cfg(any(target_os = "linux", target_os = "freebsd"))]
-impl TestContext for OfsTestContext {
- fn setup() -> Self {
- let mut backend_root = None;
- let backend = tests::init_test_service()
- .expect("init test service")
- .unwrap_or_else(|| {
- let tmp_root = tempfile::tempdir().expect("create temporary backend root");
- let root_path = tmp_root.path().to_string_lossy().to_string();
- let fs = services::Fs::default().root(&root_path);
- let backend = Operator::new(fs)
- .expect("build fallback fs operator")
- .finish();
- backend_root = Some(tmp_root);
- backend
- });
- let capability = backend.info().full_capability();
-
- INIT_LOGGER.get_or_init(|| logforth::starter_log::stderr().apply());
-
- let mount_point = tempfile::tempdir().unwrap();
- let mount_point_str = mount_point.path().to_string_lossy().to_string();
- let mount_handle = RUNTIME
- .get_or_init(|| {
- runtime::Builder::new_multi_thread()
- .enable_all()
- .build()
- .expect("build runtime")
- })
- .block_on(
- #[allow(clippy::async_yields_async)]
- async move {
- let mut mount_options = fuse3::MountOptions::default();
- let gid = nix::unistd::getgid().into();
- mount_options.gid(gid);
- let uid = nix::unistd::getuid().into();
- mount_options.uid(uid);
-
- let fs = fuse3_opendal::Filesystem::new(backend, uid, gid);
- fuse3::path::Session::new(mount_options)
- .mount_with_unprivileged(fs, mount_point_str)
- .await
- .unwrap()
- },
- );
-
- OfsTestContext {
- mount_point,
- backend_root,
- capability,
- mount_handle,
- }
- }
-
- // We don't care if the unmount fails, so we ignore the result.
- fn teardown(self) {
- let _ = RUNTIME
- .get()
- .expect("runtime")
- .block_on(async move { self.mount_handle.unmount().await });
- let _ = self.mount_point.close();
- }
-}
diff --git a/tests/file.rs b/tests/file.rs
deleted file mode 100644
index 67918ae..0000000
--- a/tests/file.rs
+++ /dev/null
@@ -1,126 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#![cfg(any(target_os = "linux", target_os = "freebsd"))]
-
-mod common;
-
-use std::fs::File;
-use std::fs::OpenOptions;
-use std::fs::{self};
-use std::io::Read;
-use std::io::Seek;
-use std::io::SeekFrom;
-use std::io::Write;
-use std::thread;
-use std::time::Duration;
-
-use common::OfsTestContext;
-use test_context::test_context;
-
-static TEST_TEXT: &str = include_str!("../Cargo.toml");
-
-#[test_context(OfsTestContext)]
-#[test]
-fn test_file(ctx: &mut OfsTestContext) {
- let path = ctx.mount_point.path().join("test_file.txt");
- let mut file = File::create(&path).unwrap();
-
- file.write_all(TEST_TEXT.as_bytes()).unwrap();
- drop(file);
-
- let mut file = File::open(&path).unwrap();
- let mut buf = String::new();
- file.read_to_string(&mut buf).unwrap();
- assert_eq!(buf, TEST_TEXT);
- drop(file);
-
- fs::remove_file(path).unwrap();
-}
-
-#[test_context(OfsTestContext)]
-#[test]
-fn test_file_append(ctx: &mut OfsTestContext) {
- if !ctx.capability.write_can_append {
- // wait for ofs to be ready
- thread::sleep(Duration::from_secs(1));
- return;
- }
-
- let path = ctx.mount_point.path().join("test_file_append.txt");
- let mut file = File::create(&path).unwrap();
-
- file.write_all(TEST_TEXT.as_bytes()).unwrap();
- drop(file);
-
- let mut file = File::options().append(true).open(&path).unwrap();
- file.write_all(b"test").unwrap();
- drop(file);
-
- let mut file = File::open(&path).unwrap();
- let mut buf = String::new();
- file.read_to_string(&mut buf).unwrap();
- assert_eq!(buf, TEST_TEXT.to_owned() + "test");
- drop(file);
-
- fs::remove_file(path).unwrap();
-}
-
-#[test_context(OfsTestContext)]
-#[test]
-fn test_file_seek(ctx: &mut OfsTestContext) {
- let path = ctx.mount_point.path().join("test_file_seek.txt");
- let mut file = File::create(&path).unwrap();
-
- file.write_all(TEST_TEXT.as_bytes()).unwrap();
- drop(file);
-
- let mut file = File::open(&path).unwrap();
- file.seek(SeekFrom::Start(TEST_TEXT.len() as u64 / 2))
- .unwrap();
- let mut buf = String::new();
- file.read_to_string(&mut buf).unwrap();
- assert_eq!(buf, TEST_TEXT[TEST_TEXT.len() / 2..]);
- drop(file);
-
- fs::remove_file(path).unwrap();
-}
-
-#[test_context(OfsTestContext)]
-#[test]
-fn test_file_truncate(ctx: &mut OfsTestContext) {
- let path = ctx.mount_point.path().join("test_file_truncate.txt");
- let mut file = File::create(&path).unwrap();
- file.write_all(TEST_TEXT.as_bytes()).unwrap();
- drop(file);
-
- let mut file = OpenOptions::new()
- .write(true)
- .truncate(true)
- .open(&path)
- .unwrap();
- file.write_all(&TEST_TEXT.as_bytes()[..TEST_TEXT.len() / 2])
- .unwrap();
- drop(file);
-
- assert_eq!(
- fs::read_to_string(&path).unwrap(),
- TEST_TEXT[..TEST_TEXT.len() / 2]
- );
-
- fs::remove_file(path).unwrap();
-}
diff --git a/tests/file_system.rs b/tests/file_system.rs
deleted file mode 100644
index 364bd35..0000000
--- a/tests/file_system.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#![cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
-
-use std::ffi::OsStr;
-
-use fuse3::path::prelude::*;
-use opendal::Operator;
-use opendal::services;
-
-#[tokio::test]
-async fn test_release_commits_pending_write() {
- let root = tempfile::tempdir().unwrap();
- let root_path = root.path().to_string_lossy().to_string();
- let operator = Operator::new(services::Fs::default().root(&root_path))
- .unwrap()
- .finish();
- let filesystem = fuse3_opendal::Filesystem::new(operator.clone(), 0, 0);
-
- let path = OsStr::new("test.txt");
- let flags = (libc::O_WRONLY | libc::O_TRUNC) as u32;
- let created = filesystem
- .create(Request::default(), OsStr::new(""), path, 0o644, flags)
- .await
- .unwrap();
- filesystem
- .write(
- Request::default(),
- Some(path),
- created.fh,
- 0,
- b"hello",
- 0,
- flags,
- )
- .await
- .unwrap();
-
- filesystem
- .release(Request::default(), Some(path), created.fh, flags, 0, false)
- .await
- .unwrap();
-
- let content = operator.read("test.txt").await.unwrap().to_bytes();
- assert_eq!(content.as_ref(), b"hello");
-}
-
-#[tokio::test]
-async fn test_flush_keeps_file_handle_open() {
- let root = tempfile::tempdir().unwrap();
- let root_path = root.path().to_string_lossy().to_string();
- let operator = Operator::new(services::Fs::default().root(&root_path))
- .unwrap()
- .finish();
- operator.write("test.txt", "hello").await.unwrap();
-
- let filesystem = fuse3_opendal::Filesystem::new(operator, 0, 0);
- let path = OsStr::new("test.txt");
- let flags = libc::O_RDONLY as u32;
- let opened = filesystem
- .open(Request::default(), path, flags)
- .await
- .unwrap();
-
- filesystem
- .flush(Request::default(), Some(path), opened.fh, 0)
- .await
- .unwrap();
-
- let reply = filesystem
- .read(Request::default(), Some(path), opened.fh, 0, 5)
- .await
- .unwrap();
- assert_eq!(reply.data.as_ref(), b"hello");
-
- filesystem
- .release(Request::default(), Some(path), opened.fh, flags, 0, false)
- .await
- .unwrap();
-}
diff --git a/tests/path.rs b/tests/path.rs
deleted file mode 100644
index 1357f79..0000000
--- a/tests/path.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-
-#![cfg(any(target_os = "linux", target_os = "freebsd"))]
-
-mod common;
-
-use std::fs;
-
-use common::OfsTestContext;
-use test_context::test_context;
-use walkdir::WalkDir;
-
-#[test_context(OfsTestContext)]
-#[test]
-fn test_path(ctx: &mut OfsTestContext) {
- let actual_entries = [
- ("dir1", false),
- ("dir2", false),
- ("dir3", false),
- ("dir3/dir4", false),
- ("dir3/dir5", false),
- ("dir3/file3", true),
- ("dir3/file4", true),
- ("file1", true),
- ("file2", true),
- ]
- .into_iter()
- .map(|(x, y)| (x.to_string(), y))
- .collect::<Vec<_>>();
-
- for (path, is_file) in actual_entries.iter() {
- let path = ctx.mount_point.path().join(path);
- match is_file {
- true => fs::write(path, "hello").unwrap(),
- false => fs::create_dir(path).unwrap(),
- }
- }
-
- assert_eq!(
- actual_entries,
- WalkDir::new(ctx.mount_point.path())
- .min_depth(1)
- .max_depth(2)
- .sort_by_file_name()
- .into_iter()
- .map(|x| {
- let x = x.unwrap();
- (
- x.path()
- .strip_prefix(&ctx.mount_point)
- .unwrap()
- .to_str()
- .unwrap()
- .to_string(),
- x.file_type().is_file(),
- )
- })
- .collect::<Vec<_>>()
- );
-}