-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from ink0rr/dev
Add `--cached` flag to run and watch command
- Loading branch information
Showing
7 changed files
with
249 additions
and
38 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
use super::{copy_dir, move_dir}; | ||
use anyhow::{Context, Result}; | ||
use rayon::prelude::*; | ||
use std::{ | ||
fs, | ||
io::{BufRead, BufReader}, | ||
path::Path, | ||
}; | ||
|
||
pub fn copy_dir_cached( | ||
from: impl AsRef<Path>, | ||
to: impl AsRef<Path>, | ||
cache: impl AsRef<Path>, | ||
) -> Result<()> { | ||
let from = from.as_ref(); | ||
let to = to.as_ref(); | ||
let cache = cache.as_ref(); | ||
if cache.is_dir() { | ||
move_dir(cache, to)?; | ||
copy_cached(from, to).context(format!( | ||
"Failed to copy directory\n\ | ||
<yellow> >></> From: {}\n\ | ||
<yellow> >></> To: {}", | ||
from.display(), | ||
to.display(), | ||
))?; | ||
cleanup(from, to) | ||
} else { | ||
copy_dir(from, to) | ||
} | ||
} | ||
|
||
/// Copy files from the source directory to the target directory, but only if they are different. | ||
fn copy_cached(from: &Path, to: &Path) -> Result<()> { | ||
fs::create_dir_all(to)?; | ||
fs::read_dir(from)? | ||
.par_bridge() | ||
.map(|entry| -> Result<()> { | ||
let entry = entry?; | ||
let from = entry.path(); | ||
let to = to.join(entry.file_name()); | ||
if diff(&from, &to)? { | ||
return Ok(()); | ||
} | ||
let to_dir = to.is_dir(); | ||
if from.is_dir() { | ||
if !to_dir { | ||
fs::remove_file(&to)?; | ||
} | ||
return copy_cached(&from, &to); | ||
} | ||
if to_dir { | ||
fs::remove_dir_all(&to)?; | ||
} | ||
fs::copy(&from, &to)?; | ||
Ok(()) | ||
}) | ||
.collect() | ||
} | ||
|
||
/// Remove files that are not present in the source directory. | ||
fn cleanup(from: &Path, to: &Path) -> Result<()> { | ||
fs::read_dir(to)? | ||
.par_bridge() | ||
.map(|entry| -> Result<()> { | ||
let entry = entry?; | ||
let from = from.join(entry.file_name()); | ||
let to = entry.path(); | ||
let is_dir = to.is_dir(); | ||
if !from.exists() { | ||
let remove: std::io::Result<()> = match is_dir { | ||
true => fs::remove_dir_all(&to), | ||
false => fs::remove_file(&to), | ||
}; | ||
return remove.context(format!( | ||
"Failed to remove file/directory\n\ | ||
<yellow> >></> Path: {}", | ||
to.display(), | ||
)); | ||
} | ||
if is_dir { | ||
cleanup(&from, &to)?; | ||
} | ||
Ok(()) | ||
}) | ||
.collect() | ||
} | ||
|
||
/// Compare two file contents. Return true if they are identical. | ||
fn diff(a: impl AsRef<Path>, b: impl AsRef<Path>) -> Result<bool> { | ||
let a = fs::File::open(a); | ||
let b = fs::File::open(b); | ||
if a.is_err() || b.is_err() { | ||
return Ok(false); | ||
} | ||
let mut a_reader = BufReader::new(a.unwrap()); | ||
let mut b_reader = BufReader::new(b.unwrap()); | ||
if a_reader.capacity() != b_reader.capacity() { | ||
return Ok(false); | ||
} | ||
loop { | ||
let len = { | ||
let a_buf = a_reader.fill_buf()?; | ||
let b_buf = b_reader.fill_buf()?; | ||
if a_buf.is_empty() && b_buf.is_empty() { | ||
return Ok(true); | ||
} | ||
if a_buf != b_buf { | ||
return Ok(false); | ||
} | ||
a_buf.len() | ||
}; | ||
a_reader.consume(len); | ||
b_reader.consume(len); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.