aboutsummaryrefslogtreecommitdiff
path: root/node_modules/shelljs/src/rm.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/shelljs/src/rm.js')
-rw-r--r--node_modules/shelljs/src/rm.js150
1 files changed, 150 insertions, 0 deletions
diff --git a/node_modules/shelljs/src/rm.js b/node_modules/shelljs/src/rm.js
new file mode 100644
index 000000000..595368114
--- /dev/null
+++ b/node_modules/shelljs/src/rm.js
@@ -0,0 +1,150 @@
+var common = require('./common');
+var fs = require('fs');
+
+common.register('rm', _rm, {
+ cmdOptions: {
+ 'f': 'force',
+ 'r': 'recursive',
+ 'R': 'recursive',
+ },
+});
+
+// Recursively removes 'dir'
+// Adapted from https://github.com/ryanmcgrath/wrench-js
+//
+// Copyright (c) 2010 Ryan McGrath
+// Copyright (c) 2012 Artur Adib
+//
+// Licensed under the MIT License
+// http://www.opensource.org/licenses/mit-license.php
+function rmdirSyncRecursive(dir, force) {
+ var files;
+
+ files = fs.readdirSync(dir);
+
+ // Loop through and delete everything in the sub-tree after checking it
+ for (var i = 0; i < files.length; i++) {
+ var file = dir + '/' + files[i];
+ var currFile = fs.lstatSync(file);
+
+ if (currFile.isDirectory()) { // Recursive function back to the beginning
+ rmdirSyncRecursive(file, force);
+ } else { // Assume it's a file - perhaps a try/catch belongs here?
+ if (force || isWriteable(file)) {
+ try {
+ common.unlinkSync(file);
+ } catch (e) {
+ /* istanbul ignore next */
+ common.error('could not remove file (code ' + e.code + '): ' + file, {
+ continue: true,
+ });
+ }
+ }
+ }
+ }
+
+ // Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
+ // Huzzah for the shopkeep.
+
+ var result;
+ try {
+ // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+ var start = Date.now();
+
+ // TODO: replace this with a finite loop
+ for (;;) {
+ try {
+ result = fs.rmdirSync(dir);
+ if (fs.existsSync(dir)) throw { code: 'EAGAIN' };
+ break;
+ } catch (er) {
+ /* istanbul ignore next */
+ // In addition to error codes, also check if the directory still exists and loop again if true
+ if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+ if (Date.now() - start > 1000) throw er;
+ } else if (er.code === 'ENOENT') {
+ // Directory did not exist, deletion was successful
+ break;
+ } else {
+ throw er;
+ }
+ }
+ }
+ } catch (e) {
+ common.error('could not remove directory (code ' + e.code + '): ' + dir, { continue: true });
+ }
+
+ return result;
+} // rmdirSyncRecursive
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow
+function isWriteable(file) {
+ var writePermission = true;
+ try {
+ var __fd = fs.openSync(file, 'a');
+ fs.closeSync(__fd);
+ } catch (e) {
+ writePermission = false;
+ }
+
+ return writePermission;
+}
+
+//@
+//@ ### rm([options,] file [, file ...])
+//@ ### rm([options,] file_array)
+//@ Available options:
+//@
+//@ + `-f`: force
+//@ + `-r, -R`: recursive
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ rm('-rf', '/tmp/*');
+//@ rm('some_file.txt', 'another_file.txt');
+//@ rm(['some_file.txt', 'another_file.txt']); // same as above
+//@ ```
+//@
+//@ Removes files.
+function _rm(options, files) {
+ if (!files) common.error('no paths given');
+
+ // Convert to array
+ files = [].slice.call(arguments, 1);
+
+ files.forEach(function (file) {
+ var stats;
+ try {
+ stats = fs.lstatSync(file); // test for existence
+ } catch (e) {
+ // Path does not exist, no force flag given
+ if (!options.force) {
+ common.error('no such file or directory: ' + file, { continue: true });
+ }
+ return; // skip file
+ }
+
+ // If here, path exists
+ if (stats.isFile()) {
+ if (options.force || isWriteable(file)) {
+ // -f was passed, or file is writable, so it can be removed
+ common.unlinkSync(file);
+ } else {
+ common.error('permission denied: ' + file, { continue: true });
+ }
+ } else if (stats.isDirectory()) {
+ if (options.recursive) {
+ // -r was passed, so directory can be removed
+ rmdirSyncRecursive(file, options.force);
+ } else {
+ common.error('path is a directory', { continue: true });
+ }
+ } else if (stats.isSymbolicLink() || stats.isFIFO()) {
+ common.unlinkSync(file);
+ }
+ }); // forEach(file)
+ return '';
+} // rm
+module.exports = _rm;