Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"extends": [
"eslint:recommended"
],
"parserOptions": {
"ecmaVersion": 2017,
},
"rules": {
"quotes": ["error", "single"],
"dot-notation": "off",
Expand Down
118 changes: 50 additions & 68 deletions lib/copy.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
'use strict';

var Promise = global.Promise || require('promise');

var fs = require('graceful-fs');
var path = require('path');
var EventEmitter = require('events').EventEmitter;
var pify = require('pify');
var mkdirp = require('mkdirp');
var rimraf = require('rimraf');
var fs = require('node:fs');
var path = require('node:path');
var EventEmitter = require('node:events');
var junk = require('junk');
var errno = require('errno');
var maximatch = require('maximatch');
Expand All @@ -27,13 +22,14 @@ var EVENT_COPY_FILE_START = 'copyFileStart';
var EVENT_COPY_FILE_ERROR = 'copyFileError';
var EVENT_COPY_FILE_COMPLETE = 'copyFileComplete';

var mkdir = pify(mkdirp, Promise);
var stat = pify(fs.stat, Promise);
var lstat = pify(fs.lstat, Promise);
var readlink = pify(fs.readlink, Promise);
var symlink = pify(fs.symlink, Promise);
var readdir = pify(fs.readdir, Promise);
var remove = pify(rimraf, Promise);
var mkdirp = path => fs.promises.mkdir(path, { recursive: true });
var mkdir = mkdirp;
var stat = fs.promises.stat;
var lstat = fs.promises.lstat;
var readlink = fs.promises.readlink;
var symlink = fs.promises.symlink;
var readdir = fs.promises.readdir;
var remove = path => fs.promises.rm(path, { recursive: true, force: true });

module.exports = function(src, dest, options, callback) {
if ((arguments.length === 3) && (typeof options === 'function')) {
Expand Down Expand Up @@ -145,18 +141,16 @@ function batch(inputs, iteratee, options) {
});
}

function getFilePaths(src, shouldExpandSymlinks) {
return (shouldExpandSymlinks ? stat : lstat)(src)
.then(function(stats) {
if (stats.isDirectory()) {
return getFileListing(src, shouldExpandSymlinks)
.then(function(filenames) {
return [src].concat(filenames);
});
} else {
return [src];
}
});
async function getFilePaths(src, shouldExpandSymlinks) {
const method = shouldExpandSymlinks ? stat : lstat
const stats = await method(src)

if (stats.isDirectory()) {
const filenames = await getFileListing(src, shouldExpandSymlinks)
return [src, ...filenames];
} else {
return [src];
}
}

function getFilteredPaths(paths, filter, options) {
Expand All @@ -182,32 +176,27 @@ function ensureDirectoryExists(path) {
return mkdir(path);
}

function getFileListing(srcPath, shouldExpandSymlinks) {
return readdir(srcPath)
.then(function(filenames) {
return Promise.all(
filenames.map(function(filename) {
var filePath = path.join(srcPath, filename);
return (shouldExpandSymlinks ? stat : lstat)(filePath)
.then(function(stats) {
if (stats.isDirectory()) {
return getFileListing(filePath, shouldExpandSymlinks)
.then(function(childPaths) {
return [filePath].concat(childPaths);
});
} else {
return [filePath];
}
});
})
)
.then(function mergeArrays(arrays) {
return Array.prototype.concat.apply([], arrays);
});
});
async function getFileListing(srcPath, shouldExpandSymlinks) {
const method = shouldExpandSymlinks ? stat : lstat;
const filenames = await readdir(srcPath);
const arrays = await Promise.all(
filenames.map(async function(filename) {
const filePath = path.join(srcPath, filename);
const stats = await method(filePath);

if (stats.isDirectory()) {
const childPaths = await getFileListing(filePath, shouldExpandSymlinks);
return [filePath, ...childPaths];
} else {
return [filePath];
}
})
);

return arrays.flat();
}

function copy(srcPath, destPath, hasFinished, emitEvent, options) {
async function copy(srcPath, destPath, hasFinished, emitEvent, options) {
if (options.debug) { log('Preparing to copy ' + srcPath + '…'); }
return prepareForCopy(srcPath, destPath, options)
.then(function(stats) {
Expand All @@ -233,37 +222,30 @@ function copy(srcPath, destPath, hasFinished, emitEvent, options) {
});
}

function prepareForCopy(srcPath, destPath, options) {
var shouldExpandSymlinks = Boolean(options.expand);
var shouldOverwriteExistingFiles = Boolean(options.overwrite);
return (shouldExpandSymlinks ? stat : lstat)(srcPath)
.then(function(stats) {
return ensureDestinationIsWritable(destPath, stats, shouldOverwriteExistingFiles)
.then(function() {
return stats;
});
});
async function prepareForCopy(srcPath, destPath, options) {
const method = (options.expand ? stat : lstat)
const shouldOverwriteExistingFiles = Boolean(options.overwrite);
const stats = await method(srcPath)

await ensureDestinationIsWritable(destPath, stats, shouldOverwriteExistingFiles);
return stats;
}

function ensureDestinationIsWritable(destPath, srcStats, shouldOverwriteExistingFiles) {
async function ensureDestinationIsWritable(destPath, srcStats, shouldOverwriteExistingFiles) {
return lstat(destPath)
.catch(function(error) {
var shouldIgnoreError = error.code === 'ENOENT';
if (shouldIgnoreError) { return null; }
throw error;
})
.then(function(destStats) {
var destExists = Boolean(destStats);
if (!destExists) { return true; }
if (!destStats) { return true; }

var isMergePossible = srcStats.isDirectory() && destStats.isDirectory();
if (isMergePossible) { return true; }

if (shouldOverwriteExistingFiles) {
return remove(destPath)
.then(function(paths) {
return true;
});
return remove(destPath).then(() => true);
} else {
throw fsError('EEXIST', destPath);
}
Expand Down
Loading