pax_global_header00006660000000000000000000000064131057170770014522gustar00rootroot0000000000000052 comment=3a27851dc08f43dbe2d3fda2dddef34c67408715 fs-mkdirp-stream-1.0.0/000077500000000000000000000000001310571707700147055ustar00rootroot00000000000000fs-mkdirp-stream-1.0.0/.editorconfig000066400000000000000000000003051310571707700173600ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false fs-mkdirp-stream-1.0.0/.eslintrc000066400000000000000000000000301310571707700165220ustar00rootroot00000000000000{ "extends": "gulp" } fs-mkdirp-stream-1.0.0/.gitignore000066400000000000000000000012541310571707700166770ustar00rootroot00000000000000# Logs logs *.log # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # Commenting this out is preferred by some people, see # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- node_modules # Users Environment Variables .lock-wscript # Garbage files .DS_Store # Generated by integration tests test/fixtures/tmp test/fixtures/out fs-mkdirp-stream-1.0.0/.jscsrc000066400000000000000000000000271310571707700161740ustar00rootroot00000000000000{ "preset": "gulp" } fs-mkdirp-stream-1.0.0/.travis.yml000066400000000000000000000001711310571707700170150ustar00rootroot00000000000000sudo: false language: node_js node_js: - '6' - '5' - '4' - '0.12' - '0.10' after_script: - npm run coveralls fs-mkdirp-stream-1.0.0/LICENSE000066400000000000000000000023521310571707700157140ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2017 Blaine Bublitz , Eric Schoffstall and other contributors (Originally based on code from node-mkdirp - MIT/X11 license - Copyright 2010 James Halliday) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fs-mkdirp-stream-1.0.0/README.md000066400000000000000000000053171310571707700161720ustar00rootroot00000000000000

# fs-mkdirp-stream [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] Ensure directories exist before writing to them. ## Usage ```js var to = require('to2'); var from = require('from2'); var mkdirpStream = require('fs-mkdirp-stream'); from.obj([{ dirname: '/path/to/my/', path: '/path/to/my/file.js' }]) .pipe(mkdirpStream.obj(function(obj, callback) { // callback can take 3 arguments (err, dirname, mode) callback(null, obj.dirname); })) .pipe(to.obj(function(obj) { // This will be called once the directory exists // obj === { dirname: '/path/to/my/', path: '/path/to/my/file.js' } })); ``` ## API ### `mkdirpStream(resolver)` Takes a `resolver` function or string and returns a `through2` stream. If the `resolver` is a function, it will be called once per chunk with the signature `(chunk, callback)`. The `callback(error, dirpath, mode)` must be called with the `dirpath` to be created as the 2nd parameter or an `error` as the 1st parameter; optionally with a `mode` as the 3rd parameter. If the `resolver` is a string, it will be created/ensured for each chunk (e.g. if it were deleted between chunks, it would be recreated). When using a string, a custom `mode` can't be used. ### `mkdirpStream.obj(resolver)` The same as the top-level API but for object streams. See the example to see the benefit of object streams with this module. ## License MIT Contains a custom implementation of `mkdirp` originally based on https://github.com/substack/node-mkdirp (Licensed MIT/X11 - Copyright 2010 James Halliday) with heavy modification to better support custom modes. [downloads-image]: http://img.shields.io/npm/dm/fs-mkdirp-stream.svg [npm-url]: https://npmjs.com/package/fs-mkdirp-stream [npm-image]: http://img.shields.io/npm/v/fs-mkdirp-stream.svg [travis-url]: https://travis-ci.org/gulpjs/fs-mkdirp-stream [travis-image]: http://img.shields.io/travis/gulpjs/fs-mkdirp-stream.svg?label=travis-ci [appveyor-url]: https://ci.appveyor.com/project/gulpjs/fs-mkdirp-stream [appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/fs-mkdirp-stream.svg?label=appveyor [coveralls-url]: https://coveralls.io/r/gulpjs/fs-mkdirp-stream [coveralls-image]: http://img.shields.io/coveralls/gulpjs/fs-mkdirp-stream/master.svg [gitter-url]: https://gitter.im/gulpjs/gulp [gitter-image]: https://badges.gitter.im/gulpjs/gulp.png fs-mkdirp-stream-1.0.0/appveyor.yml000066400000000000000000000007211310571707700172750ustar00rootroot00000000000000# http://www.appveyor.com/docs/appveyor-yml # http://www.appveyor.com/docs/lang/nodejs-iojs environment: matrix: # node.js - nodejs_version: "0.10" - nodejs_version: "0.12" - nodejs_version: "4" - nodejs_version: "5" - nodejs_version: "6" install: - ps: Install-Product node $env:nodejs_version - npm install test_script: - node --version - npm --version - cmd: npm test build: off # build version format version: "{build}" fs-mkdirp-stream-1.0.0/index.js000066400000000000000000000017641310571707700163620ustar00rootroot00000000000000'use strict'; var through = require('through2'); var mkdirp = require('./mkdirp'); function toFunction(dirpath) { function stringResolver(chunk, callback) { callback(null, dirpath); } return stringResolver; } function define(options) { function mkdirpStream(resolver) { // Handle resolver that's just a dirpath if (typeof resolver === 'string') { resolver = toFunction(resolver); } function makeFileDirs(chunk, enc, callback) { resolver(chunk, onDirpath); function onDirpath(dirpathErr, dirpath, mode) { if (dirpathErr) { return callback(dirpathErr); } mkdirp(dirpath, mode, onMkdirp); } function onMkdirp(mkdirpErr) { if (mkdirpErr) { return callback(mkdirpErr); } callback(null, chunk); } } return through(options, makeFileDirs); } return mkdirpStream; } module.exports = define(); module.exports.obj = define({ objectMode: true, highWaterMark: 16 }); fs-mkdirp-stream-1.0.0/mkdirp.js000066400000000000000000000025651310571707700165410ustar00rootroot00000000000000'use strict'; var path = require('path'); var fs = require('graceful-fs'); var MASK_MODE = parseInt('7777', 8); var DEFAULT_DIR_MODE = parseInt('0777', 8); function mkdirp(dirpath, customMode, callback) { if (typeof customMode === 'function') { callback = customMode; customMode = undefined; } var mode = customMode || (DEFAULT_DIR_MODE & ~process.umask()); dirpath = path.resolve(dirpath); fs.mkdir(dirpath, mode, onMkdir); function onMkdir(mkdirErr) { if (!mkdirErr) { return fs.stat(dirpath, onStat); } switch (mkdirErr.code) { case 'ENOENT': { return mkdirp(path.dirname(dirpath), onRecurse); } case 'EEXIST': { return fs.stat(dirpath, onStat); } default: { return callback(mkdirErr); } } function onStat(statErr, stats) { if (statErr) { return callback(statErr); } if (!stats.isDirectory()) { return callback(mkdirErr); } // TODO: Is it proper to mask like this? if ((stats.mode & MASK_MODE) === mode) { return callback(); } if (!customMode) { return callback(); } fs.chmod(dirpath, mode, callback); } } function onRecurse(recurseErr) { if (recurseErr) { return callback(recurseErr); } mkdirp(dirpath, mode, callback); } } module.exports = mkdirp; fs-mkdirp-stream-1.0.0/package.json000066400000000000000000000023251310571707700171750ustar00rootroot00000000000000{ "name": "fs-mkdirp-stream", "version": "1.0.0", "description": "Ensure directories exist before writing to them.", "author": "Gulp Team (http://gulpjs.com/)", "contributors": [ "Blaine Bublitz " ], "repository": "gulpjs/fs-mkdirp-stream", "license": "MIT", "engines": { "node": ">= 0.10" }, "main": "index.js", "files": [ "LICENSE", "index.js", "mkdirp.js" ], "scripts": { "lint": "eslint index.js mkdirp.js test/ && jscs index.js mkdirp.js test/", "pretest": "npm run lint", "test": "mocha --async-only", "cover": "istanbul cover _mocha --report lcovonly", "coveralls": "npm run cover && istanbul-coveralls" }, "dependencies": { "graceful-fs": "^4.1.11", "through2": "^2.0.3" }, "devDependencies": { "eslint": "^1.10.3", "eslint-config-gulp": "^2.0.0", "expect": "^1.20.2", "istanbul": "^0.4.3", "istanbul-coveralls": "^1.0.3", "jscs": "^2.4.0", "jscs-preset-gulp": "^1.0.0", "mississippi": "^1.3.0", "mocha": "^3.2.0", "rimraf": "^2.6.1" }, "keywords": [ "fs", "mkdirp", "stream", "mkdir", "directory", "directories", "ensure" ] } fs-mkdirp-stream-1.0.0/test/000077500000000000000000000000001310571707700156645ustar00rootroot00000000000000fs-mkdirp-stream-1.0.0/test/.eslintrc000066400000000000000000000000351310571707700175060ustar00rootroot00000000000000{ "extends": "gulp/test" } fs-mkdirp-stream-1.0.0/test/index.js000066400000000000000000000076751310571707700173500ustar00rootroot00000000000000'use strict'; var os = require('os'); var path = require('path'); var fs = require('graceful-fs'); var miss = require('mississippi'); var expect = require('expect'); var rimraf = require('rimraf'); var mkdirpStream = require('../'); var pipe = miss.pipe; var from = miss.from; var concat = miss.concat; describe('mkdirpStream', function() { var MASK_MODE = parseInt('7777', 8); var isWindows = (os.platform() === 'win32'); var outputBase = path.join(__dirname, './out-fixtures'); var outputDirpath = path.join(outputBase, './foo'); function cleanup(done) { this.timeout(20000); expect.restoreSpies(); // Async del to get sort-of-fix for https://github.com/isaacs/rimraf/issues/72 rimraf(outputBase, done); } function masked(mode) { return mode & MASK_MODE; } function statMode(outputPath) { return masked(fs.lstatSync(outputPath).mode); } function applyUmask(mode) { if (typeof mode !== 'number') { mode = parseInt(mode, 8); } return (mode & ~process.umask()); } beforeEach(cleanup); afterEach(cleanup); beforeEach(function(done) { fs.mkdir(outputBase, function(err) { if (err) { return done(err); } // Linux inherits the setgid of the directory and it messes up our assertions // So we explixitly set the mode to 777 before each test fs.chmod(outputBase, '777', done); }); }); it('exports a main function, .obj and .withMode methods', function(done) { expect(typeof mkdirpStream).toEqual('function'); expect(typeof mkdirpStream.obj).toEqual('function'); done(); }); it('takes a string to create', function(done) { function assert() { expect(statMode(outputDirpath)).toExist(); } pipe([ from(['test']), mkdirpStream(outputDirpath), concat(assert), ], done); }); it('takes a resolver function that receives chunk', function(done) { function resolver(chunk, cb) { expect(chunk).toEqual('test'); cb(null, outputDirpath); } function assert() { expect(statMode(outputDirpath)).toExist(); } pipe([ from(['test']), mkdirpStream(resolver), concat(assert), ], done); }); it('can pass a mode as the 3rd argument to the resolver callback', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); function resolver(chunk, cb) { expect(chunk).toEqual('test'); cb(null, outputDirpath, mode); } function assert() { expect(statMode(outputDirpath)).toEqual(mode); } pipe([ from(['test']), mkdirpStream(resolver), concat(assert), ], done); }); it('can pass an error as the 1st argument to the resolver callback to error', function(done) { function resolver(chunk, cb) { cb(new Error('boom')); } function notExists() { statMode(outputDirpath); } function assert(err) { expect(err).toExist(); expect(notExists).toThrow(); done(); } pipe([ from(['test']), mkdirpStream(resolver), concat(), ], assert); }); it('works with objectMode', function(done) { function resolver(chunk, cb) { expect(typeof chunk).toEqual('object'); expect(chunk.dirname).toExist(); cb(null, chunk.dirname); } function assert() { expect(statMode(outputDirpath)).toExist(); } pipe([ from.obj([{ dirname: outputDirpath }]), mkdirpStream.obj(resolver), concat(assert), ], done); }); it('bubbles mkdir errors', function(done) { expect.spyOn(fs, 'mkdir').andCall(function(dirpath, mode, cb) { cb(new Error('boom')); }); function notExists() { statMode(outputDirpath); } function assert(err) { expect(err).toExist(); expect(notExists).toThrow(); done(); } pipe([ from(['test']), mkdirpStream(outputDirpath), concat(), ], assert); }); }); fs-mkdirp-stream-1.0.0/test/mkdirp.js000066400000000000000000000162161310571707700175160ustar00rootroot00000000000000'use strict'; var os = require('os'); var path = require('path'); var fs = require('graceful-fs'); var expect = require('expect'); var rimraf = require('rimraf'); var mkdirp = require('../mkdirp'); describe('mkdirp', function() { var MASK_MODE = parseInt('7777', 8); var DEFAULT_DIR_MODE = parseInt('0777', 8); var isWindows = (os.platform() === 'win32'); var outputBase = path.join(__dirname, './out-fixtures'); var outputDirpath = path.join(outputBase, './foo'); var outputNestedPath = path.join(outputDirpath, './test.txt'); var outputNestedDirpath = path.join(outputDirpath, './bar/baz/'); var contents = 'Hello World!\n'; function cleanup(done) { this.timeout(20000); expect.restoreSpies(); // Async del to get sort-of-fix for https://github.com/isaacs/rimraf/issues/72 rimraf(outputBase, done); } function masked(mode) { return mode & MASK_MODE; } function statMode(outputPath) { return masked(fs.lstatSync(outputPath).mode); } function applyUmask(mode) { if (typeof mode !== 'number') { mode = parseInt(mode, 8); } return (mode & ~process.umask()); } beforeEach(cleanup); afterEach(cleanup); beforeEach(function(done) { fs.mkdir(outputBase, function(err) { if (err) { return done(err); } // Linux inherits the setgid of the directory and it messes up our assertions // So we explixitly set the mode to 777 before each test fs.chmod(outputBase, '777', done); }); }); it('makes a single directory', function(done) { mkdirp(outputDirpath, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toExist(); done(); }); }); it('makes single directory w/ default mode', function(done) { if (isWindows) { this.skip(); return; } var defaultMode = applyUmask(DEFAULT_DIR_MODE); mkdirp(outputDirpath, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toEqual(defaultMode); done(); }); }); it('makes multiple directories', function(done) { mkdirp(outputNestedDirpath, function(err) { expect(err).toNotExist(); expect(statMode(outputNestedDirpath)).toExist(); done(); }); }); it('makes multiple directories w/ default mode', function(done) { if (isWindows) { this.skip(); return; } var defaultMode = applyUmask(DEFAULT_DIR_MODE); mkdirp(outputNestedDirpath, function(err) { expect(err).toNotExist(); expect(statMode(outputNestedDirpath)).toEqual(defaultMode); done(); }); }); it('makes directory with custom mode', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); mkdirp(outputDirpath, mode, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toEqual(mode); done(); }); }); it('can create a directory with setgid permission', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('2700'); mkdirp(outputDirpath, mode, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toEqual(mode); done(); }); }); it('does not change directory mode if exists and no mode given', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); mkdirp(outputDirpath, mode, function(err) { expect(err).toNotExist(); mkdirp(outputDirpath, function(err2) { expect(err2).toNotExist(); expect(statMode(outputDirpath)).toEqual(mode); done(); }); }); }); it('makes multiple directories with custom mode', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); mkdirp(outputNestedDirpath, mode, function(err) { expect(err).toNotExist(); expect(statMode(outputNestedDirpath)).toEqual(mode); done(); }); }); it('uses default mode on intermediate directories', function(done) { if (isWindows) { this.skip(); return; } var intermediateDirpath = path.dirname(outputNestedDirpath); var mode = applyUmask('700'); var defaultMode = applyUmask(DEFAULT_DIR_MODE); mkdirp(outputNestedDirpath, mode, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toEqual(defaultMode); expect(statMode(intermediateDirpath)).toEqual(defaultMode); done(); }); }); it('changes mode of existing directory', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); var defaultMode = applyUmask(DEFAULT_DIR_MODE); mkdirp(outputDirpath, function(err) { expect(err).toNotExist(); expect(statMode(outputDirpath)).toEqual(defaultMode); mkdirp(outputDirpath, mode, function(err2) { expect(err2).toNotExist(); expect(statMode(outputDirpath)).toEqual(mode); done(); }); }); }); it('errors with EEXIST if file in path', function(done) { mkdirp(outputDirpath, function(err) { expect(err).toNotExist(); fs.writeFile(outputNestedPath, contents, function(err2) { expect(err2).toNotExist(); mkdirp(outputNestedPath, function(err3) { expect(err3).toExist(); expect(err3.code).toEqual('EEXIST'); done(); }); }); }); }); it('does not change mode of existing file', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); mkdirp(outputDirpath, function(err) { expect(err).toNotExist(); fs.writeFile(outputNestedPath, contents, function(err2) { expect(err2).toNotExist(); var expectedMode = statMode(outputNestedPath); mkdirp(outputNestedPath, mode, function(err3) { expect(err3).toExist(); expect(statMode(outputNestedPath)).toEqual(expectedMode); done(); }); }); }); }); it('surfaces mkdir errors that happening during recursion', function(done) { var ogMkdir = fs.mkdir; var spy = expect.spyOn(fs, 'mkdir').andCall(function(dirpath, mode, cb) { if (spy.calls.length === 1) { return ogMkdir(dirpath, mode, cb); } cb(new Error('boom')); }); mkdirp(outputNestedDirpath, function(err) { expect(err).toExist(); done(); }); }); it('surfaces fs.stat errors', function(done) { expect.spyOn(fs, 'stat').andCall(function(dirpath, cb) { cb(new Error('boom')); }); mkdirp(outputDirpath, function(err) { expect(err).toExist(); done(); }); }); it('does not attempt fs.chmod if custom mode matches mode on disk', function(done) { if (isWindows) { this.skip(); return; } var mode = applyUmask('700'); mkdirp(outputDirpath, mode, function(err) { expect(err).toNotExist(); var spy = expect.spyOn(fs, 'chmod').andCallThrough(); mkdirp(outputDirpath, mode, function(err) { expect(err).toNotExist(); expect(spy.calls.length).toEqual(0); done(); }); }); }); });