From 878b5aee0777c47cd886748310dd0d96f140ee6e Mon Sep 17 00:00:00 2001 From: Jacob O'Toole Date: Sat, 22 Apr 2017 09:17:04 +0100 Subject: [PATCH 01/14] fs: add fs.copy, fs.copySync, fs.delete and fs.deleteSync with docs and tests. So I and many other often need to recursively copy or delete directory's with node and copy file that keep their permissions and properties etc. Many use an external library or write their own and that takes up a lot of time and adds deps to your project which you might not want. I have added fs.copy and fs.copySync to recursively copy directory's or just copy files, all files/directory's copied with fs.copy and fs.copySync retain they owners, mode and times. fs.delete and fs.deleteSync either delete a file (basically an alias for fs.unlink) or of a directory is passed into the path recursively remove the content of the directory and remove the directory itself. There are however a few notes, this is writen in JavaScript only and thus calls other functions in the fs module, I have placed the code at the bottom of lib/fs.js however there may be a better place to put the code. I also change open the directory's for copying in different modes dependent on the platform, I use 'process.platform==="win32"?"r+":"r"' to determine the mode to open the directory in, I have done this because I found during testing that on Windows, you need to have the directory open in r+ mode to modify it's properties whereas on Linux it throws when you attempt to open a directory in r+ mode & you can open it in r mode and still change the properties. I don't have a Mac OS computer & thus cannot test it on Mac so this mode could be wrong on Mac. I also use read streams and write streams in fs.copy however I use fs.readFileSync to read the file in fs.copySync, I know that this could load the entire file into the main memory and thus not be a great way of doing it however I am not sure how to do this better. So advise on this would be helpful. I have also used readable.on('end') to determine when the copying of the file contents has ended, however I have seen the finish event used in some other cases, the end event seems to work to I haven't changed it but again that is something that might need changing. My tests are relatively simplistic however they do test the copying. I haven't got a test for the overwrite mode being a function however I can write that if it is needed. Hope this is OK, Jacob --- doc/api/fs.md | 64 ++ lib/fs.js | 854 +++++++++++++++++++++++ test/parallel/test-fs-copy-and-delete.js | 118 ++++ 3 files changed, 1036 insertions(+) create mode 100644 test/parallel/test-fs-copy-and-delete.js diff --git a/doc/api/fs.md b/doc/api/fs.md index f3828f15e70baa..7089c42f68802e 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -599,6 +599,48 @@ Returns an object containing commonly used constants for file system operations. The specific constants currently defined are described in [FS Constants][]. +## fs.copy(path1, path2, overwrite_mode, callback) + +* `path1` {string} +* `path2` {string} +* `overwrite_mode` {string|Boolean|function} +* `callback` {function} + +Asynchronous copying of file or recursively copying directory's, including +ownership, permissions and times. If `path1` is a file, it will be copied +to `path2`, if `path1` is a directory it will be recursively copied +retaining it's file structure with the root of the `path1` directory +being the root of the `path2` directory. + +If `overwrite_mode` is a function, any time a file in `path2` already +exists it will be called with the arguments (`file1`,`file2`,`callback`) +where `file1` and `file2` are full paths of the files being copied, +`file1` being the source and `file2` being the destination that already +exists. The callback will take 1 argument, which is the mode to be used +for this file only. This can be used for prompting the user whether or +not they want to overwrite specific files etc. + +If `overwrite_mode` (this also can be the value passed via the +callback of `overwrite_mode`) is a number greater than 1 or true, +any files that already exist within `path2` will be overwritten, if +`overwrite_mode` is 1 or false, existing file will not be +overwritten however if it is acting recursively, it will continue +copying. If `overwrite_mode` is a number less than 1 it will throw +an error if a file already exists. + +No arguments other than a possible exception are given to the completion +callback. + +## fs.copySync(path1, path2, overwrite_mode) + +* `path1` {string} +* `path2` {string} +* `overwrite_mode` {string|Boolean|function} + +Synchronous version of [`fs.copy()`][]. However if `overwrite_mode` is +a function, it should return the mode rather then pass it to a callback. +`overwrite_mode` will not be called with a callback. + ## fs.createReadStream(path[, options])