Skip to content

Commit

Permalink
Simplify the implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Dec 1, 2024
1 parent 14890b0 commit 704baef
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 150 deletions.
110 changes: 40 additions & 70 deletions yazi-cli/src/package/deploy.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,36 @@
use std::path::PathBuf;

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 tokio::fs;
use yazi_shared::{Xdg, fs::{maybe_exists, must_exists, remove_dir_clean}};

use super::{DiffAction, Package};
use crate::package::Git;
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"][..]
Expand All @@ -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;
Self::deploy_assets(from.join("assets"), to.join("assets")).await?;

if !diff_actions.is_empty() {
dirs = &[];
}
println!("Done!");
Ok(())
}

for dir in dirs {
let (from, to) = (origin.join(dir), dest.join(dir));
async fn deploy_assets(from: PathBuf, to: PathBuf) -> Result<()> {
use std::io::ErrorKind::NotFound;

if !from.exists() {
if to.exists() {
remove_dir_all(&to)
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 prune no-longer exist folder {}", to.display()))?;
.with_context(|| format!("failed to remove `{}`", entry.path().display()))?;
}
continue;
}
Err(e) if e.kind() == NotFound => {}
Err(e) => Err(e).context(format!("failed to read `{}`", to.display()))?,
};

copy_dir_all(&from, &to).await.with_context(|| {
format!("failed to copy dir `{}` to `{}`", from.display(), 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()))?,
}

println!("Done!");
Ok(())
}
}
63 changes: 0 additions & 63 deletions yazi-cli/src/package/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -49,48 +42,6 @@ impl Git {
))
}

pub(super) async fn diff(path: &Path, rev: &str, filter: &[&str]) -> Result<Vec<DiffAction>> {
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")?;
Expand All @@ -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
}
}
17 changes: 0 additions & 17 deletions yazi-shared/src/fs/fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Path>, dst: impl AsRef<Path>) -> 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)]
Expand Down

0 comments on commit 704baef

Please sign in to comment.