Skip to content

Commit

Permalink
follow symlinks while walking dirs (and improve error messages)
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieupoumeyrolsonos authored and kali committed Apr 9, 2024
1 parent b76f6da commit 61b2bbc
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
18 changes: 12 additions & 6 deletions dinghy-lib/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::Platform;
use crate::Result;
use crate::Runnable;
use anyhow::anyhow;
use anyhow::Context;
use cargo_metadata::Metadata;
use ignore::WalkBuilder;
use log::{debug, trace};
Expand Down Expand Up @@ -136,11 +137,14 @@ pub fn rec_copy_excl<P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path> + ::std::
);

let mut walker = WalkBuilder::new(src);
walker.follow_links(true);
walker.git_ignore(!copy_ignored_test_data);
walker.add_ignore(ignore_file);
for entry in walker.build() {
let entry = entry?;
let metadata = entry.metadata()?;
let metadata = entry
.metadata()
.with_context(|| format!("Getting metadata for {entry:?}"))?;

if more_exclude.iter().any(|ex| entry.path().starts_with(ex)) {
debug!("Exclude {:?}", entry.path());
Expand All @@ -167,24 +171,26 @@ pub fn rec_copy_excl<P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path> + ::std::

if metadata.is_dir() {
if target.exists() && target.is_file() {
fs::remove_file(&target)?;
fs::remove_file(&target).with_context(|| format!("Removing file {target:?}"))?;
}
trace!("Creating directory {}", target.display());
fs::create_dir_all(&target)?;
fs::create_dir_all(&target).with_context(|| format!("Creating dirs {target:?}"))?;
} else if metadata.is_file() {
if target.exists() && !target.is_file() {
trace!("Remove 2 {:?}", target);
fs::remove_dir_all(&target)?;
fs::remove_dir_all(&target).with_context(|| format!("Removing dirs {target:?}"))?;
}
if !target.exists()
|| target.metadata()?.len() != entry.metadata()?.len()
|| target.metadata()?.modified()? < entry.metadata()?.modified()?
{
if target.exists() && target.metadata()?.permissions().readonly() {
fs::remove_dir_all(&target)?;
fs::remove_dir_all(&target)
.with_context(|| format!("Removing dirs {target:?}"))?;
}
trace!("Copying {} to {}", entry.path().display(), target.display());
copy_and_sync_file(entry.path(), &target)?;
copy_and_sync_file(entry.path(), &target)
.with_context(|| format!("Syncing {entry:?} and {target:?}"))?;
} else {
trace!("{} is already up-to-date", target.display());
}
Expand Down
24 changes: 19 additions & 5 deletions dinghy-lib/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::errors::Result;
use anyhow::Context;
use anyhow::{anyhow, bail};
use filetime::set_file_times;
use filetime::FileTime;
Expand All @@ -13,23 +14,36 @@ pub fn copy_and_sync_file<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> Res
let from = &from.as_ref();
let to = &to.as_ref();

if !from.exists() {
bail!("Source {from:?} is missing")
}

if !to.parent().unwrap().exists() {
bail!("Target directory is missing")
}

// Make target file writeable if it is read-only.
if to.exists() {
let mut permissions = fs::metadata(&to)?.permissions();
let mut permissions = fs::metadata(&to)
.with_context(|| format!("Checking metadata for {to:?}"))?
.permissions();
if permissions.readonly() {
permissions.set_readonly(false);
fs::set_permissions(&to, permissions)?;
fs::set_permissions(&to, permissions)
.with_context(|| format!("Setting permissions {to:?}"))?;
}
}

log::trace!("copy {:?} to {:?}", from, to);
fs::copy(&from, &to)?;
fs::copy(&from, &to).with_context(|| format!("Copying {from:?} to {to:?}"))?;

// Keep filetime to avoid useless sync on some devices (e.g. Android).
let from_metadata = from.metadata()?;
let from_metadata = from
.metadata()
.with_context(|| format!("Checking metadata for {from:?}"))?;
let atime = FileTime::from_last_access_time(&from_metadata);
let mtime = FileTime::from_last_modification_time(&from_metadata);
set_file_times(&to, atime, mtime)?;
set_file_times(&to, atime, mtime).with_context(|| format!("Setting times to {to:?}"))?;

Ok(())
}
Expand Down

0 comments on commit 61b2bbc

Please sign in to comment.