From 449450d0db1cb8e30ddc94c7b1d8ef42aa2a0d48 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Mon, 24 Nov 2025 15:23:06 +0800 Subject: [PATCH] feat!: introduce `Path` as a subset of `Url` to enforce type safety (#3361) --- .github/workflows/cachix.yml | 2 +- .github/workflows/check.yml | 6 +++--- .github/workflows/draft.yml | 10 +++++----- .github/workflows/test.yml | 2 +- .github/workflows/validate-form.yml | 2 +- CHANGELOG.md | 1 + yazi-binding/src/path.rs | 3 +++ yazi-boot/src/boot.rs | 3 +-- yazi-shared/src/strand/buf.rs | 14 ++++++++++---- yazi-shared/src/strand/cow.rs | 9 ++------- 10 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 2d1c89e3..1bde031f 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -12,7 +12,7 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install Nix uses: cachix/install-nix-action@v31 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 56e8e14d..43466367 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -14,7 +14,7 @@ jobs: clippy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Rust toolchain run: | @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Rust toolchain run: | @@ -47,7 +47,7 @@ jobs: stylua: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: JohnnyMorganz/stylua-action@v4 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index 15f6a43d..f95b4562 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -39,7 +39,7 @@ jobs: CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install gcc if: matrix.gcc != '' @@ -78,7 +78,7 @@ jobs: CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER: lld-link.exe CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER: lld-link.exe steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: @@ -117,7 +117,7 @@ jobs: container: image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: @@ -147,7 +147,7 @@ jobs: arch: arm64 runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 @@ -229,7 +229,7 @@ jobs: echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/download-artifact@v6 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e524a55a..17ed52e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Rust toolchain run: rustup toolchain install stable --profile minimal diff --git a/.github/workflows/validate-form.yml b/.github/workflows/validate-form.yml index 2d48f16a..b9416d4b 100644 --- a/.github/workflows/validate-form.yml +++ b/.github/workflows/validate-form.yml @@ -12,7 +12,7 @@ jobs: permissions: issues: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 diff --git a/CHANGELOG.md b/CHANGELOG.md index aded5892..0a216a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/): - Rename `name` to `url` for open, fetchers, spotters, preloaders, previewers, filetype, and `globs` icon rules to support virtual file system ([#3034]) - Rename `mime` fetcher to `mime.local`, and introduce `mime.dir` fetcher to support folder MIME types ([#3222]) - Remove `$0` parameter in opener rules to make the `open` command work under empty directories ([#3226]) +- Return `Path` instead of `Url` from `Url:strip_prefix()` to enforce type safety ([#3361]) - Use `body` instead of the term `content` in confirmations ([#2921]) - Use `u16` instead of `u32` as the type of `max_width` and `max_height` options to avoid memory exhaustion ([#3313]) - Implement `__pairs` metamethod instead of `__index` for the callback argument of the `@yank` DDS event ([#2997]) diff --git a/yazi-binding/src/path.rs b/yazi-binding/src/path.rs index a18dbd5e..be37b940 100644 --- a/yazi-binding/src/path.rs +++ b/yazi-binding/src/path.rs @@ -115,6 +115,9 @@ impl UserData for Path { cached_field!(fields, stem, |lua, me| { me.stem().map(|s| lua.create_string(s.encoded_bytes())).transpose() }); + + fields.add_field_method_get("is_absolute", |_, me| Ok(me.is_absolute())); + fields.add_field_method_get("has_root", |_, me| Ok(me.has_root())); } fn add_methods>(methods: &mut M) { diff --git a/yazi-boot/src/boot.rs b/yazi-boot/src/boot.rs index 2c123084..2be24d9e 100644 --- a/yazi-boot/src/boot.rs +++ b/yazi-boot/src/boot.rs @@ -2,12 +2,11 @@ use std::path::PathBuf; use futures::executor::block_on; use hashbrown::HashSet; -use serde::Serialize; use yazi_fs::{CWD, Xdg, path::expand_url}; use yazi_shared::{strand::StrandBuf, url::{UrlBuf, UrlLike}}; use yazi_vfs::provider; -#[derive(Debug, Default, Serialize)] +#[derive(Debug, Default)] pub struct Boot { pub cwds: Vec, pub files: Vec, diff --git a/yazi-shared/src/strand/buf.rs b/yazi-shared/src/strand/buf.rs index f75f093d..e5a28479 100644 --- a/yazi-shared/src/strand/buf.rs +++ b/yazi-shared/src/strand/buf.rs @@ -1,13 +1,11 @@ -use std::{borrow::Cow, ffi::OsString}; +use std::{borrow::Cow, ffi::OsString, hash::{Hash, Hasher}}; use anyhow::Result; -use serde::Serialize; use crate::{FromWtf8Vec, path::PathDyn, strand::{AsStrand, Strand, StrandCow, StrandError, StrandKind}}; // --- StrandBuf -#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] -#[serde(untagged)] +#[derive(Clone, Debug, Eq)] pub enum StrandBuf { Os(OsString), Utf8(String), @@ -43,10 +41,18 @@ impl From> for StrandBuf { fn from(value: StrandCow<'_>) -> Self { value.into_owned() } } +impl PartialEq for StrandBuf { + fn eq(&self, other: &Self) -> bool { self.as_strand() == other.as_strand() } +} + impl PartialEq> for StrandBuf { fn eq(&self, other: &Strand<'_>) -> bool { self.as_strand() == *other } } +impl Hash for StrandBuf { + fn hash(&self, state: &mut H) { self.as_strand().hash(state); } +} + impl StrandBuf { pub fn clear(&mut self) { match self { diff --git a/yazi-shared/src/strand/cow.rs b/yazi-shared/src/strand/cow.rs index f18f099b..74d6b906 100644 --- a/yazi-shared/src/strand/cow.rs +++ b/yazi-shared/src/strand/cow.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}}; use anyhow::Result; -use crate::strand::{Strand, StrandBuf, StrandKind}; +use crate::strand::{AsStrand, Strand, StrandBuf, StrandKind}; pub enum StrandCow<'a> { Borrowed(Strand<'a>), @@ -35,12 +35,7 @@ impl From for StrandCow<'_> { } impl PartialEq> for StrandCow<'_> { - fn eq(&self, other: &Strand) -> bool { - match self { - Self::Borrowed(s) => s == other, - Self::Owned(s) => s == other, - } - } + fn eq(&self, other: &Strand) -> bool { self.as_strand() == *other } } impl<'a> StrandCow<'a> {