🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

fs-jetpack

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fs-jetpack - npm Package Compare versions

Comparing version

to
0.9.0

benchmark/utils.js

120

benchmark/copy.js

@@ -0,1 +1,3 @@

// Benchmark to make sure performance of copy is near 'native' bash command.
/* eslint no-console: 0 */

@@ -9,49 +11,87 @@

var promisedExec = Q.denodeify(childProcess.exec);
var benchUtils = require('./utils');
var jetpack = require('..');
var startTimer = function () {
var start = Date.now();
return function stop() {
return Date.now() - start;
};
};
var testDir = jetpack.dir(os.tmpdir() + '/jetpack-benchmark', { empty: true });
var toCopyDir = testDir.dir('to-copy');
for (var i = 0; i < 10000; i += 1) {
toCopyDir.file(i + '.txt', { content: 'text' });
toCopyDir.file(i + '.md', { content: 'markdown' });
}
var stop;
var timer;
var jetpackTime;
var jetpackFilteredTime;
var nativeTime;
stop = startTimer();
toCopyDir.copyAsync('.', testDir.path('copied-jetpack'))
.then(function () {
jetpackTime = stop();
console.log('Jetpack took ' + jetpackTime + 'ms');
stop = startTimer();
return toCopyDir.copyAsync('.', testDir.path('copied-filtered-jetpack'), {
matching: '*.txt'
var prepareFiles = function (testConfig) {
return new Q.Promise(function (resolve, reject) {
var count = 0;
var content = new Buffer(testConfig.size);
var makeOneFile = function () {
toCopyDir.fileAsync(count + '.txt', { content: content })
.then(function () {
count += 1;
if (count < testConfig.files) {
makeOneFile();
} else {
resolve();
}
}, reject);
};
console.log('Preparing ' + testConfig.files + ' test files (' +
benchUtils.humanFileSize(testConfig.size, true) + ' each)...');
makeOneFile();
});
})
.then(function () {
jetpackFilteredTime = stop();
console.log('Jetpack with *.txt filter took ' + jetpackFilteredTime + 'ms');
stop = startTimer();
return promisedExec('cp -R ' + toCopyDir.path() + ' ' + testDir.path('copied-native'));
})
.then(function () {
nativeTime = stop();
console.log('Native took ' + nativeTime + 'ms');
var times = jetpackTime / nativeTime;
console.log('Jetpack is ' + times.toFixed(1) + ' times slower than native');
testDir.remove('.');
})
.catch(function (err) {
console.log(err);
});
};
var waitAWhile = function () {
return new Q.Promise(function (resolve) {
console.log('Waiting 10s to allow hardware buffers be emptied...');
setTimeout(resolve, 10000);
});
};
var test = function (testConfig) {
console.log('----------------------');
return prepareFiles(testConfig)
.then(waitAWhile)
.then(function () {
timer = benchUtils.startTimer('jetpack.copyAsync()');
return toCopyDir.copyAsync('.', testDir.path('copied-jetpack'));
})
.then(function () {
jetpackTime = timer();
return waitAWhile();
})
.then(function () {
timer = benchUtils.startTimer('Native cp -R');
return promisedExec('cp -R ' + toCopyDir.path() + ' ' + testDir.path('copied-native'));
})
.then(function () {
nativeTime = timer();
console.log('Jetpack is ' + (jetpackTime / nativeTime).toFixed(1) +
' times slower than native');
console.log('Cleaning up after test...');
return testDir.removeAsync();
})
.catch(function (err) {
console.log(err);
});
};
var testConfigs = [{
files: 10000,
size: 100
}, {
files: 1000,
size: 1000 * 100
}, {
files: 100,
size: 1000 * 1000 * 10
}];
var runNext = function () {
if (testConfigs.length > 0) {
test(testConfigs.pop()).then(runNext);
}
};
runNext();

@@ -0,1 +1,6 @@

0.9.0 (2016-05-10)
-------------------
* **(breaking change)** `read()`, `list()`, `inspect()` and `inspectTree()` returns `undefined` instead of `null` if path doesn't exist.
* More sane edge cases for `dir()`, `file()` and `list()`.
0.8.0 (2016-04-09)

@@ -2,0 +7,0 @@ -------------------

@@ -10,14 +10,14 @@ 'use strict';

var matcher = require('./utils/matcher');
var mode = require('./utils/mode');
var inspector = require('./inspector');
var fileOps = require('./file_ops');
var fileMode = require('./utils/mode');
var inspectTree = require('./inspect_tree');
var write = require('./write');
var parseOptions = function (options, from) {
var opts = options || {};
var parsedOptions = {};
options = options || {};
parsedOptions.overwrite = options.overwrite;
parsedOptions.overwrite = opts.overwrite;
if (options.matching) {
parsedOptions.allowedToCopy = matcher.create(options.matching, from);
if (opts.matching) {
parsedOptions.allowedToCopy = matcher.create(opts.matching, from);
} else {

@@ -49,44 +49,59 @@ parsedOptions.allowedToCopy = function () {

var copySync = function (inspectData, to) {
var mod = mode.normalizeFileMode(inspectData.mode);
var checksBeforeCopyingSync = function (from, to, opts) {
if (!exists.sync(from)) {
throw generateNoSourceError(from);
}
if (exists.sync(to) && !opts.overwrite) {
throw generateDestinationExistsError(to);
}
};
var copyFileSync = function (from, to, mode) {
var data = fs.readFileSync(from);
write.sync(to, data, { mode: mode });
};
var copySymlinkSync = function (from, to) {
var symlinkPointsAt = fs.readlinkSync(from);
try {
fs.symlinkSync(symlinkPointsAt, to);
} catch (err) {
// There is already file/symlink with this name on destination location.
// Must erase it manually, otherwise system won't allow us to place symlink there.
if (err.code === 'EEXIST') {
fs.unlinkSync(to);
// Retry...
fs.symlinkSync(symlinkPointsAt, to);
} else {
throw err;
}
}
};
var copyItemSync = function (inspectData, to) {
var mode = fileMode.normalizeFileMode(inspectData.mode);
if (inspectData.type === 'dir') {
mkdirp.sync(to, { mode: mod });
mkdirp.sync(to, { mode: mode });
} else if (inspectData.type === 'file') {
var data = fs.readFileSync(inspectData.absolutePath);
fileOps.write(to, data, { mode: mod });
copyFileSync(inspectData.absolutePath, to, mode);
} else if (inspectData.type === 'symlink') {
var symlinkPointsAt = fs.readlinkSync(inspectData.absolutePath);
try {
fs.symlinkSync(symlinkPointsAt, to);
} catch (err) {
// There is already file/symlink with this name on destination location.
// Must erase it manually, otherwise system won't allow us to place symlink there.
if (err.code === 'EEXIST') {
fs.unlinkSync(to);
// Retry...
fs.symlinkSync(symlinkPointsAt, to);
} else {
throw err;
}
}
copySymlinkSync(inspectData.absolutePath, to);
}
};
var sync = function (from, to, options) {
options = parseOptions(options, from);
var copySync = function (from, to, options) {
var opts = parseOptions(options, from);
var walker;
var inspectData;
var destPath;
if (!exists.sync(from)) {
throw generateNoSourceError(from);
}
checksBeforeCopyingSync(from, to, opts);
if (exists.sync(to) && !options.overwrite) {
throw generateDestinationExistsError(to);
}
var walker = inspector.createTreeWalkerSync(from);
walker = inspectTree.createTreeWalkerSync(from);
while (walker.hasNext()) {
var inspectData = walker.getNext();
var destPath = pathUtil.join(to, inspectData.relativePath);
if (options.allowedToCopy(inspectData.absolutePath)) {
copySync(inspectData, destPath);
inspectData = walker.getNext();
destPath = pathUtil.join(to, inspectData.relativePath);
if (opts.allowedToCopy(inspectData.absolutePath)) {
copyItemSync(inspectData, destPath);
}

@@ -106,81 +121,102 @@ }

var copyAsync = function (inspectData, to) {
var mod = mode.normalizeFileMode(inspectData.mode);
var checksBeforeCopyingAsync = function (from, to, opts) {
return exists.async(from)
.then(function (srcPathExists) {
if (!srcPathExists) {
throw generateNoSourceError(from);
} else {
return exists.async(to);
}
})
.then(function (destPathExists) {
if (destPathExists && !opts.overwrite) {
throw generateDestinationExistsError(to);
}
});
};
var copyFileAsync = function (from, to, mode) {
return promisedReadFile(from)
.then(function (data) {
return write.async(to, data, { mode: mode });
});
};
var copySymlinkAsync = function (from, to) {
return promisedReadlink(from)
.then(function (symlinkPointsAt) {
var deferred = Q.defer();
promisedSymlink(symlinkPointsAt, to)
.then(deferred.resolve)
.catch(function (err) {
if (err.code === 'EEXIST') {
// There is already file/symlink with this name on destination location.
// Must erase it manually, otherwise system won't allow us to place symlink there.
promisedUnlink(to)
.then(function () {
// Retry...
return promisedSymlink(symlinkPointsAt, to);
})
.then(deferred.resolve, deferred.reject);
} else {
deferred.reject(err);
}
});
return deferred.promise;
});
};
var copyItemAsync = function (inspectData, to) {
var mode = fileMode.normalizeFileMode(inspectData.mode);
if (inspectData.type === 'dir') {
return promisedMkdirp(to, { mode: mod });
return promisedMkdirp(to, { mode: mode });
} else if (inspectData.type === 'file') {
return promisedReadFile(inspectData.absolutePath)
.then(function (data) {
return fileOps.writeAsync(to, data, { mode: mod });
});
return copyFileAsync(inspectData.absolutePath, to, mode);
} else if (inspectData.type === 'symlink') {
return promisedReadlink(inspectData.absolutePath)
.then(function (symlinkPointsAt) {
var deferred = Q.defer();
promisedSymlink(symlinkPointsAt, to)
.then(deferred.resolve)
.catch(function (err) {
if (err.code === 'EEXIST') {
// There is already file/symlink with this name on destination location.
// Must erase it manually, otherwise system won't allow us to place symlink there.
promisedUnlink(to)
.then(function () {
// Retry...
return promisedSymlink(symlinkPointsAt, to);
})
.then(deferred.resolve, deferred.reject);
} else {
deferred.reject(err);
}
});
return deferred.promise;
});
return copySymlinkAsync(inspectData.absolutePath, to);
}
// Ha! This is none of supported file system entities. What now?
// Just continuing without actually copying sounds sane.
return new Q();
};
var async = function (from, to, options) {
var runCopyLoop = function (from, to, opts) {
var deferred = Q.defer();
var inspectData;
var destPath;
var startCopying = function () {
var copyNext = function (walker) {
if (walker.hasNext()) {
var inspectData = walker.getNext();
var destPath = pathUtil.join(to, inspectData.relativePath);
if (options.allowedToCopy(inspectData.absolutePath)) {
copyAsync(inspectData, destPath)
.then(function () {
copyNext(walker);
})
.catch(deferred.reject);
} else {
var copyNext = function (walker) {
if (walker.hasNext()) {
inspectData = walker.getNext();
destPath = pathUtil.join(to, inspectData.relativePath);
if (opts.allowedToCopy(inspectData.absolutePath)) {
copyItemAsync(inspectData, destPath)
.then(function () {
copyNext(walker);
}
})
.catch(deferred.reject);
} else {
deferred.resolve();
copyNext(walker);
}
};
inspector.createTreeWalkerAsync(from).then(copyNext);
} else {
deferred.resolve();
}
};
options = parseOptions(options, from);
inspectTree.createTreeWalkerAsync(from).then(copyNext);
// Checks before copying
exists.async(from)
.then(function (srcPathExists) {
if (!srcPathExists) {
throw generateNoSourceError(from);
} else {
return exists.async(to);
}
return deferred.promise;
};
var copyAsync = function (from, to, options) {
var deferred = Q.defer();
var opts = parseOptions(options, from);
checksBeforeCopyingAsync(from, to, opts)
.then(function () {
return runCopyLoop(from, to, opts);
})
.then(function (destPathExists) {
if (destPathExists && !options.overwrite) {
throw generateDestinationExistsError(to);
} else {
startCopying();
}
})
.then(deferred.resolve)
.catch(deferred.reject);

@@ -195,3 +231,3 @@

module.exports.sync = sync;
module.exports.async = async;
exports.sync = copySync;
exports.async = copyAsync;

@@ -11,6 +11,4 @@ 'use strict';

function getCriteriaDefaults(criteria) {
if (criteria === undefined) {
criteria = {};
}
var getCriteriaDefaults = function (passedCriteria) {
var criteria = passedCriteria || {};
if (typeof criteria.empty !== 'boolean') {

@@ -23,4 +21,9 @@ criteria.empty = false;

return criteria;
}
};
var generatePathOccupiedByNotDirectoryError = function (path) {
return new Error('Path ' + path + ' exists but is not a directory.' +
' Halting jetpack.dir() call for safety reasons.');
};
// ---------------------------------------------------------

@@ -30,7 +33,7 @@ // Sync

var sync = function (path, criteria) {
criteria = getCriteriaDefaults(criteria);
var checkWhatAlreadyOccupiesPathSync = function (path) {
var stat;
try {
var stat = fs.statSync(path);
stat = fs.statSync(path);
} catch (err) {

@@ -43,14 +46,26 @@ // Detection if path already exists

if (stat && stat.isFile()) {
// This is file, but should be directory.
fs.unlinkSync(path);
// Clear stat variable to indicate now nothing is there
stat = undefined;
if (stat && !stat.isDirectory()) {
throw generatePathOccupiedByNotDirectoryError(path);
}
if (stat) {
// Ensure existing directory matches criteria
return stat;
};
var createBrandNewDirectorySync = function (path, criteria) {
mkdirp.sync(path, { mode: criteria.mode });
};
var checkExistingDirectoryFulfillsCriteriaSync = function (path, stat, criteria) {
var checkMode = function () {
var mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
fs.chmodSync(path, criteria.mode);
}
};
var checkEmptiness = function () {
var list;
if (criteria.empty) {
// Delete everything inside this directory
var list = fs.readdirSync(path);
list = fs.readdirSync(path);
list.forEach(function (filename) {

@@ -60,11 +75,15 @@ rimraf.sync(pathUtil.resolve(path, filename));

}
};
var mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
// Mode is different than specified in criteria, fix that.
fs.chmodSync(path, criteria.mode);
}
checkMode();
checkEmptiness();
};
var dirSync = function (path, passedCriteria) {
var criteria = getCriteriaDefaults(passedCriteria);
var stat = checkWhatAlreadyOccupiesPathSync(path);
if (stat) {
checkExistingDirectoryFulfillsCriteriaSync(path, stat, criteria);
} else {
// Directory doesn't exist now. Create it.
mkdirp.sync(path, { mode: criteria.mode });
createBrandNewDirectorySync(path, criteria);
}

@@ -83,4 +102,28 @@ };

var checkWhatAlreadyOccupiesPathAsync = function (path) {
var deferred = Q.defer();
promisedStat(path)
.then(function (stat) {
if (stat.isDirectory()) {
deferred.resolve(stat);
} else {
deferred.reject(generatePathOccupiedByNotDirectoryError(path));
}
})
.catch(function (err) {
if (err.code === 'ENOENT') {
// Path doesn't exist
deferred.resolve(undefined);
} else {
// This is other error that nonexistent path, so end here.
deferred.reject(err);
}
});
return deferred.promise;
};
// Delete all files and directores inside given directory
var empty = function (path) {
var emptyAsync = function (path) {
var deferred = Q.defer();

@@ -91,6 +134,7 @@

var doOne = function (index) {
var subPath;
if (index === list.length) {
deferred.resolve();
} else {
var subPath = pathUtil.resolve(path, list[index]);
subPath = pathUtil.resolve(path, list[index]);
promisedRimraf(subPath).then(function () {

@@ -109,85 +153,42 @@ doOne(index + 1);

var async = function (path, criteria) {
var checkExistingDirectoryFulfillsCriteriaAsync = function (path, stat, criteria) {
var deferred = Q.defer();
criteria = getCriteriaDefaults(criteria);
var checkMode = function () {
var mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
return promisedChmod(path, criteria.mode);
}
return new Q();
};
var checkWhatWeHaveNow = function () {
var checkDeferred = Q.defer();
promisedStat(path)
.then(function (stat) {
if (stat.isFile()) {
// This is not a directory, and should be.
promisedRimraf(path)
.then(function () {
// We just deleted that path, so can't
// pass stat further down.
checkDeferred.resolve(undefined);
})
.catch(checkDeferred.reject);
} else {
checkDeferred.resolve(stat);
}
})
.catch(function (err) {
if (err.code === 'ENOENT') {
// Path doesn't exist
checkDeferred.resolve(undefined);
} else {
// This is other error that nonexistent path, so end here.
checkDeferred.reject(err);
}
});
return checkDeferred.promise;
var checkEmptiness = function () {
if (criteria.empty) {
return emptyAsync(path);
}
return new Q();
};
var checkWhatShouldBe = function (stat) {
var checkDeferred = Q.defer();
checkMode()
.then(checkEmptiness)
.then(deferred.resolve, deferred.reject);
var needToCheckMoreCriteria = function () {
var checkEmptiness = function () {
if (criteria.empty) {
// Delete everything inside this directory
empty(path)
.then(checkDeferred.resolve, checkDeferred.reject);
} else {
// Everything done!
checkDeferred.resolve();
}
};
return deferred.promise;
};
var checkMode = function () {
var mode = modeUtil.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
// Mode is different than specified in criteria, fix that
promisedChmod(path, criteria.mode)
.then(checkEmptiness, checkDeferred.reject);
} else {
checkEmptiness();
}
};
var createBrandNewDirectoryAsync = function (path, criteria) {
return promisedMkdirp(path, { mode: criteria.mode });
};
checkMode();
};
var dirAsync = function (path, passedCriteria) {
var deferred = Q.defer();
var criteria = getCriteriaDefaults(passedCriteria);
var checkExistence = function () {
if (!stat) {
promisedMkdirp(path, { mode: criteria.mode })
.then(checkDeferred.resolve, checkDeferred.reject);
} else {
// Directory exists, but we still don't
// know if it matches all criteria.
needToCheckMoreCriteria();
}
};
checkExistence();
return checkDeferred.promise;
};
checkWhatWeHaveNow()
.then(checkWhatShouldBe)
checkWhatAlreadyOccupiesPathAsync(path)
.then(function (stat) {
if (stat !== undefined) {
return checkExistingDirectoryFulfillsCriteriaAsync(path, stat, criteria);
}
return createBrandNewDirectoryAsync(path, criteria);
})
.then(deferred.resolve, deferred.reject);

@@ -202,3 +203,3 @@

module.exports.sync = sync;
module.exports.async = async;
module.exports.sync = dirSync;
module.exports.async = dirAsync;

@@ -10,5 +10,6 @@ 'use strict';

var sync = function (path) {
var existsSync = function (path) {
var stat;
try {
var stat = fs.statSync(path);
stat = fs.statSync(path);
if (stat.isDirectory()) {

@@ -33,3 +34,3 @@ return 'dir';

var async = function (path) {
var existsAsync = function (path) {
var deferred = Q.defer();

@@ -60,3 +61,3 @@

module.exports.sync = sync;
module.exports.async = async;
exports.sync = existsSync;
exports.async = existsAsync;

@@ -5,17 +5,19 @@ 'use strict';

var Q = require('q');
var rimraf = require('rimraf');
var modeUtils = require('./utils/mode');
var fileOps = require('./file_ops');
var modeUtil = require('./utils/mode');
var write = require('./write');
function getCriteriaDefaults(criteria) {
if (criteria === undefined) {
criteria = {};
}
var getCriteriaDefaults = function (passedCriteria) {
var criteria = passedCriteria || {};
if (criteria.mode !== undefined) {
criteria.mode = modeUtils.normalizeFileMode(criteria.mode);
criteria.mode = modeUtil.normalizeFileMode(criteria.mode);
}
return criteria;
}
};
var generatePathOccupiedByNotFileError = function (path) {
return new Error('Path ' + path + ' exists but is not a file.' +
' Halting jetpack.file() call for safety reasons.');
};
// ---------------------------------------------------------

@@ -25,7 +27,7 @@ // Sync

var sync = function (path, criteria) {
criteria = getCriteriaDefaults(criteria);
var checkWhatAlreadyOccupiesPathSync = function (path) {
var stat;
try {
var stat = fs.statSync(path);
stat = fs.statSync(path);
} catch (err) {

@@ -39,35 +41,55 @@ // Detection if path exists

if (stat && !stat.isFile()) {
// This have to be file, so if is directory must be removed.
rimraf.sync(path);
// Clear stat variable to indicate now nothing is there.
stat = undefined;
throw generatePathOccupiedByNotFileError(path);
}
if (stat) {
// Ensure file mode
var mode = modeUtils.normalizeFileMode(stat.mode);
if (criteria.mode !== undefined && criteria.mode !== mode) {
fs.chmodSync(path, criteria.mode);
}
return stat;
};
// Ensure file content
var checkExistingFileFulfillsCriteriaSync = function (path, stat, criteria) {
var mode = modeUtil.normalizeFileMode(stat.mode);
var checkContent = function () {
if (criteria.content !== undefined) {
fileOps.write(path, criteria.content, {
write.sync(path, criteria.content, {
mode: mode,
jsonIndent: criteria.jsonIndent
});
return true;
}
} else {
// File doesn't exist. Create it.
var content = '';
if (criteria.content !== undefined) {
content = criteria.content;
return false;
};
var checkMode = function () {
if (criteria.mode !== undefined && criteria.mode !== mode) {
fs.chmodSync(path, criteria.mode);
}
fileOps.write(path, content, {
mode: criteria.mode,
jsonIndent: criteria.jsonIndent
});
};
var contentReplaced = checkContent();
if (!contentReplaced) {
checkMode();
}
};
var createBrandNewFileSync = function (path, criteria) {
var content = '';
if (criteria.content !== undefined) {
content = criteria.content;
}
write.sync(path, content, {
mode: criteria.mode,
jsonIndent: criteria.jsonIndent
});
};
var fileSync = function (path, passedCriteria) {
var criteria = getCriteriaDefaults(passedCriteria);
var stat = checkWhatAlreadyOccupiesPathSync(path);
if (stat !== undefined) {
checkExistingFileFulfillsCriteriaSync(path, stat, criteria);
} else {
createBrandNewFileSync(path, criteria);
}
};
// ---------------------------------------------------------

@@ -79,87 +101,88 @@ // Async

var promisedChmod = Q.denodeify(fs.chmod);
var promisedRimraf = Q.denodeify(rimraf);
var async = function (path, criteria) {
var checkWhatAlreadyOccupiesPathAsync = function (path) {
var deferred = Q.defer();
criteria = getCriteriaDefaults(criteria);
promisedStat(path)
.then(function (stat) {
if (stat.isFile()) {
deferred.resolve(stat);
} else {
deferred.reject(generatePathOccupiedByNotFileError(path));
}
})
.catch(function (err) {
if (err.code === 'ENOENT') {
// Path doesn't exist.
deferred.resolve(undefined);
} else {
// This is other error. Must end here.
deferred.reject(err);
}
});
var checkWhatWeHaveNow = function () {
var checkDeferred = Q.defer();
return deferred.promise;
};
promisedStat(path)
.then(function (stat) {
if (stat.isDirectory()) {
// This is not a file, so remove it.
promisedRimraf(path)
.then(function () {
// Clear stat variable to indicate now nothing is there
checkDeferred.resolve(undefined);
})
.catch(checkDeferred.reject);
} else {
checkDeferred.resolve(stat);
}
})
.catch(function (err) {
if (err.code === 'ENOENT') {
// Path doesn't exist.
checkDeferred.resolve(undefined);
} else {
// This is other error. Must end here.
checkDeferred.reject(err);
}
});
var checkExistingFileFulfillsCriteriaAsync = function (path, stat, criteria) {
var mode = modeUtil.normalizeFileMode(stat.mode);
return checkDeferred.promise;
};
var checkContent = function () {
var deferred = Q.defer();
var checkWhatShouldBe = function (stat) {
var checkDeferred = Q.defer();
if (!stat) {
// Path doesn't exist now. Put file there.
var content = '';
if (criteria.content !== undefined) {
content = criteria.content;
}
fileOps.writeAsync(path, content, {
mode: criteria.mode,
if (criteria.content !== undefined) {
write.async(path, criteria.content, {
mode: mode,
jsonIndent: criteria.jsonIndent
})
.then(checkDeferred.resolve, checkDeferred.reject);
.then(function () {
deferred.resolve(true);
})
.catch(deferred.reject);
} else {
// File already exists. Must do more checking.
deferred.resolve(false);
}
var mode = modeUtils.normalizeFileMode(stat.mode);
return deferred.promise;
};
var checkMode = function () {
if (criteria.mode !== undefined && criteria.mode !== mode) {
promisedChmod(path, criteria.mode)
.then(checkDeferred.resolve, checkDeferred.reject);
} else {
checkDeferred.resolve();
}
};
var checkMode = function () {
if (criteria.mode !== undefined && criteria.mode !== mode) {
return promisedChmod(path, criteria.mode);
}
return undefined;
};
var checkContent = function () {
if (criteria.content !== undefined) {
fileOps.writeAsync(path, criteria.content, {
mode: mode,
jsonIndent: criteria.jsonIndent
})
.then(checkDeferred.resolve, checkDeferred.reject);
} else {
checkMode();
}
};
checkContent();
return checkContent()
.then(function (contentReplaced) {
if (!contentReplaced) {
return checkMode();
}
return undefined;
});
};
return checkDeferred.promise;
};
var createBrandNewFileAsync = function (path, criteria) {
var content = '';
if (criteria.content !== undefined) {
content = criteria.content;
}
checkWhatWeHaveNow()
.then(checkWhatShouldBe)
return write.async(path, content, {
mode: criteria.mode,
jsonIndent: criteria.jsonIndent
});
};
var fileAsync = function (path, passedCriteria) {
var deferred = Q.defer();
var criteria = getCriteriaDefaults(passedCriteria);
checkWhatAlreadyOccupiesPathAsync(path)
.then(function (stat) {
if (stat !== undefined) {
return checkExistingFileFulfillsCriteriaAsync(path, stat, criteria);
}
return createBrandNewFileAsync(path, criteria);
})
.then(deferred.resolve, deferred.reject);

@@ -174,3 +197,3 @@

module.exports.sync = sync;
module.exports.async = async;
exports.sync = fileSync;
exports.async = fileAsync;

@@ -5,3 +5,3 @@ 'use strict';

var Q = require('q');
var inspector = require('./inspector');
var inspectTree = require('./inspect_tree');
var matcher = require('./utils/matcher');

@@ -24,3 +24,3 @@

return inspector.utils.flattenTree(tree)
return inspectTree.utils.flattenTree(tree)
.filter(function (inspectObj) {

@@ -62,11 +62,11 @@ return matchesAnyOfGlobs(inspectObj.absolutePath);

var sync = function (path, options) {
var findSync = function (path, options) {
var foundInspectObjects;
var tree;
tree = inspector.tree(path, {
tree = inspectTree.sync(path, {
absolutePath: true
});
if (tree === null) {
if (tree === undefined) {
throw generatePathDoesntExistError(path);

@@ -85,6 +85,6 @@ } else if (tree.type !== 'dir') {

var async = function (path, options) {
var findAsync = function (path, options) {
var deferred = Q.defer();
inspector.treeAsync(path, {
inspectTree.async(path, {
relativePath: true,

@@ -97,3 +97,3 @@ absolutePath: true

if (tree === null) {
if (tree === undefined) {
throw generatePathDoesntExistError(path);

@@ -117,3 +117,3 @@ } else if (tree.type !== 'dir') {

module.exports.sync = sync;
module.exports.async = async;
exports.sync = findSync;
exports.async = findAsync;

@@ -8,13 +8,17 @@ /* eslint no-param-reassign:0 */

var fileOps = require('./file_ops');
var inspector = require('./inspector');
var append = require('./append');
var dir = require('./dir');
var file = require('./file');
var find = require('./find');
var inspect = require('./inspect');
var inspectTree = require('./inspect_tree');
var copy = require('./copy');
var exists = require('./exists');
var list = require('./list');
var move = require('./move');
var read = require('./read');
var remove = require('./remove');
var symlink = require('./symlink');
var streams = require('./streams');
var write = require('./write');

@@ -68,6 +72,6 @@ // The Jetpack Context object.

append: function (path, data, options) {
fileOps.append(resolvePath(path), data, options);
append.sync(resolvePath(path), data, options);
},
appendAsync: function (path, data, options) {
return fileOps.appendAsync(resolvePath(path), data, options);
return append.async(resolvePath(path), data, options);
},

@@ -147,20 +151,20 @@

inspect: function (path, fieldsToInclude) {
return inspector.inspect(resolvePath(path), fieldsToInclude);
return inspect.sync(resolvePath(path), fieldsToInclude);
},
inspectAsync: function (path, fieldsToInclude) {
return inspector.inspectAsync(resolvePath(path), fieldsToInclude);
return inspect.async(resolvePath(path), fieldsToInclude);
},
inspectTree: function (path, options) {
return inspector.tree(resolvePath(path), options);
return inspectTree.sync(resolvePath(path), options);
},
inspectTreeAsync: function (path, options) {
return inspector.treeAsync(resolvePath(path), options);
return inspectTree.async(resolvePath(path), options);
},
list: function (path) {
return inspector.list(resolvePath(path || '.'));
return list.sync(resolvePath(path || '.'));
},
listAsync: function (path) {
return inspector.listAsync(resolvePath(path || '.'));
return list.async(resolvePath(path || '.'));
},

@@ -176,6 +180,6 @@

read: function (path, returnAs) {
return fileOps.read(resolvePath(path), returnAs);
return read.sync(resolvePath(path), returnAs);
},
readAsync: function (path, returnAs) {
return fileOps.readAsync(resolvePath(path), returnAs);
return read.async(resolvePath(path), returnAs);
},

@@ -211,6 +215,6 @@

write: function (path, data, options) {
fileOps.write(resolvePath(path), data, options);
write.sync(resolvePath(path), data, options);
},
writeAsync: function (path, data, options) {
return fileOps.writeAsync(resolvePath(path), data, options);
return write.async(resolvePath(path), data, options);
}

@@ -217,0 +221,0 @@ };

@@ -19,3 +19,3 @@ 'use strict';

var sync = function (from, to) {
var moveSync = function (from, to) {
try {

@@ -34,4 +34,4 @@ fs.renameSync(from, to);

if (!exists.sync(to)) {
var destDir = pathUtil.dirname(to);
mkdirp.sync(destDir);
// Some parent directory doesn't exist. Create it.
mkdirp.sync(pathUtil.dirname(to));
// Retry the attempt

@@ -70,3 +70,3 @@ fs.renameSync(from, to);

var async = function (from, to) {
var moveAsync = function (from, to) {
var deferred = Q.defer();

@@ -107,3 +107,3 @@

module.exports.sync = sync;
module.exports.async = async;
exports.sync = moveSync;
exports.async = moveAsync;

@@ -10,3 +10,3 @@ 'use strict';

var sync = function (path) {
var removeSync = function (path) {
rimraf.sync(path);

@@ -21,3 +21,3 @@ };

var async = function (path) {
var removeAsync = function (path) {
return qRimraf(path);

@@ -30,3 +30,3 @@ };

module.exports.sync = sync;
module.exports.async = async;
exports.sync = removeSync;
exports.async = removeAsync;

@@ -5,3 +5,3 @@ 'use strict';

module.exports.createWriteStream = fs.createWriteStream;
module.exports.createReadStream = fs.createReadStream;
exports.createWriteStream = fs.createWriteStream;
exports.createReadStream = fs.createReadStream;

@@ -12,3 +12,3 @@ 'use strict';

var sync = function (symlinkValue, path) {
var symlinkSync = function (symlinkValue, path) {
try {

@@ -34,3 +34,3 @@ fs.symlinkSync(symlinkValue, path);

var async = function (symlinkValue, path) {
var symlinkAsync = function (symlinkValue, path) {
var deferred = Q.defer();

@@ -60,3 +60,3 @@

module.exports.sync = sync;
module.exports.async = async;
exports.sync = symlinkSync;
exports.async = symlinkAsync;

@@ -7,40 +7,57 @@ // Matcher for glob patterns (e.g. *.txt, /a/b/**/z)

var create = function (patterns, basePath) {
if (typeof patterns === 'string') {
patterns = [patterns];
}
var convertPatternToAbsolutePath = function (passedPattern, basePath) {
// All patterns without slash are left as they are, if pattern contain
// any slash we need to turn it into absolute path.
var pattern = passedPattern;
var hasSlash = (pattern.indexOf('/') !== -1);
var isAbsolute;
var isNegated;
// Convert patterns to absolute paths
patterns = patterns.map(function (pattern) {
var hasSlash = (pattern.indexOf('/') !== -1);
// All patterns without slash are left as they are
if (hasSlash) {
// Maybe already is in the format we wanted
var isAbsolute = /^!?\//.test(pattern); // Starts with '/' or '!/'
if (!isAbsolute) {
var isNegated = (pattern[0] === '!');
if (hasSlash) {
// Maybe already is in the format we wanted
isAbsolute = /^!?\//.test(pattern); // Starts with '/' or '!/'
if (!isAbsolute) {
isNegated = (pattern[0] === '!');
// Remove starting characters which have meaning '!' and '.'
// and first slash to normalize the path.
if (isNegated) {
pattern = pattern.substring(1);
}
if (pattern[0] === '.') {
pattern = pattern.substring(1);
}
if (pattern[0] === '/') {
pattern = pattern.substring(1);
}
// Remove starting characters which have meaning '!' and '.'
// and first slash to normalize the path.
if (isNegated) {
pattern = pattern.substring(1);
}
if (pattern[0] === '.') {
pattern = pattern.substring(1);
}
if (pattern[0] === '/') {
pattern = pattern.substring(1);
}
// Finally construct ready pattern
if (isNegated) {
pattern = '!' + basePath + '/' + pattern;
} else {
pattern = basePath + '/' + pattern;
}
// Finally construct ready pattern
if (isNegated) {
pattern = '!' + basePath + '/' + pattern;
} else {
pattern = basePath + '/' + pattern;
}
}
return pattern;
}
return pattern;
};
var normalizePatterns = function (passedPatterns, basePath) {
var patterns;
if (typeof passedPatterns === 'string') {
// Patterns must be an Array
patterns = [passedPatterns];
} else {
patterns = passedPatterns;
}
return patterns.map(function (pattern) {
return convertPatternToAbsolutePath(pattern, basePath);
});
};
exports.create = function (passedPatterns, basePath) {
var patterns = normalizePatterns(passedPatterns, basePath);
var matchers = patterns.map(function (pattern) {

@@ -54,10 +71,12 @@ return new Minimatch(pattern, {

var doMatch = function (path) {
return function performMatch(path) {
var mode = 'matching';
var weHaveMatch = false;
var currentMatcher;
var i;
for (var i = 0; i < matchers.length; i += 1) {
var ma = matchers[i];
for (i = 0; i < matchers.length; i += 1) {
currentMatcher = matchers[i];
if (ma.negate) {
if (currentMatcher.negate) {
mode = 'negation';

@@ -72,3 +91,3 @@ if (i === 0) {

if (mode === 'negation' && weHaveMatch && !ma.match(path)) {
if (mode === 'negation' && weHaveMatch && !currentMatcher.match(path)) {
// One negation match is enought to know we can reject this one.

@@ -79,3 +98,3 @@ return false;

if (mode === 'matching' && !weHaveMatch) {
weHaveMatch = ma.match(path);
weHaveMatch = currentMatcher.match(path);
}

@@ -86,6 +105,2 @@ }

};
return doMatch;
};
module.exports.create = create;

@@ -6,7 +6,10 @@ // Logic for unix file mode operations.

// Converts mode to string 3 characters long.
module.exports.normalizeFileMode = function (rawMode) {
if (typeof rawMode === 'number') {
rawMode = rawMode.toString(8);
exports.normalizeFileMode = function (mode) {
var modeAsString;
if (typeof mode === 'number') {
modeAsString = mode.toString(8);
} else {
modeAsString = mode;
}
return rawMode.substring(rawMode.length - 3);
return modeAsString.substring(modeAsString.length - 3);
};
{
"name": "fs-jetpack",
"description": "Better file system API",
"version": "0.8.0",
"version": "0.9.0",
"author": "Jakub Szwacz <jakub@szwacz.com>",

@@ -6,0 +6,0 @@ "dependencies": {

fs-jetpack [![Build Status](https://travis-ci.org/szwacz/fs-jetpack.svg?branch=master)](https://travis-ci.org/szwacz/fs-jetpack) [![Build status](https://ci.appveyor.com/api/projects/status/er206e91fpuuqf58?svg=true)](https://ci.appveyor.com/project/szwacz/fs-jetpack)
==========
Node's [fs library](http://nodejs.org/api/fs.html) is very low level and because of that often painful to use. *fs-jetpack* wants to fix that by giving you completely rethought, much more conveninet API to work with file system.
Node's [fs library](http://nodejs.org/api/fs.html) is very low level and because of that often painful to use. *fs-jetpack* wants to fix that by giving you completely rethought, much more convenient API to work with file system.

@@ -32,3 +32,3 @@ #### [Jump to API Docs](#api)

// Want to make that call asnychronous? Just add the word "Async"
// Want to make that call asynchronous? Just add the word "Async"
// and it will give you promise instead of ready value.

@@ -62,7 +62,6 @@ jetpack.readAsync('file.txt')

Everyone who did something with files for sure seen (and probably hates) *"ENOENT, no such file or directory"* error. Jetpack tries to recover from that error if possible.
1. For wrte/creation operations, if any of parent directories doesn't exist jetpack will just create them as well.
2. For read/inspect operations, if file or directory doesn't exist `null` is returned instead of throwing.
1. For write/creation operations, if any of parent directories doesn't exist jetpack will just create lacking directories.
2. For read/inspect operations, if file or directory doesn't exist `undefined` is returned instead of throwing.
## Jetpack can do more in less code (examples)
All methods play nicely with each other. Here are few examples what it gives you.
## All methods play nicely with each other (examples)
**Note:** All examples are synchronous. Unfortunately asynchronous equivalents won't be that pretty.

@@ -137,24 +136,23 @@

**Methods:**
* [append](#append)
* [copy](#copy)
* [createReadStream](#create-read-stream)
* [createWriteStream](#create-write-stream)
* [cwd](#cwd)
* [dir](#dir)
* [exists](#exists)
* [file](#file)
* [find](#find)
* [inspect](#inspect)
* [inspectTree](#inspect-tree)
* [list](#list)
* [move](#move)
* [path](#path)
* [read](#read)
* [remove](#remove)
* [rename](#rename)
* [symlink](#symlink)
* [write](#write)
- [append](#appendpath-data-options)
- [copy](#copyfrom-to-options)
- [createReadStream](#createreadstreampath-options)
- [createWriteStream](#createwritestreampath-options)
- [cwd](#cwdpath)
- [dir](#dirpath-criteria)
- [exists](#existspath)
- [file](#filepath-criteria)
- [find](#findpath-searchoptions)
- [inspect](#inspectpath-options)
- [inspectTree](#inspecttreepath-options)
- [list](#listpath)
- [move](#movefrom-to)
- [path](#pathparts)
- [read](#readpath-returnas)
- [remove](#removepath)
- [rename](#renamepath-newname)
- [symlink](#symlinksymlinkvalue-path)
- [write](#writepath-data-options)
## <a name="append"></a> append(path, data, [options])
## append(path, data, [options])
asynchronous: **appendAsync(path, data, [options])**

@@ -174,3 +172,3 @@

## <a name="copy"></a> copy(from, to, [options])
## copy(from, to, [options])
asynchronous: **copyAsync(from, to, [options])**

@@ -192,3 +190,3 @@

```javascript
// Copies a file (and replaces it if one already exists in 'copied' direcotry)
// Copies a file (and replaces it if one already exists in 'copied' directory)
jetpack.copy('file.txt', 'copied/file.txt', { overwrite: true });

@@ -214,3 +212,3 @@

## <a name="create-read-stream"></a> createReadStream(path, [options])
## createReadStream(path, [options])

@@ -220,3 +218,3 @@ Just an alias to vanilla [fs.createReadStream](http://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options).

## <a name="create-write-stream"></a> createWriteStream(path, [options])
## createWriteStream(path, [options])

@@ -227,3 +225,3 @@ Just an alias to vanilla [fs.createWriteStream](http://nodejs.org/api/fs.html#fs_fs_createwritestream_path_options).

## <a name="cwd"></a> cwd([path...])
## cwd([path...])
Returns Current Working Directory (CWD) for this instance of jetpack, or creates new jetpack object with given path as its internal CWD.

@@ -262,3 +260,3 @@ **Note:** fs-jetpack never changes value of `process.cwd()`, the CWD we are talking about here is internal value inside every jetpack instance.

## <a name="dir"></a> dir(path, [criteria])
## dir(path, [criteria])
asynchronous: **dirAsync(path, [criteria])**

@@ -293,6 +291,6 @@

## <a name="exists"></a> exists(path)
## exists(path)
asynchronous: **existsAsync(path)**
Checks whether something exists on given `path`. This method returns values more specyfic than `true/false` to protect from errors like "I was expecting directory, but it was a file".
Checks whether something exists on given `path`. This method returns values more specific than `true/false` to protect from errors like "I was expecting directory, but it was a file".

@@ -306,3 +304,3 @@ **returns:**

## <a name="file"></a> file(path, [criteria])
## file(path, [criteria])
asynchronous: **fileAsync(path, [criteria])**

@@ -332,3 +330,3 @@

## <a name="find"></a> find([path], searchOptions)
## find([path], searchOptions)
asynchronous: **findAsync([path], searchOptions)**

@@ -364,3 +362,3 @@

## <a name="inspect"></a> inspect(path, [options])
## inspect(path, [options])
asynchronous: **inspectAsync(path, [options])**

@@ -376,7 +374,7 @@

* `times` (default `false`) if set to `true` will add atime, mtime and ctime fields (here called `accessTime`, `modifyTime` and `changeTime`).
* `absolutePath` (dafault `false`) if set to `true` will add absolute path to this resource.
* `symlinks` (dafault `false`) if set to `true` will just inspect symlink itself and not follow it.
* `absolutePath` (default `false`) if set to `true` will add absolute path to this resource.
* `symlinks` (default `false`) if set to `true` will just inspect symlink itself and not follow it.
**returns:**
`null` if given path doens't exist.
`undefined` if given path doens't exist.
Otherwise `Object` of structure:

@@ -400,3 +398,3 @@ ```javascript

## <a name="inspect-tree"></a> inspectTree(path, [options])
## inspectTree(path, [options])
asynchronous: **inspectTreeAsync(path, [options])**

@@ -413,3 +411,3 @@

**returns:**
`null` if given path doesn't exist.
`undefined` if given path doesn't exist.
Otherwise tree of inspect objects like:

@@ -429,5 +427,5 @@ ```javascript

type: 'dir',
size: 0, // the directory is empty
size: 0,
relativePath: './dir',
md5: null, // can't calculate checksum of empty directory
md5: 'd41d8cd98f00b204e9800998ecf8427e',
children: []

@@ -446,3 +444,3 @@ },{

## <a name="list"></a> list([path])
## list([path])
asynchronous: **listAsync(path, [useInspect])**

@@ -456,6 +454,6 @@

**returns:**
Array of file names inside given path, or `null` if given path doesn't exist.
Array of file names inside given path, or `undefined` if given path doesn't exist.
## <a name="move"></a> move(from, to)
## move(from, to)
asynchronous: **moveAsync(from, to)**

@@ -473,3 +471,3 @@

## <a name="path"></a> path(parts...)
## path(parts...)
Returns path resolved to internal CWD of this jetpack object.

@@ -492,6 +490,6 @@

## <a name="read"></a> read(path, [returnAs])
## read(path, [returnAs])
asynchronous: **readAsync(path, [returnAs])**
Reads content of file. If file on given path doesn't exist returns `null` instead of throwing error.
Reads content of file.

@@ -508,6 +506,6 @@ **parameters:**

**returns:**
File content in specified format, or `null` if file doesn't exist.
File content in specified format, or `undefined` if file doesn't exist.
## <a name="remove"></a> remove([path])
## remove([path])
asynchronous: **removeAsync([path])**

@@ -538,10 +536,10 @@

## <a name="symlink"></a> symlink(symlinkValue, path)
asynchronous: **symlinkAsync(symlinkValue, path)**
## rename(path, newName)
asynchronous: **renameAsync(path, newName)**
Creates symbolic link.
Renames given file or directory.
**parameters:**
`symlinkValue` path where symbolic link should point.
`path` path where symbolic link should be put.
`path` path to thing you want to change name.
`newName` new name for this thing (not full path, just a name).

@@ -552,10 +550,10 @@ **returns:**

## <a name="rename"></a> rename(path, newName)
asynchronous: **renameAsync(path, newName)**
## symlink(symlinkValue, path)
asynchronous: **symlinkAsync(symlinkValue, path)**
Renames given file or directory.
Creates symbolic link.
**parameters:**
`path` path to thing you want to change name.
`newName` new name for this thing (not full path, just a name).
`symlinkValue` path where symbolic link should point.
`path` path where symbolic link should be put.

@@ -566,3 +564,3 @@ **returns:**

## <a name="write"></a> write(path, data, [options])
## write(path, data, [options])
asynchronous: **writeAsync(path, data, [options])**

@@ -569,0 +567,0 @@

@@ -132,21 +132,21 @@ /* eslint-env jasmine */

it('if given path is file, deletes it and places dir instead', function (done) {
var preparations = function () {
helper.clearWorkingDir();
fse.outputFileSync('a', 'abc');
it('halts if given path is something other than directory', function (done) {
var expectations = function (err) {
expect(err.message).toContain('exists but is not a directory.');
};
var expectations = function () {
expect('a').toBeDirectory();
};
fse.outputFileSync('a', 'abc');
// SYNC
preparations();
jetpack.dir('a');
expectations();
try {
jetpack.dir('a');
throw new Error('to make sure this code throws');
} catch (err) {
expectations(err);
}
// ASYNC
preparations();
jetpack.dirAsync('a')
.then(function () {
expectations();
.catch(function (err) {
expectations(err);
done();

@@ -153,0 +153,0 @@ });

@@ -199,22 +199,20 @@ /* eslint-env jasmine */

it('if given path is directory, should delete it and place file instead', function (done) {
var preparations = function () {
helper.clearWorkingDir();
// Create nested directories to be sure we can delete non-empty dir.
fse.outputFileSync('a/b/c.txt', 'abc');
it('halts if given path is not a file', function (done) {
var expectations = function (err) {
expect(err.message).toContain('exists but is not a file.');
};
var expectations = function () {
expect('a').toBeFileWithContent('');
};
fse.mkdirsSync('a');
// SYNC
preparations();
jetpack.file('a');
expectations();
try {
jetpack.file('a');
} catch (err) {
expectations(err);
}
// ASYNC
preparations();
jetpack.fileAsync('a')
.then(function () {
expectations();
.catch(function (err) {
expectations(err);
done();

@@ -221,0 +219,0 @@ });

@@ -177,3 +177,3 @@ /* eslint-env jasmine */

expect(err.code).toBe('ENOENT');
expect(err.message).toMatch(/^Path you want to find stuff in doesn't exist/);
expect(err.message).toContain("Path you want to find stuff in doesn't exist");
};

@@ -184,2 +184,3 @@

jetpack.find('a', { matching: '*.txt' });
throw new Error('to make sure this code throws');
} catch (err) {

@@ -222,3 +223,4 @@ expectations(err);

var expectations = function (found) {
expect(found).toEqual(['b/c/d.txt']); // NOT a/b/c/d.txt
var normalizedFound = helper.convertToUnixPathSeparators(found);
expect(normalizedFound).toEqual(['b/c/d.txt']); // NOT a/b/c/d.txt
};

@@ -225,0 +227,0 @@

@@ -86,54 +86,2 @@ /* eslint-env jasmine */

it('can compute checksum of a whole tree', function (done) {
var expectations = function (data) {
// md5 of
// 'a.txt' + '900150983cd24fb0d6963f7d28e17f72' +
// 'b.txt' + '025e4da7edac35ede583f5e8d51aa7ec'
expect(data.md5).toBe('b0ff9df854172efe752cb36b96c8bccd');
// md5 of 'abc'
expect(data.children[0].md5).toBe('900150983cd24fb0d6963f7d28e17f72');
// md5 of 'defg'
expect(data.children[1].md5).toBe('025e4da7edac35ede583f5e8d51aa7ec');
};
fse.outputFileSync('dir/a.txt', 'abc');
fse.outputFileSync('dir/b.txt', 'defg');
// SYNC
expectations(jetpack.inspectTree('dir', { checksum: 'md5' }));
// ASYNC
jetpack.inspectTreeAsync('dir', { checksum: 'md5' })
.then(function (tree) {
expectations(tree);
done();
});
});
it('can deal with empty directories while computing checksum', function (done) {
var expectations = function (data) {
// md5 of
// 'empty_dir' + 'd41d8cd98f00b204e9800998ecf8427e' +
// 'file.txt' + '900150983cd24fb0d6963f7d28e17f72'
expect(data.md5).toBe('4715a354a7871a1db629b379e6267b95');
// md5 of empty directory -> md5 of empty string
expect(data.children[0].md5).toBe('d41d8cd98f00b204e9800998ecf8427e');
// md5 of 'abc'
expect(data.children[1].md5).toBe('900150983cd24fb0d6963f7d28e17f72');
};
fse.mkdirsSync('dir/empty_dir');
fse.outputFileSync('dir/file.txt', 'abc');
// SYNC
expectations(jetpack.inspectTree('dir', { checksum: 'md5' }));
// ASYNC
jetpack.inspectTreeAsync('dir', { checksum: 'md5' })
.then(function (tree) {
expectations(tree);
done();
});
});
it('can output relative path for every tree node', function (done) {

@@ -221,5 +169,5 @@ var expectations = function (data) {

it("returns null if path doesn't exist", function (done) {
it("returns undefined if path doesn't exist", function (done) {
var expectations = function (data) {
expect(data).toBe(null);
expect(data).toBe(undefined);
};

@@ -226,0 +174,0 @@

@@ -56,5 +56,5 @@ /* eslint-env jasmine */

it("returns null if path doesn't exist", function (done) {
it("returns undefined if path doesn't exist", function (done) {
var expectations = function (data) {
expect(data).toBe(null);
expect(data).toBe(undefined);
};

@@ -131,45 +131,2 @@

describe('checksums |', function () {
[
{
name: 'md5',
content: 'abc',
expected: '900150983cd24fb0d6963f7d28e17f72'
},
{
name: 'sha1',
content: 'abc',
expected: 'a9993e364706816aba3e25717850c26c9cd0d89d'
},
{
name: 'sha256',
content: 'abc',
expected: 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
},
{
name: 'md5',
content: '', // just to check if we are counting checksums of empty file correctly
expected: 'd41d8cd98f00b204e9800998ecf8427e'
}
].forEach(function (test) {
it(test.name, function (done) {
var expectations = function (data) {
expect(data[test.name]).toBe(test.expected);
};
fse.outputFileSync('file.txt', test.content);
// SYNC
expectations(jetpack.inspect('file.txt', { checksum: test.name }));
// ASYNC
jetpack.inspectAsync('file.txt', { checksum: test.name })
.then(function (data) {
expectations(data);
done();
});
});
});
});
describe('*nix specific', function () {

@@ -176,0 +133,0 @@ if (process.platform === 'win32') {

@@ -55,5 +55,5 @@ /* eslint-env jasmine */

it("returns null if path doesn't exist", function (done) {
it("returns undefined if path doesn't exist", function (done) {
var expectations = function (data) {
expect(data).toBe(null);
expect(data).toBe(undefined);
};

@@ -72,5 +72,5 @@

it('returns null if given path is a file', function (done) {
var expectations = function (list) {
expect(list).toBe(null);
it('throws if given path is not a directory', function (done) {
var expectations = function (err) {
expect(err.code).toBe('ENOTDIR');
};

@@ -81,8 +81,13 @@

// SYNC
expectations(jetpack.list('file.txt'));
try {
jetpack.list('file.txt');
throw new Error('to make sure this code throws');
} catch (err) {
expectations(err);
}
// ASYNC
jetpack.listAsync('file.txt')
.then(function (list) {
expectations(list);
.catch(function (err) {
expectations(err);
done();

@@ -89,0 +94,0 @@ });

@@ -143,5 +143,5 @@ /* eslint-env jasmine */

it("returns null if file doesn't exist", function (done) {
it("returns undefined if file doesn't exist", function (done) {
var expectations = function (content) {
expect(content).toBe(null);
expect(content).toBe(undefined);
};

@@ -148,0 +148,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet