1
0
Fork 0

feat(io): use fs.cp & fs.rm fallback on ioUtil.rename EXDEV exception

pull/1466/head
Anton Golub 2023-07-13 18:32:20 +03:00
parent 91d3933eb5
commit 07f1f35f65
2 changed files with 50 additions and 1 deletions

View File

@ -292,6 +292,34 @@ describe('mv', () => {
)
await assertNotExists(sourceFile)
})
describe('ioUtil.rename', () => {
beforeAll(() => {
jest.spyOn(fs, 'rename').mockImplementation(() => {
throw Object.assign(new Error('cross-device link not permitted'), {
code: 'EXDEV'
})
})
})
afterEach(() => {
jest.restoreAllMocks()
})
it('fallbacks to `fs.cp` and `fs.rm` on `EXDEV` exception', async () => {
const root: string = path.join(getTestTemp(), 'rename_fallback_test')
const source: string = path.join(root, 'realfile1')
const dest: string = path.join(root, 'realfile2')
await io.mkdirP(root)
await fs.writeFile(source, 'test file content', {encoding: 'utf8'})
await io.mv(source, dest)
expect(await fs.readFile(dest, {encoding: 'utf8'})).toBe(
'test file content'
)
})
})
})
describe('rmRF', () => {

View File

@ -9,13 +9,34 @@ export const {
open,
readdir,
readlink,
rename,
rm,
rmdir,
stat,
symlink,
unlink
} = fs.promises
export async function rename(
src: fs.PathLike,
dest: fs.PathLike
): Promise<void> {
try {
await fs.promises.rename(src, dest)
} catch (err) {
if (err.code === 'EXDEV') {
await fs.promises.cp(
src instanceof Buffer ? src.toString('utf8') : src,
dest instanceof Buffer ? dest.toString('utf8') : dest,
{recursive: true}
)
await fs.promises.rm(src, {recursive: true})
return
}
throw err
}
}
// export const {open} = 'fs'
export const IS_WINDOWS = process.platform === 'win32'
// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691