Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Nov 4, 2022. It is now read-only.

Commit 0388f6a

Browse files
committed
also use the copy fallback for EPERM errors
PR-URL: #5 Credit: @nlf Close: #5 Reviewed-by: @wraithgar
1 parent c9cddf1 commit 0388f6a

File tree

4 files changed

+136
-9
lines changed

4 files changed

+136
-9
lines changed

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const moveFile = async (source, destination, options = {}, root = true, symlinks
7373
try {
7474
await rename(source, destination)
7575
} catch (error) {
76-
if (error.code === 'EXDEV') {
76+
if (error.code === 'EXDEV' || error.code === 'EPERM') {
7777
const sourceStat = await lstat(source)
7878
if (sourceStat.isDirectory()) {
7979
const files = await readdir(source)
@@ -124,7 +124,7 @@ const moveFileSync = (source, destination, options = {}, root = true, symlinks =
124124
try {
125125
renameSync(source, destination)
126126
} catch (error) {
127-
if (error.code === 'EXDEV') {
127+
if (error.code === 'EXDEV' || error.code === 'EPERM') {
128128
const sourceStat = lstatSync(source)
129129
if (sourceStat.isDirectory()) {
130130
const files = readdirSync(source)

package-lock.json

Lines changed: 6 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/async.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ t.test('move a file across devices', async t => {
8181
t.equal(fs.readFileSync(dest, 'utf8'), fixture)
8282
})
8383

84+
t.test('move a file across devices (EPERM)', async t => {
85+
const exdevError = new Error()
86+
exdevError.code = 'EPERM'
87+
const moveFile = requireInject('../', {
88+
fs: {
89+
...fs,
90+
rename: (s, d, cb) => process.nextTick(() => cb(exdevError)),
91+
},
92+
})
93+
94+
const dir = t.testdir({
95+
src: fixture,
96+
})
97+
const dest = `${dir}/dest`
98+
await moveFile(`${dir}/src`, dest)
99+
t.equal(fs.readFileSync(dest, 'utf8'), fixture)
100+
})
101+
84102
t.test('move a directory across devices', async t => {
85103
const exdevError = new Error()
86104
exdevError.code = 'EXDEV'
@@ -127,6 +145,52 @@ t.test('move a directory across devices', async t => {
127145
t.equal(fs.readlinkSync(`${dest}/abs`), process.platform === 'win32' ? `${process.cwd()}\\` : process.cwd(), 'kept the correct absolute path')
128146
})
129147

148+
t.test('move a directory across devices (EPERM)', async t => {
149+
const exdevError = new Error()
150+
exdevError.code = 'EXDEV'
151+
const moveFile = requireInject('../', {
152+
fs: {
153+
...fs,
154+
rename: (s, d, cb) => process.nextTick(() => cb(exdevError)),
155+
},
156+
})
157+
158+
const dir = t.testdir({
159+
src: {
160+
one: fixture,
161+
two: fixture,
162+
sub: {
163+
three: fixture,
164+
four: fixture,
165+
five: t.fixture('symlink', './four'),
166+
reallysub: {
167+
six: t.fixture('symlink', '../../one')
168+
}
169+
},
170+
link: t.fixture('symlink', './sub'),
171+
abs: t.fixture('symlink', process.cwd())
172+
}
173+
})
174+
const dest = `${dir}/dest`
175+
await moveFile(`${dir}/src`, dest)
176+
t.ok(fs.statSync(dest).isDirectory(), 'created a directory')
177+
t.equal(fs.readFileSync(`${dest}/one`, 'utf8'), fixture, 'copied file one')
178+
t.equal(fs.readFileSync(`${dest}/two`, 'utf8'), fixture, 'copied file two')
179+
t.ok(fs.statSync(`${dest}/sub`).isDirectory(), 'created the subdirectory')
180+
t.equal(fs.readFileSync(`${dest}/sub/three`, 'utf8'), fixture, 'copied file three')
181+
t.equal(fs.readFileSync(`${dest}/sub/four`, 'utf8'), fixture, 'copied file four')
182+
t.ok(fs.lstatSync(`${dest}/sub/five`).isSymbolicLink(), 'created a file symbolic link')
183+
t.equal(fs.readlinkSync(`${dest}/sub/five`).replace(/\\/g, '/'), './four', 'created file symlink')
184+
t.ok(fs.lstatSync(`${dest}/link`).isSymbolicLink(), 'created a directory symbolic link')
185+
// below assertion varies for windows because junctions are absolute paths
186+
t.equal(fs.readlinkSync(`${dest}/link`), process.platform === 'win32' ? join(dest, 'sub\\') : './sub', 'created the directory symbolic link with the correct target')
187+
t.ok(fs.lstatSync(`${dest}/sub/reallysub`).isDirectory(), 'created the innermost subdirectory')
188+
t.ok(fs.lstatSync(`${dest}/sub/reallysub/six`).isSymbolicLink(), 'created the innermost symlink')
189+
t.equal(fs.readlinkSync(`${dest}/sub/reallysub/six`).replace(/\\/g, '/'), '../../one', 'created the symlink with the appropriate target')
190+
t.ok(fs.lstatSync(`${dest}/abs`).isSymbolicLink(), 'created the absolute path symlink')
191+
t.equal(fs.readlinkSync(`${dest}/abs`), process.platform === 'win32' ? `${process.cwd()}\\` : process.cwd(), 'kept the correct absolute path')
192+
})
193+
130194
t.test('overwrite option', async t => {
131195
const dir = t.testdir({
132196
src: 'x',

test/sync.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ t.test('move a file across devices', async t => {
5858
t.equal(fs.readFileSync(dest, 'utf8'), fixture)
5959
})
6060

61+
t.test('move a file across devices (EPERM)', async t => {
62+
const exdevError = new Error()
63+
exdevError.code = 'EPERM'
64+
const moveFile = requireInject('../', {
65+
fs: {
66+
...fs,
67+
renameSync: () => { throw exdevError },
68+
},
69+
})
70+
71+
const dir = t.testdir({
72+
src: fixture,
73+
})
74+
const dest = `${dir}/dest`
75+
moveFile.sync(`${dir}/src`, dest)
76+
t.equal(fs.readFileSync(dest, 'utf8'), fixture)
77+
})
78+
6179
t.test('move a directory across devices', async t => {
6280
const exdevError = new Error()
6381
exdevError.code = 'EXDEV'
@@ -104,6 +122,52 @@ t.test('move a directory across devices', async t => {
104122
t.equal(fs.readlinkSync(`${dest}/abs`), process.platform === 'win32' ? `${process.cwd()}\\` : process.cwd(), 'kept the correct absolute path')
105123
})
106124

125+
t.test('move a directory across devices (EPERM)', async t => {
126+
const exdevError = new Error()
127+
exdevError.code = 'EXDEV'
128+
const moveFile = requireInject('../', {
129+
fs: {
130+
...fs,
131+
renameSync: () => { throw exdevError },
132+
},
133+
})
134+
135+
const dir = t.testdir({
136+
src: {
137+
one: fixture,
138+
two: fixture,
139+
sub: {
140+
three: fixture,
141+
four: fixture,
142+
five: t.fixture('symlink', './four'),
143+
reallysub: {
144+
six: t.fixture('symlink', '../../one')
145+
}
146+
},
147+
link: t.fixture('symlink', './sub'),
148+
abs: t.fixture('symlink', process.cwd())
149+
}
150+
})
151+
const dest = `${dir}/dest`
152+
moveFile.sync(`${dir}/src`, dest)
153+
t.ok(fs.statSync(dest).isDirectory(), 'created a directory')
154+
t.equal(fs.readFileSync(`${dest}/one`, 'utf8'), fixture, 'copied file one')
155+
t.equal(fs.readFileSync(`${dest}/two`, 'utf8'), fixture, 'copied file two')
156+
t.ok(fs.statSync(`${dest}/sub`).isDirectory(), 'created the subdirectory')
157+
t.equal(fs.readFileSync(`${dest}/sub/three`, 'utf8'), fixture, 'copied file three')
158+
t.equal(fs.readFileSync(`${dest}/sub/four`, 'utf8'), fixture, 'copied file four')
159+
t.ok(fs.lstatSync(`${dest}/sub/five`).isSymbolicLink(), 'created a file symbolic link')
160+
t.equal(fs.readlinkSync(`${dest}/sub/five`).replace(/\\/g, '/'), './four', 'created file symlink')
161+
t.ok(fs.lstatSync(`${dest}/link`).isSymbolicLink(), 'created a directory symbolic link')
162+
// below assertion varies for windows because junctions are absolute paths
163+
t.equal(fs.readlinkSync(`${dest}/link`), process.platform === 'win32' ? join(dest, 'sub\\') : './sub', 'created the directory symbolic link with the correct target')
164+
t.ok(fs.lstatSync(`${dest}/sub/reallysub`).isDirectory(), 'created the innermost subdirectory')
165+
t.ok(fs.lstatSync(`${dest}/sub/reallysub/six`).isSymbolicLink(), 'created the innermost symlink')
166+
t.equal(fs.readlinkSync(`${dest}/sub/reallysub/six`).replace(/\\/g, '/'), '../../one', 'created the symlink with the appropriate target')
167+
t.ok(fs.lstatSync(`${dest}/abs`).isSymbolicLink(), 'created the absolute path symlink')
168+
t.equal(fs.readlinkSync(`${dest}/abs`), process.platform === 'win32' ? `${process.cwd()}\\` : process.cwd(), 'kept the correct absolute path')
169+
})
170+
107171
t.test('other types of errors fail', async t => {
108172
const randoError = new Error()
109173
randoError.code = 'ERANDO'

0 commit comments

Comments
 (0)