Skip to content

Commit 0d29382

Browse files
authored
Move clone_recursive documentation (#11579)
While investigating #11554 I noticed this was not quite correct and hard to find.
1 parent b086437 commit 0d29382

File tree

2 files changed

+21
-15
lines changed

2 files changed

+21
-15
lines changed

clippy.toml

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ doc-valid-idents = [
44
"PyPy",
55
"CPython",
66
"GraalPy",
7+
"ReFS",
78
".." # Include the defaults
89
]
910

crates/uv-install-wheel/src/linker.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ impl LinkMode {
7272
/// via copy-on-write, which is similar to a hard link, but allows the files to be modified
7373
/// independently (that is, the file is copied upon modification).
7474
///
75-
/// This method uses `clonefile` on macOS, and `reflink` on Linux.
75+
/// This method uses `clonefile` on macOS, and `reflink` on Linux. See [`clone_recursive`] for
76+
/// details.
7677
fn clone_wheel_files(
7778
site_packages: impl AsRef<Path>,
7879
wheel: impl AsRef<Path>,
@@ -81,17 +82,6 @@ fn clone_wheel_files(
8182
let mut count = 0usize;
8283
let mut attempt = Attempt::default();
8384

84-
// On macOS, directories can be recursively copied with a single `clonefile` call.
85-
// So we only need to iterate over the top-level of the directory, and copy each file or
86-
// subdirectory unless the subdirectory exists already in which case we'll need to recursively
87-
// merge its contents with the existing directory.
88-
//
89-
// On linux, we need to always reflink recursively, as `FICLONE` ioctl does not support directories.
90-
// Also note, that reflink is only supported on certain filesystems (btrfs, xfs, ...), and only when
91-
// it does not cross filesystem boundaries.
92-
//
93-
// On windows, we also always need to reflink recursively, as `FSCTL_DUPLICATE_EXTENTS_TO_FILE` ioctl
94-
// is not supported on directories. Also, it is only supported on certain filesystems (ReFS, SMB, ...).
9585
for entry in fs::read_dir(wheel.as_ref())? {
9686
clone_recursive(
9787
site_packages.as_ref(),
@@ -144,6 +134,21 @@ enum Attempt {
144134
}
145135

146136
/// Recursively clone the contents of `from` into `to`.
137+
///
138+
/// Note the behavior here is platform-dependent.
139+
///
140+
/// On macOS, directories can be recursively copied with a single `clonefile` call. So we only
141+
/// need to iterate over the top-level of the directory, and copy each file or subdirectory
142+
/// unless the subdirectory exists already in which case we'll need to recursively merge its
143+
/// contents with the existing directory.
144+
///
145+
/// On Linux, we need to always reflink recursively, as `FICLONE` ioctl does not support
146+
/// directories. Also note, that reflink is only supported on certain filesystems (btrfs, xfs,
147+
/// ...), and only when it does not cross filesystem boundaries.
148+
///
149+
/// On Windows, we also always need to reflink recursively, as `FSCTL_DUPLICATE_EXTENTS_TO_FILE`
150+
/// ioctl is not supported on directories. Also, it is only supported on certain filesystems
151+
/// (ReFS, SMB, ...).
147152
fn clone_recursive(
148153
site_packages: &Path,
149154
wheel: &Path,
@@ -158,7 +163,6 @@ fn clone_recursive(
158163
trace!("Cloning {} to {}", from.display(), to.display());
159164

160165
if (cfg!(windows) || cfg!(target_os = "linux")) && from.is_dir() {
161-
// On Windows, reflinking directories is not supported, so we copy each file instead.
162166
fs::create_dir_all(&to)?;
163167
for entry in fs::read_dir(from)? {
164168
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
@@ -170,7 +174,8 @@ fn clone_recursive(
170174
Attempt::Initial => {
171175
if let Err(err) = reflink::reflink(&from, &to) {
172176
if err.kind() == std::io::ErrorKind::AlreadyExists {
173-
// If cloning/copying fails and the directory exists already, it must be merged recursively.
177+
// If cloning or copying fails and the directory exists already, it must be
178+
// merged recursively.
174179
if entry.file_type()?.is_dir() {
175180
for entry in fs::read_dir(from)? {
176181
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
@@ -197,7 +202,7 @@ fn clone_recursive(
197202
from.display(),
198203
to.display()
199204
);
200-
// switch to copy fallback
205+
// Fallback to copying
201206
*attempt = Attempt::UseCopyFallback;
202207
clone_recursive(site_packages, wheel, locks, entry, attempt)?;
203208
}

0 commit comments

Comments
 (0)