From d54e0c1c895f9abae46da91a535ff0147dc298b2 Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Thu, 19 Jul 2018 18:37:04 -0700 Subject: [PATCH 1/2] backport Upgrade copyTree #125 with targetFs.exists review --- README.md | 12 ++++++++- fs-common.js | 76 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index cd115ab..b30a6b7 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,21 @@ directory. Returns a promise for the completion of the operation. -### copyTree(source, target) +### copyTree(source, target, {targetFs?, include?}) Copies a file or tree of files from one path to another. Symbolic links are copied but not followed. +Optionally copies to the given target file system. +Any file system that implements the Q-IO file system interface will suffice, +including a mock file system. + +Optionally includes only copies entries that pass the given include test. +The test may return true, false, or a promise for true or false. +The include test receives the name and stats of the entry, including symbolic +link entries. +The entry name is not fully qualified. + Returns a promise for the completion of the operation. ### list(path) diff --git a/fs-common.js b/fs-common.js index c5e83a1..da05517 100644 --- a/fs-common.js +++ b/fs-common.js @@ -157,34 +157,54 @@ exports.update = function (exports, workingDirectory) { }); }; - exports.copyTree = function (source, target) { - var self = this; - return Q.when(self.stat(source), function (stat) { - if (stat.isFile()) { - return self.copy(source, target); - } else if (stat.isDirectory()) { - return self.exists(target).then(function (targetExists) { - function copySubTree() { - return Q.when(self.list(source), function (list) { - return Q.all(list.map(function (child) { - return self.copyTree( - self.join(source, child), - self.join(target, child) - ); - })); - }); - } - if (targetExists) { - return copySubTree(); - } else { - return Q.when(self.makeDirectory(target, stat.node.mode), copySubTree); - } - }); - } else if (stat.isSymbolicLink()) { - // TODO copy the link and type with readPath (but what about - // Windows junction type?) - return self.symbolicCopy(source, target); - } + exports.copyTree = function (source, target, options) { + var sourceFs = this; + options = options || {}; + targetFs = options.targetFs || sourceFs; + includeTest = options.include || returnTrue; + return sourceFs.statLink(source).then(function (stat) { + var include = includeTest(source, stat); + return Q(include).then(function (include) { + if (!include) return; + if (stat.isFile()) { + return sourceFs.copy(source, target); + } else if (stat.isDirectory()) { + return targetFs.exists(target).then(function (targetExists) { + function copySubTree() { + return sourceFs.list(source).then(function (list) { + return Q.all(list.map(function (child) { + return sourceFs.copyTree( + sourceFs.join(source, child), + targetFs.join(target, child), + options + ); + })); + }); + } + if (targetExists) { + return copySubTree(); + } else { + return targetFs.makeDirectory(target, stat.node.mode) + .then(copySubTree); + } + }); + } else if (stat.isSymbolicLink()) { + // Convert symbolic links to relative links and replicate on the + // target file system. + return sourceFs.isDirectory(source) + .then(function (isDirectory) { + var relative, type; + if (isDirectory) { + relative = sourceFs.relativeFromDirectory(source, target); + type = "directory"; + } else { + relative = sourceFs.relativeFromFile(source, target); + type = "file"; + } + return targetFs.symbolicLink(target, relative, type); + }) + } + }); }); }; From 3dc7c87f44332b465fe10d6b038b35d0f8d5b2a2 Mon Sep 17 00:00:00 2001 From: Harold Thetiot Date: Thu, 19 Jul 2018 19:07:35 -0700 Subject: [PATCH 2/2] fix ReferenceError: returnTrue is not defined --- fs-common.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs-common.js b/fs-common.js index da05517..130eb71 100644 --- a/fs-common.js +++ b/fs-common.js @@ -157,6 +157,10 @@ exports.update = function (exports, workingDirectory) { }); }; + function returnTrue () { + return true; + } + exports.copyTree = function (source, target, options) { var sourceFs = this; options = options || {};