Browse Source

Add native fs.copyFile to copy()

ci/travis-osximage
Mani Maghsoudlou 7 years ago
parent
commit
0bd52793a2
  1. 59
      lib/copy/copy.js

59
lib/copy/copy.js

@ -75,7 +75,7 @@ function onFile (srcStat, src, dest, opts, cb) {
checkDest(dest, (err, resolvedPath) => {
if (err) return cb(err)
if (resolvedPath === notExist) {
return cpFile(srcStat, src, dest, opts, cb)
return copyFile(srcStat, src, dest, opts, cb)
} else if (resolvedPath === existsReg) {
return mayCopyFile(srcStat, src, dest, opts, cb)
} else {
@ -89,30 +89,41 @@ function mayCopyFile (srcStat, src, dest, opts, cb) {
if (opts.overwrite) {
fs.unlink(dest, err => {
if (err) return cb(err)
return cpFile(srcStat, src, dest, opts, cb)
return copyFile(srcStat, src, dest, opts, cb)
})
} else if (opts.errorOnExist) {
return cb(new Error(`'${dest}' already exists`))
} else return cb()
}
function cpFile (srcStat, src, dest, opts, cb) {
function copyFile (srcStat, src, dest, opts, cb) {
if (typeof fs.copyFile === 'function') {
return fs.copyFile(src, dest, err => {
if (err) return cb(err)
return handleDestModeAndTimestamps(srcStat, dest, opts, cb)
})
}
return copyFileFallback(srcStat, src, dest, opts, cb)
}
function copyFileFallback (srcStat, src, dest, opts, cb) {
const rs = fs.createReadStream(src)
const ws = fs.createWriteStream(dest, { mode: srcStat.mode })
rs.on('error', err => cb(err))
ws.on('error', err => cb(err))
ws.on('open', () => {
rs.pipe(ws)
}).once('close', () => {
fs.chmod(dest, srcStat.mode, err => {
if (err) return cb(err)
if (opts.preserveTimestamps) {
return utimes(dest, srcStat.atime, srcStat.mtime, cb)
}
return cb()
})
ws.on('open', () => rs.pipe(ws))
.once('close', () => handleDestModeAndTimestamps(srcStat, dest, opts, cb))
}
function handleDestModeAndTimestamps (srcStat, dest, opts, cb) {
fs.chmod(dest, srcStat.mode, err => {
if (err) return cb(err)
if (opts.preserveTimestamps) {
return utimes(dest, srcStat.atime, srcStat.mtime, cb)
}
return cb()
})
}
@ -131,7 +142,7 @@ function onDir (srcStat, src, dest, opts, cb) {
return mayCopyDir(src, dest, opts, cb)
} else {
if (src === resolvedPath) return cb()
return cpDir(src, dest, opts, cb)
return copyDir(src, dest, opts, cb)
}
})
}
@ -142,7 +153,7 @@ function mayCopyDir (src, dest, opts, cb) {
if (!st.isDirectory()) {
return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`))
}
return cpDir(src, dest, opts, cb)
return copyDir(src, dest, opts, cb)
})
}
@ -151,24 +162,24 @@ function mkDirAndCopy (srcStat, src, dest, opts, cb) {
if (err) return cb(err)
fs.chmod(dest, srcStat.mode, err => {
if (err) return cb(err)
return cpDir(src, dest, opts, cb)
return copyDir(src, dest, opts, cb)
})
})
}
function cpDir (src, dest, opts, cb) {
function copyDir (src, dest, opts, cb) {
fs.readdir(src, (err, items) => {
if (err) return cb(err)
return cpDirItems(items, src, dest, opts, cb)
return copyDirItems(items, src, dest, opts, cb)
})
}
function cpDirItems (items, src, dest, opts, cb) {
function copyDirItems (items, src, dest, opts, cb) {
const item = items.pop()
if (!item) return cb()
startCopy(path.join(src, item), path.join(dest, item), opts, err => {
if (err) return cb(err)
return cpDirItems(items, src, dest, opts, cb)
return copyDirItems(items, src, dest, opts, cb)
})
}
@ -201,27 +212,27 @@ function onLink (src, dest, opts, cb) {
if (st.isDirectory() && isSrcSubdir(resolvedDestPath, resolvedSrcPath)) {
return cb(new Error(`Cannot overwrite '${resolvedDestPath}' with '${resolvedSrcPath}'.`))
}
return cpLink(resolvedSrcPath, dest, cb)
return copyLink(resolvedSrcPath, dest, cb)
})
}
})
})
}
function cpLink (resolvedSrcPath, dest, cb) {
function copyLink (resolvedSrcPath, dest, cb) {
fs.unlink(dest, err => {
if (err) return cb(err)
return fs.symlink(resolvedSrcPath, dest, cb)
})
}
// check dest to see if it exists and/or is a symlink
// check if dest exists and/or is a symlink
function checkDest (dest, cb) {
fs.readlink(dest, (err, resolvedPath) => {
if (err) {
if (err.code === 'ENOENT') return cb(null, notExist)
// dest exists and is a regular file or directory, Windows throws UNKNOWN error.
// dest exists and is a regular file or directory, Windows may throw UNKNOWN error.
if (err.code === 'EINVAL' || err.code === 'UNKNOWN') return cb(null, existsReg)
return cb(err)

Loading…
Cancel
Save