mirror of https://github.com/astral-sh/uv
Move `clone_recursive` documentation (#11579)
While investigating #11554 I noticed this was not quite correct and hard to find.
This commit is contained in:
parent
b086437bff
commit
0d29382664
|
|
@ -4,6 +4,7 @@ doc-valid-idents = [
|
||||||
"PyPy",
|
"PyPy",
|
||||||
"CPython",
|
"CPython",
|
||||||
"GraalPy",
|
"GraalPy",
|
||||||
|
"ReFS",
|
||||||
".." # Include the defaults
|
".." # Include the defaults
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,8 @@ impl LinkMode {
|
||||||
/// via copy-on-write, which is similar to a hard link, but allows the files to be modified
|
/// via copy-on-write, which is similar to a hard link, but allows the files to be modified
|
||||||
/// independently (that is, the file is copied upon modification).
|
/// independently (that is, the file is copied upon modification).
|
||||||
///
|
///
|
||||||
/// This method uses `clonefile` on macOS, and `reflink` on Linux.
|
/// This method uses `clonefile` on macOS, and `reflink` on Linux. See [`clone_recursive`] for
|
||||||
|
/// details.
|
||||||
fn clone_wheel_files(
|
fn clone_wheel_files(
|
||||||
site_packages: impl AsRef<Path>,
|
site_packages: impl AsRef<Path>,
|
||||||
wheel: impl AsRef<Path>,
|
wheel: impl AsRef<Path>,
|
||||||
|
|
@ -81,17 +82,6 @@ fn clone_wheel_files(
|
||||||
let mut count = 0usize;
|
let mut count = 0usize;
|
||||||
let mut attempt = Attempt::default();
|
let mut attempt = Attempt::default();
|
||||||
|
|
||||||
// On macOS, directories can be recursively copied with a single `clonefile` call.
|
|
||||||
// So we only need to iterate over the top-level of the directory, and copy each file or
|
|
||||||
// subdirectory unless the subdirectory exists already in which case we'll need to recursively
|
|
||||||
// merge its contents with the existing directory.
|
|
||||||
//
|
|
||||||
// On linux, we need to always reflink recursively, as `FICLONE` ioctl does not support directories.
|
|
||||||
// Also note, that reflink is only supported on certain filesystems (btrfs, xfs, ...), and only when
|
|
||||||
// it does not cross filesystem boundaries.
|
|
||||||
//
|
|
||||||
// On windows, we also always need to reflink recursively, as `FSCTL_DUPLICATE_EXTENTS_TO_FILE` ioctl
|
|
||||||
// is not supported on directories. Also, it is only supported on certain filesystems (ReFS, SMB, ...).
|
|
||||||
for entry in fs::read_dir(wheel.as_ref())? {
|
for entry in fs::read_dir(wheel.as_ref())? {
|
||||||
clone_recursive(
|
clone_recursive(
|
||||||
site_packages.as_ref(),
|
site_packages.as_ref(),
|
||||||
|
|
@ -144,6 +134,21 @@ enum Attempt {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively clone the contents of `from` into `to`.
|
/// Recursively clone the contents of `from` into `to`.
|
||||||
|
///
|
||||||
|
/// Note the behavior here is platform-dependent.
|
||||||
|
///
|
||||||
|
/// On macOS, directories can be recursively copied with a single `clonefile` call. So we only
|
||||||
|
/// need to iterate over the top-level of the directory, and copy each file or subdirectory
|
||||||
|
/// unless the subdirectory exists already in which case we'll need to recursively merge its
|
||||||
|
/// contents with the existing directory.
|
||||||
|
///
|
||||||
|
/// On Linux, we need to always reflink recursively, as `FICLONE` ioctl does not support
|
||||||
|
/// directories. Also note, that reflink is only supported on certain filesystems (btrfs, xfs,
|
||||||
|
/// ...), and only when it does not cross filesystem boundaries.
|
||||||
|
///
|
||||||
|
/// On Windows, we also always need to reflink recursively, as `FSCTL_DUPLICATE_EXTENTS_TO_FILE`
|
||||||
|
/// ioctl is not supported on directories. Also, it is only supported on certain filesystems
|
||||||
|
/// (ReFS, SMB, ...).
|
||||||
fn clone_recursive(
|
fn clone_recursive(
|
||||||
site_packages: &Path,
|
site_packages: &Path,
|
||||||
wheel: &Path,
|
wheel: &Path,
|
||||||
|
|
@ -158,7 +163,6 @@ fn clone_recursive(
|
||||||
trace!("Cloning {} to {}", from.display(), to.display());
|
trace!("Cloning {} to {}", from.display(), to.display());
|
||||||
|
|
||||||
if (cfg!(windows) || cfg!(target_os = "linux")) && from.is_dir() {
|
if (cfg!(windows) || cfg!(target_os = "linux")) && from.is_dir() {
|
||||||
// On Windows, reflinking directories is not supported, so we copy each file instead.
|
|
||||||
fs::create_dir_all(&to)?;
|
fs::create_dir_all(&to)?;
|
||||||
for entry in fs::read_dir(from)? {
|
for entry in fs::read_dir(from)? {
|
||||||
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
|
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
|
||||||
|
|
@ -170,7 +174,8 @@ fn clone_recursive(
|
||||||
Attempt::Initial => {
|
Attempt::Initial => {
|
||||||
if let Err(err) = reflink::reflink(&from, &to) {
|
if let Err(err) = reflink::reflink(&from, &to) {
|
||||||
if err.kind() == std::io::ErrorKind::AlreadyExists {
|
if err.kind() == std::io::ErrorKind::AlreadyExists {
|
||||||
// If cloning/copying fails and the directory exists already, it must be merged recursively.
|
// If cloning or copying fails and the directory exists already, it must be
|
||||||
|
// merged recursively.
|
||||||
if entry.file_type()?.is_dir() {
|
if entry.file_type()?.is_dir() {
|
||||||
for entry in fs::read_dir(from)? {
|
for entry in fs::read_dir(from)? {
|
||||||
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
|
clone_recursive(site_packages, wheel, locks, &entry?, attempt)?;
|
||||||
|
|
@ -197,7 +202,7 @@ fn clone_recursive(
|
||||||
from.display(),
|
from.display(),
|
||||||
to.display()
|
to.display()
|
||||||
);
|
);
|
||||||
// switch to copy fallback
|
// Fallback to copying
|
||||||
*attempt = Attempt::UseCopyFallback;
|
*attempt = Attempt::UseCopyFallback;
|
||||||
clone_recursive(site_packages, wheel, locks, entry, attempt)?;
|
clone_recursive(site_packages, wheel, locks, entry, attempt)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue