├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── lib └── fs.js ├── package.json └── test ├── copy.js ├── issymlink.js ├── makedir.js ├── maketmpfile.js ├── removedir.js └── runner.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | sudo: false 5 | script: "npm test" 6 | branches: 7 | only: 8 | - master 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Dmitry Filatov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vow-fs [![NPM version](https://badge.fury.io/js/vow-fs.png)](http://badge.fury.io/js/vow-fs) [![Build Status](https://secure.travis-ci.org/dfilatov/vow-fs.png)](http://travis-ci.org/dfilatov/vow-fs) 2 | ====== 3 | 4 | [Vow](https://github.com/dfilatov/vow)-based file I/O for Node.js 5 | 6 | Requirements 7 | ------------ 8 | Vow-fs works with Node.js 0.6 and above. 9 | 10 | Getting Started 11 | --------------- 12 | You can install vow-fs using Node Package Manager (npm): 13 | 14 | npm install vow-fs 15 | 16 | #### Usage 17 | ````javascript 18 | var fs = require('vow-fs'); 19 | ```` 20 | 21 | API 22 | --- 23 | #### read(path, [encoding]) 24 | Returns a promise for the file's content at a given ````path````. 25 | #### write(path, data, [encoding]) 26 | Writes ````data```` to file at a given ````path````. Returns a promise for the completion of the operation. 27 | #### append(path, data, [encoding]) 28 | Appends````data```` to file's content at a given ````path````. Returns a promise for the completion of the operation. 29 | #### remove(path) 30 | Removes a file at a given ````path````. Returns a promise for the completion of the operation. 31 | #### copy(sourcePath, targetPath) 32 | Copies a file from ````sourcePath```` to ````targetPath````. Returns a promise for the completion of the operation. 33 | #### move(sourcePath, targetPath) 34 | Moves a file or directory from ````sourcePath```` to ````targetPath````. Returns a promise for the completion of the operation. 35 | #### stat(path) 36 | Returns a promise for the metadata about the given ````path```` as a [Stats](http://nodejs.org/api/fs.html#fs_class_fs_stats) object. 37 | #### exists(path) 38 | Returns a promise for whether the given ````path```` exists. 39 | #### link(sourcePath, targetPath) 40 | Creates a hard link from the ````sourcePath```` to ````targetPath````. 41 | #### symLink(sourcePath, targetPath, [type=file]) 42 | Creates a symbolic link from the ````sourcePath```` to ````targetPath````. 43 | #### chown(path, uid, gid) 44 | Changes the owner of a given ````path````. 45 | #### chmod(path, mode) 46 | Changes the mode of a given ````path```` to ````mode````. 47 | #### absolute(path) 48 | #### isFile(path) 49 | Returns a promise for whether the given ````path```` is a file. 50 | #### isDir(path) 51 | Returns a promise for whether the given ````path```` is a directory. 52 | #### isSocket(path) 53 | Returns a promise for whether the given ````path```` is a socket. 54 | #### isSymLink(path) 55 | Returns a promise for whether the given ````path```` is a symbolic link. 56 | #### makeTmpFile([options]) 57 | Makes a temporary file. Returns a promise with generated path to file. 58 | The ````options````: 59 | * prefix (absent by default) 60 | * dir (operating system's directory for temp files by default) 61 | * ext (````.tmp```` by default) 62 | 63 | #### listDir(path) 64 | Returns a promise for a list of files and directories in directory at the given ````path````. 65 | #### makeDir(path, [mode=0777], [failIfExist=false]) 66 | Makes a directory at a given ````path```` and any necessary subdirectories (like ````mkdir -p````). Returns a promise for the completion of the operation. 67 | #### removeDir(path) 68 | Recursively removes a directory at a given path (like ````remove -rf````). Returns a promise for the completion of the operation. 69 | #### glob(pattern, [options]) 70 | Matches files using the patterns. See https://github.com/isaacs/node-glob for details. 71 | -------------------------------------------------------------------------------- /lib/fs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module vow-fs 3 | * @author Filatov Dmitry 4 | * @version 0.3.6 5 | * @license 6 | * Dual licensed under the MIT and GPL licenses: 7 | * * http://www.opensource.org/licenses/mit-license.php 8 | * * http://www.gnu.org/licenses/gpl.html 9 | */ 10 | 11 | var vow = require('vow'), 12 | Queue = require('vow-queue'), 13 | openFilesQueue = new Queue(), 14 | fs = require('fs'), 15 | path = require('path'), 16 | os = require('os'), 17 | uuid = require('uuid'), 18 | glob = require('glob'), 19 | slice = Array.prototype.slice, 20 | promisify = function(nodeFn) { 21 | return function() { 22 | var defer = vow.defer(), 23 | args = slice.call(arguments); 24 | args.push(function(err) { 25 | err? defer.reject(err) : defer.resolve(arguments[1]); 26 | }); 27 | try { 28 | nodeFn.apply(fs, args); 29 | } 30 | catch(err) { 31 | defer.reject(err); 32 | } 33 | return defer.promise(); 34 | }; 35 | }, 36 | tmpDir = os.tmpdir || os.tmpDir || function() { return '/tmp'; }, 37 | makeDir = promisify(fs.mkdir), 38 | removeDir = promisify(fs.rmdir), 39 | lstat = promisify(fs.lstat), 40 | emfileTimeout = 1, 41 | emfileFixWrapper = function(method, weight) { 42 | var wrapper = function() { 43 | var callArgs = arguments; 44 | return openFilesQueue.enqueue(function() { 45 | return method.apply(vfs, callArgs).then( 46 | function(res) { 47 | emfileTimeout = Math.max(1, emfileTimeout / 2); 48 | return res; 49 | }, 50 | function(err) { 51 | if(err.code === 'EMFILE') { 52 | emfileTimeout++; 53 | return vow.delay(null, emfileTimeout).then(function() { 54 | return wrapper.apply(vfs, callArgs); 55 | }); 56 | } 57 | else { 58 | throw err; 59 | } 60 | }); 61 | }, weight); 62 | }; 63 | return wrapper; 64 | }, 65 | undef; 66 | 67 | var vfs = module.exports = { 68 | /** 69 | * Reads file by given path 70 | * @param {String} path 71 | * @param {String} [encoding] 72 | * @returns {vow:Promise} 73 | */ 74 | read : emfileFixWrapper(promisify(fs.readFile)), 75 | 76 | /** 77 | * Writes data to file by given path 78 | * @param {String} path 79 | * @param {String|Buffer} data 80 | * @param {String} [encoding] 81 | * @returns {vow:Promise} 82 | */ 83 | write : emfileFixWrapper(promisify(fs.writeFile)), 84 | 85 | /** 86 | * Appends data to file by given path 87 | * @param {String} path 88 | * @param {String|Buffer} data 89 | * @param {String} [encoding] 90 | * @returns {vow:Promise} 91 | */ 92 | append : emfileFixWrapper(promisify(fs.appendFile)), 93 | 94 | /** 95 | * Removes file at given path 96 | * @param {String} pathToRemove 97 | * @returns {vow:Promise} 98 | */ 99 | remove : promisify(fs.unlink), 100 | 101 | /** 102 | * Copies file from sourcePath to targetPath 103 | * @param {String} sourcePath 104 | * @param {String} targetPath 105 | * @returns {vow:Promise} 106 | */ 107 | copy : emfileFixWrapper(function(sourcePath, targetPath) { 108 | return this.isFile(sourcePath).then(function(isFile) { 109 | if(!isFile) { 110 | var err = Error(); 111 | err.errno = 28; 112 | err.code = 'EISDIR'; 113 | err.path = sourcePath; 114 | throw err; 115 | } 116 | 117 | var defer = vow.defer(), 118 | sourceStream = fs.createReadStream(sourcePath), 119 | errFn = function(err) { 120 | defer.reject(err); 121 | }; 122 | 123 | sourceStream 124 | .on('error', errFn) 125 | .on('open', function() { 126 | var targetStream = fs.createWriteStream(targetPath); 127 | sourceStream.pipe( 128 | targetStream 129 | .on('error', errFn) 130 | .on('close', function() { 131 | defer.resolve(); 132 | })); 133 | }); 134 | 135 | return defer.promise(); 136 | }); 137 | }, 2), 138 | 139 | /** 140 | * Moves from sourcePath to targetPath 141 | * @param {String} sourcePath 142 | * @param {String} targetPath 143 | * @returns {vow:Promise} 144 | */ 145 | move : promisify(fs.rename), 146 | 147 | /** 148 | * Extracts fs.Stats about a given path 149 | * @param {String} path 150 | * @returns {vow:Promise} 151 | */ 152 | stat : promisify(fs.stat), 153 | 154 | /** 155 | * Tests whether or not the given path exists 156 | * @param {String} path 157 | * @returns {vow:Promise} 158 | */ 159 | exists : fs.exists? 160 | function(path) { 161 | var defer = vow.defer(); 162 | fs.exists(path, function(exists) { 163 | defer.resolve(exists); 164 | }); 165 | return defer.promise(); 166 | } : 167 | function(path) { 168 | var defer = vow.defer(); 169 | fs.stat(path, function(err) { 170 | defer.resolve(!err); 171 | }); 172 | return defer.promise(); 173 | }, 174 | 175 | /** 176 | * Creates a hard link from the sourcePath to targetPath 177 | * @param {String} sourcePath 178 | * @param {String} targetPath 179 | * @returns {vow:Promise} 180 | */ 181 | link : promisify(fs.link), 182 | 183 | /** 184 | * Creates a relative symbolic link from the sourcePath to targetPath 185 | * @param {String} sourcePath 186 | * @param {String} targetPath 187 | * @param {String} [type=file] can be either 'dir', 'file', or 'junction' 188 | * @returns {vow:Promise} 189 | */ 190 | symLink : promisify(fs.symlink), 191 | 192 | /** 193 | * Changes the owner for a given path using Unix user-id and group-id numbers 194 | * @param {String} path 195 | * @param uid 196 | * @param gid 197 | * @returns {vow:Promise} 198 | */ 199 | chown : promisify(fs.chown), 200 | 201 | /** 202 | * Changes the Unix mode for a path. Returns a promise 203 | * @param {String} path 204 | * @param mode 205 | * @returns {vow:Promise} 206 | */ 207 | chmod : promisify(fs.chmod), 208 | 209 | /** 210 | * Normalizes a given path to absolute path 211 | * @param {String} path 212 | * @returns {vow:Promise} 213 | */ 214 | absolute : promisify(fs.realpath), 215 | 216 | /** 217 | * Checks whether the given path is a file 218 | * @param {String} path 219 | * @returns {vow:Promise} 220 | */ 221 | isFile : function(path) { 222 | return this.stat(path).then(function(stats) { 223 | return stats.isFile(); 224 | }); 225 | }, 226 | 227 | /** 228 | * Checks whether the given path is a directory 229 | * @param {String} path 230 | * @returns {vow:Promise} 231 | */ 232 | isDir : function(path) { 233 | return this.stat(path).then(function(stats) { 234 | return stats.isDirectory(); 235 | }); 236 | }, 237 | 238 | /** 239 | * Checks whether the given path is a socket 240 | * @param {String} path 241 | * @returns {vow:Promise} 242 | */ 243 | isSocket : function(path) { 244 | return this.stat(path).then(function(stats) { 245 | return stats.isSocket(); 246 | }); 247 | }, 248 | 249 | /** 250 | * Checks whether the given path is a symbolic link 251 | * @param {String} path 252 | * @returns {vow:Promise} 253 | */ 254 | isSymLink : function(path) { 255 | return lstat(path).then(function(stats) { 256 | return stats.isSymbolicLink(); 257 | }); 258 | }, 259 | 260 | /** 261 | * Makes a temporary file 262 | * @param {Object} options 263 | * @param {String} [options.prefix] 264 | * @param {String} [options.dir=os.tmpdir()] 265 | * @param {String} [options.ext=tmp] 266 | * @returns {vow:Promise} 267 | */ 268 | makeTmpFile : function(options) { 269 | options || (options = {}); 270 | 271 | var filePath = path.join( 272 | options.dir || tmpDir(), 273 | (options.prefix || '') + uuid.v4() + (options.ext || '.tmp')); 274 | 275 | return vfs.write(filePath, '').then(function() { 276 | return filePath; 277 | }); 278 | }, 279 | 280 | /** 281 | * Reads the contents of a directory by given path 282 | * @param {String} path 283 | * @returns {vow:Promise} 284 | */ 285 | listDir : emfileFixWrapper(promisify(fs.readdir)), 286 | 287 | /** 288 | * Makes a directory at a given path, recursively creating any branches that doesn't exist 289 | * @param {String} dirPath 290 | * @param [mode=0777] 291 | * @param [failIfExist=false] 292 | * @returns {vow:Promise} 293 | */ 294 | makeDir : function(dirPath, mode, failIfExist) { 295 | if(typeof mode === 'boolean') { 296 | failIfExist = mode; 297 | mode = undef; 298 | } 299 | 300 | var dirName = path.dirname(dirPath), 301 | onFailed = function(e) { 302 | if(e.code !== 'EEXIST' || failIfExist) { 303 | throw e; 304 | } 305 | 306 | return vfs.isDir(dirPath).then(function(isDir) { 307 | if(!isDir) { 308 | throw e; 309 | } 310 | }); 311 | }; 312 | 313 | return vfs.exists(dirName).then(function(exists) { 314 | if(exists) { 315 | return makeDir(dirPath, mode).fail(onFailed); 316 | } 317 | else { 318 | failIfExist = false; 319 | return vfs.makeDir(dirName, mode).then(function() { 320 | return makeDir(dirPath, mode).fail(onFailed); 321 | }); 322 | } 323 | }); 324 | }, 325 | 326 | /** 327 | * Removes directory 328 | * @param {String} dirPath 329 | * @returns {vow:Promise} 330 | */ 331 | removeDir : function(dirPath) { 332 | return vfs.listDir(dirPath) 333 | .then(function(list) { 334 | return list.length && vow.all( 335 | list.map(function(file) { 336 | var fullPath = path.join(dirPath, file); 337 | return vfs.isFile(fullPath).then(function(isFile) { 338 | return isFile? 339 | vfs.remove(fullPath) : 340 | vfs.removeDir(fullPath); 341 | }); 342 | })); 343 | }) 344 | .then(function() { 345 | return removeDir(dirPath); 346 | }); 347 | }, 348 | 349 | /** 350 | * Matches files using the patterns, see https://github.com/isaacs/node-glob for details 351 | * @param {String} pattern to be matched 352 | * @param {Object} [options] options 353 | * @returns {vow:Promise} 354 | */ 355 | glob : promisify(glob), 356 | 357 | options : function(opts) { 358 | if(typeof opts.openFileLimit !== 'undefined') { 359 | openFilesQueue.setParams({ weightLimit : opts.openFileLimit }); 360 | } 361 | } 362 | }; 363 | 364 | openFilesQueue.start(); 365 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "vow-fs", 3 | "version" : "0.3.6", 4 | "description" : "File I/O by Vow", 5 | "homepage" : "https://github.com/dfilatov/vow-fs", 6 | "keywords" : ["vow", "promise", "file system"], 7 | "author" : "Dmitry Filatov ", 8 | "contributors" : [{ 9 | "name" : "Dmitry Filatov", 10 | "email" : "dfilatov@yandex-team.ru" 11 | }], 12 | "repository": { 13 | "type" : "git", 14 | "url" : "http://github.com/dfilatov/vow-fs.git" 15 | }, 16 | "dependencies": { 17 | "uuid" : "^2.0.2", 18 | "vow" : "^0.4.7", 19 | "vow-queue" : "^0.4.1", 20 | "glob" : "^7.0.5" 21 | }, 22 | "devDependencies": { 23 | "nodeunit" : "", 24 | "istanbul" : "" 25 | }, 26 | "main" : "lib/fs", 27 | "files" : ["lib"], 28 | "engines" : { "node" : ">= 0.6.0" }, 29 | "license": "MIT", 30 | "scripts" : { 31 | "test" : "istanbul test test/runner.js" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/copy.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | vfs = require('../lib/fs'), 4 | TEST_DIR = path.join(__dirname, 'test-dir'); 5 | 6 | module.exports = { 7 | setUp : function(done) { 8 | fs.mkdirSync(TEST_DIR); 9 | done(); 10 | }, 11 | 12 | tearDown : function(done) { 13 | fs.rmdirSync(TEST_DIR); 14 | done(); 15 | }, 16 | 17 | 'should copy file' : function(test) { 18 | var sourceFile = path.join(TEST_DIR, 'source-file'), 19 | targetFile = path.join(TEST_DIR, 'target-file'); 20 | fs.writeFileSync(sourceFile, 'source'); 21 | vfs.copy(sourceFile, targetFile) 22 | .then(function() { 23 | test.equal(fs.readFileSync(targetFile, 'utf8'), 'source'); 24 | }) 25 | .always(function() { 26 | fs.unlinkSync(sourceFile); 27 | fs.unlinkSync(targetFile); 28 | test.done(); 29 | }); 30 | }, 31 | 32 | 'should copy file if target exists' : function(test) { 33 | var sourceFile = path.join(TEST_DIR, 'source-file'), 34 | targetFile = path.join(TEST_DIR, 'target-file'); 35 | fs.writeFileSync(sourceFile, 'source'); 36 | fs.writeFileSync(targetFile, 'target'); 37 | vfs.copy(sourceFile, targetFile) 38 | .then(function() { 39 | test.equal(fs.readFileSync(targetFile, 'utf8'), 'source'); 40 | }) 41 | .always(function() { 42 | fs.unlinkSync(sourceFile); 43 | fs.unlinkSync(targetFile); 44 | test.done(); 45 | }); 46 | }, 47 | 48 | 'should not copy file if source is directory' : function(test) { 49 | var sourceDir = path.join(TEST_DIR, 'source-dir'), 50 | targetFile = path.join(TEST_DIR, 'target-file'); 51 | fs.mkdirSync(sourceDir); 52 | vfs.copy(sourceDir, targetFile) 53 | .then( 54 | function() { 55 | test.ok(false); 56 | }, 57 | function(err) { 58 | test.equal(err.code, 'EISDIR'); 59 | }) 60 | .always(function() { 61 | fs.rmdirSync(sourceDir); 62 | test.done(); 63 | }); 64 | }, 65 | 66 | 'should not copy file if target is directory' : function(test) { 67 | var sourceFile = path.join(TEST_DIR, 'source-file'), 68 | targetDir = path.join(TEST_DIR, 'target-dir'); 69 | fs.writeFileSync(sourceFile, 'source'); 70 | fs.mkdirSync(targetDir); 71 | vfs.copy(sourceFile, targetDir) 72 | .then( 73 | function() { 74 | test.ok(false); 75 | }, 76 | function(err) { 77 | test.equal(err.code, 'EISDIR'); 78 | }) 79 | .always(function() { 80 | fs.unlinkSync(sourceFile); 81 | fs.rmdirSync(targetDir); 82 | test.done(); 83 | }); 84 | }, 85 | 86 | 'should not copy if target not exists' : function(test) { 87 | var sourceFile = path.join(TEST_DIR, 'source-file'), 88 | targetFile = path.join(TEST_DIR, 'target-file'); 89 | vfs.copy(sourceFile, targetFile) 90 | .then( 91 | function() { 92 | test.ok(false); 93 | }, 94 | function(err) { 95 | test.equal(err.code, 'ENOENT'); 96 | }) 97 | .always(function() { 98 | test.done(); 99 | }); 100 | } 101 | }; -------------------------------------------------------------------------------- /test/issymlink.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | vfs = require('../lib/fs'), 4 | TEST_DIR = path.join(__dirname, 'test-dir'); 5 | 6 | module.exports = { 7 | setUp : function(done) { 8 | fs.mkdirSync(TEST_DIR); 9 | done(); 10 | }, 11 | 12 | tearDown : function(done) { 13 | fs.rmdirSync(TEST_DIR); 14 | done(); 15 | }, 16 | 17 | 'should return true if the file is a symbolic link' : function(test) { 18 | var sourceFile = path.join(TEST_DIR, 'source-file'), 19 | targetFile = path.join(TEST_DIR, 'target-file'); 20 | fs.writeFileSync(sourceFile, 'source'); 21 | fs.symlinkSync(sourceFile, targetFile); 22 | vfs.isSymLink(targetFile) 23 | .then(function(isSymLink) { 24 | test.ok(isSymLink); 25 | }) 26 | .always(function() { 27 | fs.unlinkSync(sourceFile); 28 | fs.unlinkSync(targetFile); 29 | test.done(); 30 | }); 31 | }, 32 | 33 | 'should return false if the file is not a symbolic link' : function(test) { 34 | var sourceFile = path.join(TEST_DIR, 'source-file'); 35 | fs.writeFileSync(sourceFile, 'source'); 36 | vfs.isSymLink(sourceFile) 37 | .then(function(isSymLink) { 38 | test.ok(!isSymLink); 39 | }) 40 | .always(function() { 41 | fs.unlinkSync(sourceFile); 42 | test.done(); 43 | }); 44 | } 45 | }; -------------------------------------------------------------------------------- /test/makedir.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | vfs = require('../lib/fs'), 4 | TEST_DIR = path.join(__dirname, 'test-dir'); 5 | 6 | module.exports = { 7 | setUp : function(done) { 8 | fs.mkdirSync(TEST_DIR); 9 | done(); 10 | }, 11 | 12 | tearDown : function(done) { 13 | fs.rmdirSync(TEST_DIR); 14 | done(); 15 | }, 16 | 17 | 'should make directory' : function(test) { 18 | var dir = path.join(TEST_DIR, 'a'); 19 | vfs.makeDir(dir) 20 | .then( 21 | function() { 22 | return vfs.exists(dir); 23 | }, 24 | function() { 25 | test.ok(false); 26 | }) 27 | .always(function(promise) { 28 | test.ok(promise.valueOf()); 29 | test.ok(fs.statSync(dir).isDirectory()); 30 | fs.rmdirSync(dir); 31 | test.done(); 32 | }); 33 | }, 34 | 35 | 'should make directory if exists' : function(test) { 36 | var dir = path.join(TEST_DIR, 'a'); 37 | fs.mkdirSync(dir); 38 | vfs.makeDir(dir) 39 | .then( 40 | function() { 41 | return vfs.exists(dir); 42 | }, 43 | function() { 44 | test.ok(false); 45 | }) 46 | .always(function(promise) { 47 | test.ok(promise.valueOf()); 48 | test.ok(fs.statSync(dir).isDirectory()); 49 | fs.rmdirSync(dir); 50 | test.done(); 51 | }); 52 | }, 53 | 54 | 'should be failed if directory exists' : function(test) { 55 | var dir = path.join(TEST_DIR, 'a'); 56 | fs.mkdirSync(dir); 57 | vfs.makeDir(dir, true) 58 | .then( 59 | function() { 60 | test.ok(false); 61 | }, 62 | function() { 63 | test.ok(true); 64 | }) 65 | .always(function() { 66 | fs.rmdirSync(dir); 67 | test.done(); 68 | }); 69 | }, 70 | 71 | 'should be failed if file with same name exists' : function(test) { 72 | var dir = path.join(TEST_DIR, 'test-file'); 73 | fs.writeFileSync(dir, 'test'); 74 | vfs.makeDir(dir) 75 | .then( 76 | function() { 77 | test.ok(false); 78 | }, 79 | function() { 80 | test.ok(true); 81 | }) 82 | .always(function() { 83 | fs.unlinkSync(path.join(TEST_DIR, 'test-file')); 84 | test.done(); 85 | }); 86 | }, 87 | 88 | 'should make directory tree' : function(test) { 89 | var dir = path.join(TEST_DIR, 'a/b/c'); 90 | vfs.makeDir(dir) 91 | .then( 92 | function() { 93 | return vfs.exists(dir); 94 | }, 95 | function() { 96 | test.ok(false); 97 | }) 98 | .always(function(promise) { 99 | test.ok(promise.valueOf()); 100 | test.ok(fs.statSync(dir).isDirectory()); 101 | fs.rmdirSync(path.join(TEST_DIR, 'a/b/c')); 102 | fs.rmdirSync(path.join(TEST_DIR, 'a/b')); 103 | fs.rmdirSync(path.join(TEST_DIR, 'a')); 104 | test.done(); 105 | }); 106 | }, 107 | 108 | 'should make directory tree if exists' : function(test) { 109 | var dir = path.join(TEST_DIR, 'a/b/c'); 110 | fs.mkdirSync(path.join(TEST_DIR, 'a')); 111 | fs.mkdirSync(path.join(TEST_DIR, 'a', 'b')); 112 | fs.mkdirSync(dir); 113 | vfs.makeDir(dir) 114 | .then( 115 | function() { 116 | test.ok(true); 117 | }, 118 | function() { 119 | test.ok(false); 120 | }) 121 | .always(function() { 122 | fs.rmdirSync(path.join(TEST_DIR, 'a/b/c')); 123 | fs.rmdirSync(path.join(TEST_DIR, 'a/b')); 124 | fs.rmdirSync(path.join(TEST_DIR, 'a')); 125 | test.done(); 126 | }); 127 | } 128 | }; -------------------------------------------------------------------------------- /test/maketmpfile.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | os = require('os'), 4 | vfs = require('../lib/fs'), 5 | tmpDir = os.tmpdir || os.tmpDir || function() { return '/tmp'; }, 6 | TEST_DIR = path.join(__dirname, 'test-dir'); 7 | 8 | module.exports = { 9 | setUp : function(done) { 10 | fs.mkdirSync(TEST_DIR); 11 | done(); 12 | }, 13 | 14 | tearDown : function(done) { 15 | fs.rmdirSync(TEST_DIR); 16 | done(); 17 | }, 18 | 19 | 'should make temporary file with default options' : function(test) { 20 | var filePath; 21 | vfs.makeTmpFile() 22 | .then( 23 | function(_filePath) { 24 | return vfs.exists(filePath = _filePath); 25 | }, 26 | function() { 27 | test.ok(false); 28 | throw Error(); 29 | }) 30 | .then(function(exists) { 31 | fs.unlinkSync(filePath); 32 | test.strictEqual(path.dirname(filePath), path.resolve(tmpDir())); 33 | test.strictEqual(path.extname(filePath), '.tmp'); 34 | test.ok(exists); 35 | }) 36 | .always(function() { 37 | test.done(); 38 | }); 39 | }, 40 | 41 | 'should make temporary file in custom directory' : function(test) { 42 | var filePath; 43 | vfs.makeTmpFile({ dir : TEST_DIR }) 44 | .then( 45 | function(_filePath) { 46 | return vfs.exists(filePath = _filePath); 47 | }, 48 | function() { 49 | test.ok(false); 50 | throw Error(); 51 | }) 52 | .then(function(exists) { 53 | fs.unlinkSync(filePath); 54 | test.ok(exists); 55 | test.strictEqual(path.dirname(filePath), TEST_DIR); 56 | }) 57 | .always(function() { 58 | test.done(); 59 | }) 60 | }, 61 | 62 | 'should make temporary file with custom prefix' : function(test) { 63 | var filePath; 64 | vfs.makeTmpFile({ prefix : '__prefix' }) 65 | .then( 66 | function(_filePath) { 67 | return vfs.exists(filePath = _filePath); 68 | }, 69 | function() { 70 | test.ok(false); 71 | throw Error(); 72 | }) 73 | .then(function(exists) { 74 | fs.unlinkSync(filePath); 75 | test.ok(exists); 76 | test.ok(filePath.indexOf('__prefix') > -1); 77 | }) 78 | .always(function() { 79 | test.done(); 80 | }) 81 | }, 82 | 83 | 'should make temporary file with custom extension' : function(test) { 84 | var filePath; 85 | vfs.makeTmpFile({ ext : '.css' }) 86 | .then( 87 | function(_filePath) { 88 | return vfs.exists(filePath = _filePath); 89 | }, 90 | function() { 91 | test.ok(false); 92 | throw Error(); 93 | }) 94 | .then(function(exists) { 95 | fs.unlinkSync(filePath); 96 | test.ok(exists); 97 | test.strictEqual(path.extname(filePath), '.css'); 98 | }) 99 | .always(function() { 100 | test.done(); 101 | }) 102 | } 103 | }; -------------------------------------------------------------------------------- /test/removedir.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | vfs = require('../lib/fs'), 4 | TEST_DIR = path.join(__dirname, 'test-dir'); 5 | 6 | module.exports = { 7 | setUp : function(done) { 8 | fs.mkdirSync(TEST_DIR); 9 | done(); 10 | }, 11 | 12 | tearDown : function(done) { 13 | fs.rmdirSync(TEST_DIR); 14 | done(); 15 | }, 16 | 17 | 'should remove empty directory' : function(test) { 18 | var dir = path.join(TEST_DIR, 'dir'); 19 | fs.mkdirSync(dir); 20 | vfs.removeDir(dir) 21 | .then( 22 | function() { 23 | return vfs.exists(dir); 24 | }, 25 | function() { 26 | test.ok(false); 27 | }) 28 | .always(function(promise) { 29 | test.ok(!promise.valueOf()); 30 | test.done(); 31 | }); 32 | }, 33 | 34 | 'should remove directory tree' : function(test) { 35 | var dir = path.join(TEST_DIR, 'dir'); 36 | fs.mkdirSync(dir); 37 | fs.mkdirSync(path.join(dir, 'a')); 38 | fs.writeFileSync(path.join(dir, 'a', 'file'), 'file'); 39 | fs.mkdirSync(path.join(dir, 'a', 'b')); 40 | fs.writeFileSync(path.join(dir, 'a', 'b', 'file1'), 'file1'); 41 | fs.writeFileSync(path.join(dir, 'a', 'b', 'file2'), 'file2'); 42 | vfs.removeDir(dir) 43 | .then( 44 | function() { 45 | return vfs.exists(dir); 46 | }, 47 | function() { 48 | test.ok(false); 49 | }) 50 | .always(function(promise) { 51 | test.ok(!promise.valueOf()); 52 | test.done(); 53 | }); 54 | }, 55 | 56 | 'should not remove file' : function(test) { 57 | var filePath = path.join(TEST_DIR, 'file'); 58 | fs.writeFileSync(filePath, 'file'); 59 | vfs.removeDir(filePath) 60 | .then( 61 | function() { 62 | test.ok(false); 63 | }, 64 | function(err) { 65 | test.equal(err.code, 'ENOTDIR'); 66 | return vfs.exists(filePath); 67 | }) 68 | .always(function(promise) { 69 | test.ok(promise.valueOf()); 70 | fs.unlinkSync(filePath); 71 | test.done(); 72 | }); 73 | } 74 | }; -------------------------------------------------------------------------------- /test/runner.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'); 3 | 4 | require('nodeunit').reporters.default.run( 5 | fs.readdirSync(__dirname) 6 | .filter(function(file){ 7 | return fs.statSync(path.join(__dirname, file)).isFile() && file !== 'runner.js'; 8 | }) 9 | .map(function(file) { 10 | return path.join('test', file); 11 | }), 12 | null, 13 | function(err) { 14 | err && process.exit(1); 15 | }); --------------------------------------------------------------------------------