mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
fix(fs): support rename across filesystems
Rather than expect the user to know that they need to handle a special case when renaming across filesystems, we can just handle it for them. Fixes #3092
This commit is contained in:
parent
5919f31891
commit
9e40cbe495
1 changed files with 25 additions and 4 deletions
|
@ -179,16 +179,14 @@ impl FileSystem for RealFs {
|
|||
}
|
||||
|
||||
fn rename_sync(&self, oldpath: &Path, newpath: &Path) -> FsResult<()> {
|
||||
fs::rename(oldpath, newpath).map_err(Into::into)
|
||||
rename(oldpath, newpath)
|
||||
}
|
||||
async fn rename_async(
|
||||
&self,
|
||||
oldpath: PathBuf,
|
||||
newpath: PathBuf,
|
||||
) -> FsResult<()> {
|
||||
spawn_blocking(move || fs::rename(oldpath, newpath))
|
||||
.await?
|
||||
.map_err(Into::into)
|
||||
spawn_blocking(move || rename(&oldpath, &newpath)).await?
|
||||
}
|
||||
|
||||
fn link_sync(&self, oldpath: &Path, newpath: &Path) -> FsResult<()> {
|
||||
|
@ -598,6 +596,29 @@ fn read_dir(path: &Path) -> FsResult<Vec<FsDirEntry>> {
|
|||
Ok(entries)
|
||||
}
|
||||
|
||||
fn rename(oldpath: &Path, newpath: &Path) -> FsResult<()> {
|
||||
match fs::rename(oldpath, newpath) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
if err.raw_os_error() == Some(libc::EXDEV) {
|
||||
// EXDEV: rename fails because oldpath and newpath are not on the same
|
||||
// mounted filesystem. We need to do a copy and remove.
|
||||
//
|
||||
// This check can be replaced with the following once
|
||||
// https://github.com/rust-lang/rust/issues/86442 stabilizes:
|
||||
//
|
||||
// if err.kind() == io::ErrorKind::CrossDeviceLink
|
||||
//
|
||||
copy_file(oldpath, newpath)?;
|
||||
fs::remove_file(oldpath)?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn symlink(
|
||||
oldpath: &Path,
|
||||
|
|
Loading…
Reference in a new issue