From b25ae9f82d415da7fbd4d4e4b09397a194540a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20misaki=20masa?= Date: Tue, 14 Jul 2026 01:11:34 +0800 Subject: [PATCH] fix: fail when package source is missing (#4124) --- yazi-cli/src/package/delete.rs | 23 ++++++++++------------- yazi-cli/src/package/dependency.rs | 10 ++++++---- yazi-cli/src/package/deploy.rs | 12 ++++++++---- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/yazi-cli/src/package/delete.rs b/yazi-cli/src/package/delete.rs index 113484ca..0b705494 100644 --- a/yazi-cli/src/package/delete.rs +++ b/yazi-cli/src/package/delete.rs @@ -17,8 +17,14 @@ impl Dependency { } self.delete_assets().await?; - self.delete_sources().await?; - Ok(()) + if !self.delete_sources().await? { + outln!( + "For safety, user data will be preserved, manually delete them from: {}", + dir.display() + )?; + } + + Ok(outln!("Done!")?) } pub(super) async fn delete_assets(&self) -> Result<()> { @@ -39,7 +45,7 @@ impl Dependency { Ok(()) } - pub(super) async fn delete_sources(&self) -> Result<()> { + pub(super) async fn delete_sources(&self) -> Result { let dir = self.target(); let files = if self.is_flavor { Self::flavor_files() } else { Self::plugin_files(&dir).await? }; @@ -49,15 +55,6 @@ impl Dependency { .with_context(|| format!("failed to delete `{}`", path.display()))?; } - if ok_or_not_found(Local::regular(&dir).remove_dir().await).is_ok() { - outln!("Done!")?; - } else { - outln!( - "Done! -For safety, user data has been preserved, please manually delete them within: {}", - dir.display() - )?; - } - Ok(()) + Ok(ok_or_not_found(Local::regular(&dir).remove_dir().await).is_ok()) } } diff --git a/yazi-cli/src/package/dependency.rs b/yazi-cli/src/package/dependency.rs index 6de5755d..4c76f2cf 100644 --- a/yazi-cli/src/package/dependency.rs +++ b/yazi-cli/src/package/dependency.rs @@ -1,10 +1,9 @@ use std::{env, io, path::{Path, PathBuf}, str::FromStr}; -use anyhow::{Result, bail}; +use anyhow::{Context, Result, bail}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use twox_hash::XxHash3_128; use yazi_fs::Xdg; -use yazi_macro::ok_or_not_found; use yazi_shared::BytesExt; #[derive(Clone, Default)] @@ -65,8 +64,11 @@ impl Dependency { Ok(()) } - pub(super) async fn plugin_files(dir: &Path) -> io::Result> { - let mut it = ok_or_not_found!(tokio::fs::read_dir(dir).await, return Ok(vec![])); + pub(super) async fn plugin_files(dir: &Path) -> Result> { + let mut it = tokio::fs::read_dir(dir) + .await + .with_context(|| format!("failed to read plugin directory `{}`", dir.display()))?; + let mut files: Vec = ["LICENSE", "README.md", "main.lua"].into_iter().map(Into::into).collect(); while let Some(entry) = it.next_entry().await? { diff --git a/yazi-cli/src/package/deploy.rs b/yazi-cli/src/package/deploy.rs index c1d428cc..b3070160 100644 --- a/yazi-cli/src/package/deploy.rs +++ b/yazi-cli/src/package/deploy.rs @@ -13,6 +13,8 @@ impl Dependency { self.header("Deploying package `{name}`")?; self.is_flavor = maybe_exists(&from.join("flavor.toml")).await; + let files = + if self.is_flavor { Self::flavor_files() } else { Self::plugin_files(&from).await? }; let to = self.target(); let exists = maybe_exists(&to).await; @@ -24,18 +26,21 @@ impl Dependency { self.delete_assets().await?; let res1 = Self::deploy_assets(from.join("assets"), to.join("assets")).await; - let res2 = Self::deploy_sources(&from, &to, self.is_flavor).await; + let res2 = Self::deploy_sources(&from, &to, files).await; if !exists && (res2.is_err() || res1.is_err()) { self.delete_assets().await?; self.delete_sources().await?; + } else if exists && (res2.is_err() || res1.is_err()) { + self.hash = self.hash().await?; } Local::regular(&to).remove_dir_clean().await; - self.hash = self.hash().await?; res2?; res1?; + self.hash = self.hash().await?; outln!("Done!")?; + Ok(()) } @@ -56,8 +61,7 @@ impl Dependency { Ok(()) } - async fn deploy_sources(from: &Path, to: &Path, is_flavor: bool) -> Result<()> { - let files = if is_flavor { Self::flavor_files() } else { Self::plugin_files(from).await? }; + async fn deploy_sources(from: &Path, to: &Path, files: Vec) -> Result<()> { for file in files { let (from, to) = (from.join(&file), to.join(&file)); copy_and_seal(&from, &to)