Skip to content

Commit 3120c5c

Browse files
authored
copy*(): remove copyFileFallback (#755)
* copy: remove copyFileFallback * copy-sync: remove copyFileFallback
1 parent 3c3865c commit 3120c5c

File tree

4 files changed

+75
-82
lines changed

4 files changed

+75
-82
lines changed

lib/copy-sync/__tests__/copy-sync-preserve-timestamp.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ describeIfPractical('copySync() - preserveTimestamps option', () => {
6363
assert.strictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'different mtime values')
6464
assert.strictEqual(toStat.atime.getTime(), fromStat.atime.getTime(), 'different atime values')
6565
} else {
66-
assert.notStrictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'same mtime values')
6766
// the access time might actually be the same, so check only modification time
67+
assert.notStrictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'same mtime values')
6868
}
6969
}
7070
}

lib/copy-sync/copy-sync.js

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const fs = require('graceful-fs')
44
const path = require('path')
5-
const mkdirpSync = require('../mkdirs').mkdirsSync
5+
const mkdirsSync = require('../mkdirs').mkdirsSync
66
const utimesMillisSync = require('../util/utimes').utimesMillisSync
77
const stat = require('../util/stat')
88

@@ -29,7 +29,7 @@ function copySync (src, dest, opts) {
2929
function handleFilterAndCopy (destStat, src, dest, opts) {
3030
if (opts.filter && !opts.filter(src, dest)) return
3131
const destParent = path.dirname(dest)
32-
if (!fs.existsSync(destParent)) mkdirpSync(destParent)
32+
if (!fs.existsSync(destParent)) mkdirsSync(destParent)
3333
return startCopy(destStat, src, dest, opts)
3434
}
3535

@@ -64,63 +64,51 @@ function mayCopyFile (srcStat, src, dest, opts) {
6464
}
6565

6666
function copyFile (srcStat, src, dest, opts) {
67-
if (typeof fs.copyFileSync === 'function') {
68-
fs.copyFileSync(src, dest)
69-
if (opts.preserveTimestamps && (srcStat.mode & 0o200) === 0) {
70-
// Make sure the file is writable before setting the timestamp
71-
// otherwise openSync fails with EPERM when invoked with 'r+'
72-
// (through utimes call)
73-
fs.chmodSync(dest, srcStat.mode | 0o200)
74-
}
75-
return setDestTimestampsAndMode(srcStat, src, dest, opts)
76-
}
77-
return copyFileFallback(srcStat, src, dest, opts)
67+
fs.copyFileSync(src, dest)
68+
if (opts.preserveTimestamps) handleTimestamps(srcStat.mode, src, dest)
69+
return setDestMode(dest, srcStat.mode)
7870
}
7971

80-
function copyFileFallback (srcStat, src, dest, opts) {
81-
const BUF_LENGTH = 64 * 1024
82-
const _buff = require('../util/buffer')(BUF_LENGTH)
83-
84-
const fdr = fs.openSync(src, 'r')
85-
const fdw = fs.openSync(dest, 'w')
86-
let pos = 0
72+
function handleTimestamps (srcMode, src, dest) {
73+
// Make sure the file is writable before setting the timestamp
74+
// otherwise open fails with EPERM when invoked with 'r+'
75+
// (through utimes call)
76+
if (fileIsNotWritable(srcMode)) makeFileWritable(dest, srcMode)
77+
return setDestTimestamps(src, dest)
78+
}
8779

88-
while (pos < srcStat.size) {
89-
const bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos)
90-
fs.writeSync(fdw, _buff, 0, bytesRead)
91-
pos += bytesRead
92-
}
80+
function fileIsNotWritable (srcMode) {
81+
return (srcMode & 0o200) === 0
82+
}
9383

94-
setDestTimestampsAndMode(srcStat, src, fdw, opts)
84+
function makeFileWritable (dest, srcMode) {
85+
return setDestMode(dest, srcMode | 0o200)
86+
}
9587

96-
fs.closeSync(fdr)
97-
fs.closeSync(fdw)
88+
function setDestMode (dest, srcMode) {
89+
return fs.chmodSync(dest, srcMode)
9890
}
9991

100-
function setDestTimestampsAndMode (srcStat, src, dest, opts) {
101-
const utimesSync = typeof dest === 'string' ? utimesMillisSync : fs.futimesSync
102-
const chmodSync = typeof dest === 'string' ? fs.chmodSync : fs.fchmodSync
103-
if (opts.preserveTimestamps) {
104-
// The initial srcStat.atime cannot be trusted because it is modified by the read(2) system call
105-
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
106-
const updatedSrcStat = fs.statSync(src)
107-
utimesSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime)
108-
}
109-
chmodSync(dest, srcStat.mode)
92+
function setDestTimestamps (src, dest) {
93+
// The initial srcStat.atime cannot be trusted
94+
// because it is modified by the read(2) system call
95+
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
96+
const updatedSrcStat = fs.statSync(src)
97+
return utimesMillisSync(dest, updatedSrcStat.atime, updatedSrcStat.mtime)
11098
}
11199

112100
function onDir (srcStat, destStat, src, dest, opts) {
113-
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts)
101+
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts)
114102
if (destStat && !destStat.isDirectory()) {
115103
throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)
116104
}
117105
return copyDir(src, dest, opts)
118106
}
119107

120-
function mkDirAndCopy (srcStat, src, dest, opts) {
108+
function mkDirAndCopy (srcMode, src, dest, opts) {
121109
fs.mkdirSync(dest)
122110
copyDir(src, dest, opts)
123-
return fs.chmodSync(dest, srcStat.mode)
111+
return setDestMode(dest, srcMode)
124112
}
125113

126114
function copyDir (src, dest, opts) {

lib/copy/__tests__/copy-preserve-timestamp.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ describeIfPractical('copy() - preserve timestamp', () => {
6666
assert.strictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'different mtime values')
6767
assert.strictEqual(toStat.atime.getTime(), fromStat.atime.getTime(), 'different atime values')
6868
} else {
69-
assert.notStrictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'same mtime values')
7069
// the access time might actually be the same, so check only modification time
70+
assert.notStrictEqual(toStat.mtime.getTime(), fromStat.mtime.getTime(), 'same mtime values')
7171
}
7272
}
7373
}

lib/copy/copy.js

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const fs = require('graceful-fs')
44
const path = require('path')
5-
const mkdirp = require('../mkdirs').mkdirs
5+
const mkdirs = require('../mkdirs').mkdirs
66
const pathExists = require('../path-exists').pathExists
77
const utimesMillis = require('../util/utimes').utimesMillis
88
const stat = require('../util/stat')
@@ -43,7 +43,7 @@ function checkParentDir (destStat, src, dest, opts, cb) {
4343
pathExists(destParent, (err, dirExists) => {
4444
if (err) return cb(err)
4545
if (dirExists) return startCopy(destStat, src, dest, opts, cb)
46-
mkdirp(destParent, err => {
46+
mkdirs(destParent, err => {
4747
if (err) return cb(err)
4848
return startCopy(destStat, src, dest, opts, cb)
4949
})
@@ -92,64 +92,69 @@ function mayCopyFile (srcStat, src, dest, opts, cb) {
9292
}
9393

9494
function copyFile (srcStat, src, dest, opts, cb) {
95-
if (typeof fs.copyFile === 'function') {
96-
return fs.copyFile(src, dest, err => {
95+
fs.copyFile(src, dest, err => {
96+
if (err) return cb(err)
97+
if (opts.preserveTimestamps) return handleTimestampsAndMode(srcStat.mode, src, dest, cb)
98+
return setDestMode(dest, srcStat.mode, cb)
99+
})
100+
}
101+
102+
function handleTimestampsAndMode (srcMode, src, dest, cb) {
103+
// Make sure the file is writable before setting the timestamp
104+
// otherwise open fails with EPERM when invoked with 'r+'
105+
// (through utimes call)
106+
if (fileIsNotWritable(srcMode)) {
107+
return makeFileWritable(dest, srcMode, err => {
97108
if (err) return cb(err)
98-
if (opts.preserveTimestamps && (srcStat.mode & 0o200) === 0) {
99-
// Make sure the file is writable before setting the timestamp
100-
// otherwise openSync fails with EPERM when invoked with 'r+'
101-
// (through utimes call)
102-
return fs.chmod(dest, srcStat.mode | 0o200, (err) => {
103-
if (err) return cb(err)
104-
return setDestTimestampsAndMode(srcStat, src, dest, opts, cb)
105-
})
106-
}
107-
return setDestTimestampsAndMode(srcStat, src, dest, opts, cb)
109+
return setDestTimestampsAndMode(srcMode, src, dest, cb)
108110
})
109111
}
110-
return copyFileFallback(srcStat, src, dest, opts, cb)
112+
return setDestTimestampsAndMode(srcMode, src, dest, cb)
111113
}
112114

113-
function copyFileFallback (srcStat, src, dest, opts, cb) {
114-
const rs = fs.createReadStream(src)
115-
rs.on('error', err => cb(err)).once('open', () => {
116-
// explicitly not setting srcStat mode - will do that last
117-
const ws = fs.createWriteStream(dest)
118-
ws.on('error', err => cb(err))
119-
.on('open', () => rs.pipe(ws))
120-
.once('close', () => setDestTimestampsAndMode(srcStat, src, dest, opts, cb))
115+
function fileIsNotWritable (srcMode) {
116+
return (srcMode & 0o200) === 0
117+
}
118+
119+
function makeFileWritable (dest, srcMode, cb) {
120+
return setDestMode(dest, srcMode | 0o200, cb)
121+
}
122+
123+
function setDestTimestampsAndMode (srcMode, src, dest, cb) {
124+
setDestTimestamps(src, dest, err => {
125+
if (err) return cb(err)
126+
return setDestMode(dest, srcMode, cb)
121127
})
122128
}
123129

124-
function setDestTimestampsAndMode (srcStat, src, dest, opts, cb) {
125-
if (opts.preserveTimestamps) {
126-
// The initial srcStat.atime cannot be trusted because it is modified by the read(2) system call
127-
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
128-
return fs.stat(src, (err, updatedSrcStat) => {
129-
if (err) return cb(err)
130-
return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, (err2) => {
131-
if (err2) return cb(err2)
132-
return fs.chmod(dest, srcStat.mode, cb)
133-
})
134-
})
135-
}
136-
return fs.chmod(dest, srcStat.mode, cb)
130+
function setDestMode (dest, srcMode, cb) {
131+
return fs.chmod(dest, srcMode, cb)
132+
}
133+
134+
function setDestTimestamps (src, dest, cb) {
135+
// The initial srcStat.atime cannot be trusted
136+
// because it is modified by the read(2) system call
137+
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
138+
fs.stat(src, (err, updatedSrcStat) => {
139+
if (err) return cb(err)
140+
return utimesMillis(dest, updatedSrcStat.atime, updatedSrcStat.mtime, cb)
141+
})
137142
}
138143

139144
function onDir (srcStat, destStat, src, dest, opts, cb) {
140-
if (!destStat) return mkDirAndCopy(srcStat, src, dest, opts, cb)
145+
if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts, cb)
141146
if (destStat && !destStat.isDirectory()) {
142147
return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
143148
}
144149
return copyDir(src, dest, opts, cb)
145150
}
146151

147-
function mkDirAndCopy (srcStat, src, dest, opts, cb) {
152+
function mkDirAndCopy (srcMode, src, dest, opts, cb) {
148153
fs.mkdir(dest, err => {
149154
if (err) return cb(err)
150155
copyDir(src, dest, opts, err => {
151156
if (err) return cb(err)
152-
return fs.chmod(dest, srcStat.mode, cb)
157+
return setDestMode(dest, srcMode, cb)
153158
})
154159
})
155160
}

0 commit comments

Comments
 (0)