Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 31 additions & 40 deletions lib/copy/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,22 @@ async function copy (src, dest, opts = {}) {

if (!include) return

return checkParentDir(destStat, src, dest, opts)
}

async function checkParentDir (destStat, src, dest, opts) {
// check if the parent of dest exists, and create it if it doesn't exist
const destParent = path.dirname(dest)

const dirExists = await pathExists(destParent)

if (!dirExists) {
await mkdirs(destParent)
}

return getStats(destStat, src, dest, opts)
await getStatsAndPerformCopy(destStat, src, dest, opts)
}

async function runFilter (src, dest, opts) {
if (!opts.filter) return true
return opts.filter(src, dest)
}

async function getStats (destStat, src, dest, opts) {
async function getStatsAndPerformCopy (destStat, src, dest, opts) {
const statFn = opts.dereference ? fs.stat : fs.lstat
const srcStat = await statFn(src)

Expand Down Expand Up @@ -101,19 +96,10 @@ async function handleTimestampsAndMode (srcMode, src, dest) {
if (fileIsNotWritable(srcMode)) {
await makeFileWritable(dest, srcMode)
}
return setDestTimestampsAndMode(srcMode, src, dest)
}

function fileIsNotWritable (srcMode) {
return (srcMode & 0o200) === 0
}
// Set timestamps and mode correspondingly

function makeFileWritable (dest, srcMode) {
return setDestMode(dest, srcMode | 0o200)
}

async function setDestTimestampsAndMode (srcMode, src, dest) {
// The initial srcStat.atime cannot be trusted
// Note that The initial srcStat.atime cannot be trusted
// because it is modified by the read(2) system call
// (See https://nodejs.org/api/fs.html#fs_stat_time_values)
const updatedSrcStat = await fs.stat(src)
Expand All @@ -122,43 +108,47 @@ async function setDestTimestampsAndMode (srcMode, src, dest) {
return setDestMode(dest, srcMode)
}

function fileIsNotWritable (srcMode) {
return (srcMode & 0o200) === 0
}

function makeFileWritable (dest, srcMode) {
return setDestMode(dest, srcMode | 0o200)
}

function setDestMode (dest, srcMode) {
return fs.chmod(dest, srcMode)
}

async function onDir (srcStat, destStat, src, dest, opts) {
// the dest direcotry might not exist, create it
if (!destStat) {
await fs.mkdir(dest)
}
await copyDir(src, dest, opts)
if (!destStat) {
await setDestMode(dest, srcStat.mode)
}
}

async function copyDir (src, dest, opts) {
const items = await fs.readdir(src)
return copyDirItems(items, src, dest, opts)
}

function copyDirItems (items, src, dest, opts) {
const item = items.pop()
if (!item) return
return copyDirItem(items, item, src, dest, opts)
}
// loop through the files in the current directory to copy everything
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i]

async function copyDirItem (items, item, src, dest, opts) {
const srcItem = path.join(src, item)
const destItem = path.join(dest, item)
const srcItem = path.join(src, item)
const destItem = path.join(dest, item)

const include = await runFilter(srcItem, destItem, opts)
if (!include) return copyDirItems(items, src, dest, opts)
// skip the item if it is matches by the filter function
const include = await runFilter(srcItem, destItem, opts)
if (!include) continue

const { destStat } = await stat.checkPathsAsync(srcItem, destItem, 'copy', opts)
const { destStat } = await stat.checkPathsAsync(srcItem, destItem, 'copy', opts)

await getStats(destStat, srcItem, destItem, opts)
// If the item is a copyable file, `getStatsAndPerformCopy` will copy it
// If the item is a directory, `getStatsAndPerformCopy` will call `onDir` recursively
await getStatsAndPerformCopy(destStat, srcItem, destItem, opts)
}

return copyDirItems(items, src, dest, opts)
if (!destStat) {
await setDestMode(dest, srcStat.mode)
}
}

async function onLink (destStat, src, dest, opts) {
Expand Down Expand Up @@ -194,6 +184,7 @@ async function onLink (destStat, src, dest, opts) {
throw new Error(`Cannot overwrite '${resolvedDest}' with '${resolvedSrc}'.`)
}

// copy the link
await fs.unlink(dest)
return fs.symlink(resolvedSrc, dest)
}
Expand Down