Skip to content

Commit 75f2091

Browse files
committed
refactor: move copyDirectory to own file for testability
Signed-off-by: David Sanders <dsanders11@ucsbalum.com>
1 parent 19da158 commit 75f2091

2 files changed

Lines changed: 44 additions & 36 deletions

File tree

lib/copy-directory.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'strict'
2+
3+
const { promises: fs } = require('graceful-fs')
4+
const path = require('path')
5+
6+
const { backOff } = require('exponential-backoff')
7+
8+
async function copyDirectory (src, dest, ensure = false) {
9+
try {
10+
await fs.stat(src)
11+
} catch {
12+
throw new Error(`Missing source directory for copy: ${src}`)
13+
}
14+
await fs.mkdir(dest, { recursive: true })
15+
const entries = await fs.readdir(src, { withFileTypes: true })
16+
for (const entry of entries) {
17+
if (entry.isDirectory()) {
18+
await copyDirectory(path.join(src, entry.name), path.join(dest, entry.name))
19+
} else if (entry.isFile()) {
20+
// with parallel installs, copying files may cause file errors on
21+
// Windows so use an exponential backoff to resolve collisions
22+
await backOff(async () => {
23+
try {
24+
await fs.copyFile(path.join(src, entry.name), path.join(dest, entry.name))
25+
} catch (err) {
26+
// if ensure, check if file already exists and that's good enough
27+
if (ensure && err.code === 'EBUSY') {
28+
try {
29+
await fs.stat(path.join(dest, entry.name))
30+
return
31+
} catch {}
32+
}
33+
throw err
34+
}
35+
})
36+
} else {
37+
throw new Error('Unexpected file directory entry type')
38+
}
39+
}
40+
}
41+
42+
module.exports = copyDirectory

lib/install.js

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
const { createWriteStream, promises: fs } = require('graceful-fs')
44
const os = require('os')
5-
const { backOff } = require('exponential-backoff')
65
const tar = require('tar')
76
const path = require('path')
87
const { Transform, promises: { pipeline } } = require('stream')
98
const crypto = require('crypto')
109
const log = require('./log')
1110
const semver = require('semver')
11+
const copyDirectory = require('./copy-directory')
1212
const { download } = require('./download')
1313
const processRelease = require('./process-release')
1414

@@ -119,40 +119,6 @@ async function install (gyp, argv) {
119119
}
120120
}
121121

122-
async function copyDirectory (src, dest) {
123-
try {
124-
await fs.stat(src)
125-
} catch {
126-
throw new Error(`Missing source directory for copy: ${src}`)
127-
}
128-
await fs.mkdir(dest, { recursive: true })
129-
const entries = await fs.readdir(src, { withFileTypes: true })
130-
for (const entry of entries) {
131-
if (entry.isDirectory()) {
132-
await copyDirectory(path.join(src, entry.name), path.join(dest, entry.name))
133-
} else if (entry.isFile()) {
134-
// with parallel installs, copying files may cause file errors on
135-
// Windows so use an exponential backoff to resolve collisions
136-
await backOff(async () => {
137-
try {
138-
await fs.copyFile(path.join(src, entry.name), path.join(dest, entry.name))
139-
} catch (err) {
140-
// if ensure, check if file already exists and that's good enough
141-
if (gyp.opts.ensure && err.code === 'EBUSY') {
142-
try {
143-
await fs.stat(path.join(dest, entry.name))
144-
return
145-
} catch {}
146-
}
147-
throw err
148-
}
149-
})
150-
} else {
151-
throw new Error('Unexpected file directory entry type')
152-
}
153-
}
154-
}
155-
156122
async function go () {
157123
log.verbose('ensuring devDir is created', devDir)
158124

@@ -277,7 +243,7 @@ async function install (gyp, argv) {
277243
}
278244

279245
// copy over the files from the temp tarball extract directory to devDir
280-
await copyDirectory(tarExtractDir, devDir)
246+
await copyDirectory(tarExtractDir, devDir, gyp.opts.ensure)
281247
} finally {
282248
try {
283249
// try to cleanup temp dir

0 commit comments

Comments
 (0)