From 704baef26c3423f441a1d639b9a48a0128f81852 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sun, 1 Dec 2024 18:36:23 +0800 Subject: [PATCH] Simplify the implementation --- yazi-cli/src/package/deploy.rs | 126 +++++++++++++-------------------- yazi-cli/src/package/git.rs | 63 ----------------- yazi-shared/src/fs/fns.rs | 17 ----- 3 files changed, 48 insertions(+), 158 deletions(-) diff --git a/yazi-cli/src/package/deploy.rs b/yazi-cli/src/package/deploy.rs index 1591ae2c..cf4b27cc 100644 --- a/yazi-cli/src/package/deploy.rs +++ b/yazi-cli/src/package/deploy.rs @@ -1,46 +1,36 @@ -use anyhow::{Context, Result, bail}; -use tokio::fs::{self, remove_dir_all}; -use yazi_shared::{Xdg, fs::{copy_dir_all, maybe_exists, must_exists, remove_dir_clean}}; +use std::path::PathBuf; -use super::{DiffAction, Package}; -use crate::package::Git; +use anyhow::{Context, Result, bail}; +use tokio::fs; +use yazi_shared::{Xdg, fs::{maybe_exists, must_exists, remove_dir_clean}}; + +use super::Package; const TRACKER: &str = "DO_NOT_MODIFY_ANYTHING_IN_THIS_DIRECTORY"; impl Package { pub(super) async fn deploy(&mut self) -> Result<()> { let Some(name) = self.name().map(ToOwned::to_owned) else { bail!("Invalid package url") }; - let origin = self.local().join(&self.child); + let from = self.local().join(&self.child); self.header("Deploying package `{name}`")?; - self.is_flavor = maybe_exists(&origin.join("flavor.toml")).await; - let dest = if self.is_flavor { + self.is_flavor = maybe_exists(&from.join("flavor.toml")).await; + let to = if self.is_flavor { Xdg::config_dir().join(format!("flavors/{name}")) } else { Xdg::config_dir().join(format!("plugins/{name}")) }; - let tracker = dest.join(TRACKER); - if maybe_exists(&dest).await && !must_exists(&tracker).await { + let tracker = to.join(TRACKER); + if maybe_exists(&to).await && !must_exists(&tracker).await { bail!( "A user package with the same name `{name}` already exists. For safety, please manually delete it from your plugin/flavor directory and re-run the command." ); } - fs::create_dir_all(&dest).await?; - - let mut dirs = &["assets"][..]; - let mut diff_actions = vec![]; - if tracker.exists() { - let prev_rev = String::from_utf8(fs::read(&tracker).await?)?; - - if prev_rev != self.rev { - diff_actions = Git::diff(&self.local().join(&self.child), &prev_rev, dirs).await?; - } - } - - fs::write(tracker, &self.rev.trim_start_matches('=')).await?; + fs::create_dir_all(&to).await?; + fs::write(tracker, []).await?; let files = if self.is_flavor { &["flavor.toml", "tmtheme.xml", "README.md", "preview.png", "LICENSE", "LICENSE-tmtheme"][..] @@ -49,69 +39,49 @@ For safety, please manually delete it from your plugin/flavor directory and re-r }; for file in files { - let (from, to) = (origin.join(file), dest.join(file)); + let (from, to) = (from.join(file), to.join(file)); fs::copy(&from, &to) .await .with_context(|| format!("failed to copy `{}` to `{}`", from.display(), to.display()))?; } - for action in diff_actions.as_slice() { - match action { - DiffAction::Add { file } => { - let (from, to) = (origin.join(file), dest.join(file)); - fs::create_dir_all(&to).await?; - fs::copy(&from, &to).await.with_context(|| { - format!("failed to copy `{}` to `{}`", from.display(), to.display()) - })?; - } - DiffAction::Delete { file } => { - let file = dest.join(file); - fs::remove_file(&file) - .await - .with_context(|| format!("failed to remove `{}`", file.display()))?; - } - DiffAction::Rename { old, new } => { - let (from, to) = (dest.join(old), dest.join(new)); - fs::create_dir_all(&to).await?; - fs::rename(&from, &to).await.with_context(|| { - format!("failed to rename `{}` to `{}`", from.display(), to.display()) - })?; - } - DiffAction::Copy { old, new } => { - let (from, to) = (dest.join(old), dest.join(new)); - fs::create_dir_all(&to).await?; - fs::copy(&from, &to).await.with_context(|| { - format!("failed to copy `{}` to `{}`", from.display(), to.display()) - })?; - } - }; - } - - remove_dir_clean(&dest).await; - - if !diff_actions.is_empty() { - dirs = &[]; - } - - for dir in dirs { - let (from, to) = (origin.join(dir), dest.join(dir)); - - if !from.exists() { - if to.exists() { - remove_dir_all(&to) - .await - .with_context(|| format!("failed to prune no-longer exist folder {}", to.display()))?; - } - continue; - } - - copy_dir_all(&from, &to).await.with_context(|| { - format!("failed to copy dir `{}` to `{}`", from.display(), to.display()) - })?; - } + Self::deploy_assets(from.join("assets"), to.join("assets")).await?; println!("Done!"); Ok(()) } + + async fn deploy_assets(from: PathBuf, to: PathBuf) -> Result<()> { + use std::io::ErrorKind::NotFound; + + match fs::read_dir(&to).await { + Ok(mut it) => { + while let Some(entry) = it.next_entry().await? { + fs::remove_file(entry.path()) + .await + .with_context(|| format!("failed to remove `{}`", entry.path().display()))?; + } + } + Err(e) if e.kind() == NotFound => {} + Err(e) => Err(e).context(format!("failed to read `{}`", to.display()))?, + }; + + remove_dir_clean(&to).await; + match fs::read_dir(&from).await { + Ok(mut it) => { + fs::create_dir_all(&to).await?; + while let Some(entry) = it.next_entry().await? { + let (src, dist) = (entry.path(), to.join(entry.file_name())); + fs::copy(&src, &dist).await.with_context(|| { + format!("failed to copy `{}` to `{}`", src.display(), dist.display()) + })?; + } + } + Err(e) if e.kind() == NotFound => {} + Err(e) => Err(e).context(format!("failed to read `{}`", from.display()))?, + } + + Ok(()) + } } diff --git a/yazi-cli/src/package/git.rs b/yazi-cli/src/package/git.rs index 6754941d..6be4a4f3 100644 --- a/yazi-cli/src/package/git.rs +++ b/yazi-cli/src/package/git.rs @@ -6,13 +6,6 @@ use yazi_shared::strip_trailing_newline; pub(super) struct Git; -pub(super) enum DiffAction { - Add { file: String }, - Delete { file: String }, - Rename { old: String, new: String }, - Copy { old: String, new: String }, -} - impl Git { pub(super) async fn clone(url: &str, path: &Path) -> Result<()> { Self::exec(|c| c.args(["clone", url]).arg(path)).await @@ -49,48 +42,6 @@ impl Git { )) } - pub(super) async fn diff(path: &Path, rev: &str, filter: &[&str]) -> Result> { - let mut command = Command::new("git"); - command.current_dir(path).args(["diff", "-M100", "-C100", rev, "origin/HEAD", "--name-status"]); - if !filter.is_empty() { - command.arg("--"); - } - for f in filter { - command.arg(*f); - } - let output = command.output().await.context("Failed to run git diff")?; - - if !output.status.success() { - bail!("git diff failed: {}", output.status); - } - - let stdout = String::from_utf8(output.stdout).context("Failed to parse git diff output")?; - let mut diff_actions = Vec::new(); - - for line in stdout.lines() { - let parts: Vec<&str> = line.split_whitespace().collect(); - if parts.is_empty() { - continue; - } - - match parts[0] { - "A" | "M" if parts.len() == 2 => { - diff_actions.push(DiffAction::Add { file: parts[1].to_string() }) - } - "D" if parts.len() == 2 => { - diff_actions.push(DiffAction::Delete { file: parts[1].to_string() }) - } - "R100" if parts.len() == 3 => diff_actions - .push(DiffAction::Rename { old: parts[1].to_string(), new: parts[2].to_string() }), - "C100" if parts.len() == 3 => diff_actions - .push(DiffAction::Copy { old: parts[1].to_string(), new: parts[2].to_string() }), - _ => {} - } - } - - Ok(diff_actions) - } - async fn exec(f: impl FnOnce(&mut Command) -> &mut Command) -> Result<()> { let status = f(&mut Command::new("git")).status().await.context("Failed to execute `git` command")?; @@ -102,17 +53,3 @@ impl Git { Ok(()) } } - -impl DiffAction { - pub(super) fn is_in(&self, dirs: &[&str]) -> bool { - for dir in dirs { - match self { - DiffAction::Add { file } => return file.contains(dir), - DiffAction::Delete { file } => return file.contains(dir), - DiffAction::Rename { old: _, new } => return new.contains(dir), - DiffAction::Copy { old: _, new } => return new.contains(dir), - } - } - false - } -} diff --git a/yazi-shared/src/fs/fns.rs b/yazi-shared/src/fs/fns.rs index 776967d5..3487afc4 100644 --- a/yazi-shared/src/fs/fns.rs +++ b/yazi-shared/src/fs/fns.rs @@ -298,23 +298,6 @@ pub async fn remove_dir_clean(dir: &Path) { fs::remove_dir(dir).await.ok(); } -pub async fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> io::Result<()> { - fs::create_dir_all(&dst).await?; - let mut entries = fs::read_dir(src).await?; - - while let Some(entry) = entries.next_entry().await? { - let file_type = entry.file_type().await?; - let dest_path = dst.as_ref().join(entry.file_name()); - - if file_type.is_dir() { - Box::pin(copy_dir_all(entry.path(), dest_path)).await?; - } else { - fs::copy(entry.path(), dest_path).await.ok(); - } - } - Ok(()) -} - // Convert a file mode to a string representation #[cfg(unix)] #[allow(clippy::collapsible_else_if)]