Skip to content

Commit

Permalink
fix: fix copy_directory and copy_directory_with_progress incorrectly …
Browse files Browse the repository at this point in the history
…handling relative symlink destinations

Previously fs-more would not interprete relative symlink destinations relative to the containing directory, but simply relative to the current directory. This made it categorize relative symlinks as broken links.
  • Loading branch information
simongoricar committed Oct 26, 2024
1 parent 02c9cfc commit d1b52fc
Showing 1 changed file with 32 additions and 14 deletions.
46 changes: 32 additions & 14 deletions src/directory/prepared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,14 +599,33 @@ fn scan_and_plan_directory_copy(
}
})?;

// The absolute symlink destination path will only be resolved if the original path
// as-is from fs::read_link is relative. This is because relative symlinks must be interpreted
// relative to the directory they are in, not relative to the current directory.
let resolved_absolute_symlink_pathbuf = if resolved_symlink_path.is_relative() {
let symlink_parent_directory_path = &next_directory.directory_path;

let resolved_absolute_symlink_path =
symlink_parent_directory_path.join(&resolved_symlink_path);

Some(resolved_absolute_symlink_path)
} else {
None
};

let resolved_symlink_path_exists =
try_exists_without_follow(&resolved_symlink_path).map_err(|error| {
DirectoryExecutionPlanError::UnableToAccess {
path: resolved_symlink_path.clone(),
error,
}
})?;

let resolved_absolute_symlink_path = resolved_absolute_symlink_pathbuf
.as_ref()
.unwrap_or(&resolved_symlink_path);


let resolved_symlink_path_exists = try_exists_without_follow(
&resolved_absolute_symlink_path,
)
.map_err(|error| DirectoryExecutionPlanError::UnableToAccess {
path: resolved_absolute_symlink_path.to_path_buf(),
error,
})?;


if !resolved_symlink_path_exists {
Expand Down Expand Up @@ -692,14 +711,13 @@ fn scan_and_plan_directory_copy(
// Symbolic link is valid, we should look at the corresponding
// `symlink_behaviour` option.

let resolved_symlink_metadata =
fs::metadata(&resolved_symlink_path).map_err(|error| {
DirectoryExecutionPlanError::UnableToAccess {
path: resolved_symlink_path.clone(),
error,
}
let resolved_symlink_metadata = fs::metadata(&resolved_absolute_symlink_path)
.map_err(|error| DirectoryExecutionPlanError::UnableToAccess {
path: resolved_symlink_path.clone(),
error,
})?;


let resolved_symlink_file_type = resolved_symlink_metadata.file_type();
let resolved_symlink_file_size = resolved_symlink_metadata.len();

Expand Down Expand Up @@ -764,7 +782,7 @@ fn scan_and_plan_directory_copy(
// symlink's destination to the copy destination should be queued.
if resolved_symlink_file_type.is_file() {
operation_queue.push(QueuedOperation::CopyFile {
source_file_path: resolved_symlink_path,
source_file_path: resolved_absolute_symlink_path.to_path_buf(),
source_size_bytes: resolved_symlink_file_size,
destination_file_path: directory_item_destination_path,
});
Expand Down

0 comments on commit d1b52fc

Please sign in to comment.