fs-jetpack
Advanced tools
Comparing version 0.6.2 to 0.6.3
@@ -0,1 +1,5 @@ | ||
0.6.3 (2015-04-18) | ||
------------------- | ||
* Added support for symbolic links. | ||
0.6.2 (2015-04-07) | ||
@@ -2,0 +6,0 @@ ------------------- |
@@ -55,2 +55,5 @@ "use strict"; | ||
fileOps.write(to, data, { mode: mod }); | ||
} else if (inspectData.type === 'symlink') { | ||
var symlinkPointsAt = fs.readlinkSync(inspectData.absolutePath); | ||
fs.symlinkSync(symlinkPointsAt, to); | ||
} | ||
@@ -86,2 +89,4 @@ }; | ||
var promisedReadFile = Q.denodeify(fs.readFile); | ||
var promisedSymlink = Q.denodeify(fs.symlink); | ||
var promisedReadlink = Q.denodeify(fs.readlink); | ||
var promisedMkdirp = Q.denodeify(mkdirp); | ||
@@ -98,2 +103,7 @@ | ||
}); | ||
} else if (inspectData.type === 'symlink') { | ||
return promisedReadlink(inspectData.absolutePath) | ||
.then(function (symlinkPointsAt) { | ||
return promisedSymlink(symlinkPointsAt, to); | ||
}); | ||
} | ||
@@ -100,0 +110,0 @@ }; |
@@ -8,3 +8,3 @@ "use strict"; | ||
var createInspectObj = function (path, options, stat, computedChecksum) { | ||
var createInspectObj = function (path, options, stat) { | ||
var obj = {}; | ||
@@ -19,2 +19,4 @@ | ||
obj.type = 'dir'; | ||
} else if (stat.isSymbolicLink()) { | ||
obj.type = 'symlink'; | ||
} else { | ||
@@ -24,6 +26,2 @@ obj.type = 'other'; | ||
if (computedChecksum) { | ||
obj[computedChecksum.type] = computedChecksum.value; | ||
} | ||
if (options.mode) { | ||
@@ -76,10 +74,7 @@ obj.mode = stat.mode; | ||
var fileChecksum = function (path, stat, algo) { | ||
var fileChecksum = function (path, algo) { | ||
var hash = crypto.createHash(algo); | ||
var data = fs.readFileSync(path); | ||
hash.update(data); | ||
return { | ||
type: algo, | ||
value: hash.digest('hex') | ||
}; | ||
return hash.digest('hex'); | ||
}; | ||
@@ -90,4 +85,9 @@ | ||
var statFlavour = fs.statSync; | ||
if (options.symlinks) { | ||
statFlavour = fs.lstatSync; | ||
} | ||
try { | ||
var stat = fs.statSync(path); | ||
var stat = statFlavour(path); | ||
} catch (err) { | ||
@@ -103,7 +103,11 @@ // Detection if path exists | ||
if (stat.isFile() && options.checksum) { | ||
var computedChecksum = fileChecksum(path, stat, options.checksum); | ||
var inspectObj = createInspectObj(path, options, stat); | ||
if (inspectObj.type === 'file' && options.checksum) { | ||
inspectObj[options.checksum] = fileChecksum(path, options.checksum); | ||
} else if (inspectObj.type === 'symlink') { | ||
inspectObj.pointsAt = fs.readlinkSync(path); | ||
} | ||
return createInspectObj(path, options, stat, computedChecksum); | ||
return inspectObj; | ||
}; | ||
@@ -143,2 +147,3 @@ | ||
options = options || {}; | ||
options.symlinks = true; | ||
@@ -169,3 +174,3 @@ return crawlTreeSync(path, options, null); | ||
// Add together all childrens' size | ||
treeBranch.size += treeSubBranch.size; | ||
treeBranch.size += treeSubBranch.size || 0; | ||
@@ -205,5 +210,7 @@ return treeSubBranch; | ||
var promisedStat = Q.denodeify(fs.stat); | ||
var promisedLstat = Q.denodeify(fs.lstat); | ||
var promisedReaddir = Q.denodeify(fs.readdir); | ||
var promisedReadlink = Q.denodeify(fs.readlink); | ||
var fileChecksumAsync = function (path, stat, algo) { | ||
var fileChecksumAsync = function (path, algo) { | ||
var deferred = Q.defer(); | ||
@@ -217,6 +224,3 @@ | ||
s.on('end', function() { | ||
deferred.resolve({ | ||
type: algo, | ||
value: hash.digest('hex') | ||
}); | ||
deferred.resolve(hash.digest('hex')); | ||
}); | ||
@@ -233,14 +237,26 @@ s.on('error', deferred.reject); | ||
var done = function (stat, computedChecksum) { | ||
deferred.resolve(createInspectObj(path, options, stat, computedChecksum)); | ||
}; | ||
var statFlavour = promisedStat; | ||
if (options.symlinks) { | ||
statFlavour = promisedLstat; | ||
} | ||
promisedStat(path) | ||
statFlavour(path) | ||
.then(function (stat) { | ||
if (stat.isFile() && options.checksum) { | ||
fileChecksumAsync(path, stat, options.checksum).then(function (checksum) { | ||
done(stat, checksum); | ||
}); | ||
var inspectObj = createInspectObj(path, options, stat); | ||
if (inspectObj.type === 'file' && options.checksum) { | ||
fileChecksumAsync(path, options.checksum) | ||
.then(function (checksum) { | ||
inspectObj[options.checksum] = checksum; | ||
deferred.resolve(inspectObj); | ||
}) | ||
.catch(deferred.reject); | ||
} else if (inspectObj.type === 'symlink') { | ||
promisedReadlink(path) | ||
.then(function (linkPath) { | ||
inspectObj.pointsAt = linkPath; | ||
deferred.resolve(inspectObj); | ||
}) | ||
.catch(deferred.reject); | ||
} else { | ||
done(stat, null); | ||
deferred.resolve(inspectObj); | ||
} | ||
@@ -313,2 +329,3 @@ }) | ||
options = options || {}; | ||
options.symlinks = true; | ||
@@ -368,3 +385,3 @@ return crawlTreeAsync(path, options); | ||
children[index] = treeSubBranch; | ||
treeBranch.size += treeSubBranch.size; | ||
treeBranch.size += treeSubBranch.size || 0; | ||
doOne(index + 1); | ||
@@ -371,0 +388,0 @@ }) |
@@ -17,2 +17,3 @@ // The main thing. Here everything starts. | ||
var remove = require('./remove'); | ||
var symlink = require('./symlink'); | ||
var streams = require('./streams'); | ||
@@ -184,2 +185,9 @@ | ||
symlink: function (symlinkValue, path) { | ||
symlink.sync(symlinkValue, resolvePath(path)); | ||
}, | ||
symlinkAsync: function (symlinkValue, path) { | ||
return symlink.async(symlinkValue, resolvePath(path)); | ||
}, | ||
write: function (path, data, options) { | ||
@@ -186,0 +194,0 @@ fileOps.write(resolvePath(path), data, options); |
{ | ||
"name": "fs-jetpack", | ||
"description": "Better file system API", | ||
"version": "0.6.2", | ||
"version": "0.6.3", | ||
"author": "Jakub Szwacz <jakub@szwacz.com>", | ||
@@ -13,10 +13,7 @@ "dependencies": { | ||
"devDependencies": { | ||
"coveralls": "^2.11.2", | ||
"fs-extra": "^0.16.3", | ||
"istanbul": "^0.3.6", | ||
"jasmine": "^2.2.1" | ||
}, | ||
"scripts": { | ||
"test": "node_modules/.bin/jasmine", | ||
"coveralls": "node_modules/.bin/istanbul cover node_modules/.bin/jasmine && node_modules/.bin/coveralls < coverage/lcov.info" | ||
"test": "node_modules/.bin/jasmine" | ||
}, | ||
@@ -23,0 +20,0 @@ "main": "main.js", |
@@ -1,2 +0,2 @@ | ||
fs-jetpack [![Build Status](https://travis-ci.org/szwacz/fs-jetpack.svg?branch=master)](https://travis-ci.org/szwacz/fs-jetpack) [![Coverage Status](https://coveralls.io/repos/szwacz/fs-jetpack/badge.svg)](https://coveralls.io/r/szwacz/fs-jetpack) | ||
fs-jetpack [![Build Status](https://travis-ci.org/szwacz/fs-jetpack.svg?branch=master)](https://travis-ci.org/szwacz/fs-jetpack) | ||
========== | ||
@@ -32,3 +32,3 @@ | ||
// Want to make that call asnychronous? Just add the word "Async" | ||
// Want to make that call asnychronous? Just add the word "Async" | ||
// and it will give you promise instead of ready value. | ||
@@ -151,2 +151,3 @@ jetpack.readAsync('file.txt') | ||
* [rename](#rename) | ||
* [symlink](#symlink) | ||
* [write](#write) | ||
@@ -194,10 +195,10 @@ | ||
// Can copy also specyfic path anhored to CWD | ||
jetpack.copy('my_dir', 'somewhere/my_dir', { | ||
jetpack.copy('my_dir', 'somewhere/my_dir', { | ||
matching: ['my_dir/images/**'] | ||
}); | ||
// When glob pattern starts with './' it means it is anchored to base directory | ||
// you want to copy. Here will be copied only .jpg files from my-dir/images | ||
// When glob pattern starts with './' it means it is anchored to base directory | ||
// you want to copy. Here will be copied only .jpg files from my-dir/images | ||
// and .md files from my-dir/articles | ||
jetpack.copy('my_dir', 'somewhere/my_dir', { | ||
jetpack.copy('my_dir', 'somewhere/my_dir', { | ||
matching: ['./images/**/*.jpg', './articles/**/*.md' ] | ||
@@ -359,2 +360,3 @@ }); | ||
* `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. | ||
@@ -509,2 +511,15 @@ **returns:** | ||
## <a name="symlink"></a> symlink(symlinkValue, path) | ||
asynchronous: **symlinkAsync(symlinkValue, path)** | ||
Creates symbolic link. | ||
**parameters:** | ||
`symlinkValue` path where symbolic link should point. | ||
`path` path where symbolic link should be put. | ||
**returns:** | ||
Nothing. | ||
## <a name="rename"></a> rename(path, newName) | ||
@@ -532,3 +547,3 @@ asynchronous: **renameAsync(path, newName)** | ||
`options` (optional) `Object` with possible fields: | ||
* `atomic` (default `false`) if set to `true` the file will be written using strategy which is much more resistant to data loss. The trick is very simple, [read this to get the concept](http://stackoverflow.com/questions/17047994/transactionally-writing-files-in-node-js). | ||
* `atomic` (default `false`) if set to `true` the file will be written using strategy which is much more resistant to data loss. The trick is very simple, [read this to get the concept](http://stackoverflow.com/questions/17047994/transactionally-writing-files-in-node-js). | ||
* `jsonIndent` (defaults to 2) if writing JSON data this tells how many spaces should one indentation have. | ||
@@ -535,0 +550,0 @@ |
@@ -397,3 +397,3 @@ "use strict"; | ||
describe('*nix specyfic |', function () { | ||
describe('*nix specific |', function () { | ||
@@ -432,4 +432,31 @@ if (process.platform === 'win32') { | ||
it('can copy symlink', function (done) { | ||
var preparations = function () { | ||
helper.clearWorkingDir(); | ||
fse.mkdirsSync('to_copy'); | ||
fse.symlinkSync('some/file', 'to_copy/symlink'); | ||
}; | ||
var expectations = function () { | ||
expect(fse.lstatSync('copied/symlink').isSymbolicLink()).toBe(true); | ||
expect(fse.readlinkSync('copied/symlink')).toBe('some/file'); | ||
}; | ||
// SYNC | ||
preparations(); | ||
var data = jetpack.copy('to_copy', 'copied'); | ||
expectations(); | ||
// ASYNC | ||
preparations(); | ||
jetpack.copyAsync('to_copy', 'copied') | ||
.then(function () { | ||
expectations(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -302,2 +302,48 @@ "use strict"; | ||
describe('*nix specific', function () { | ||
if (process.platform === 'win32') { | ||
return; | ||
} | ||
it('can deal with symlink', function (done) { | ||
var preparations = function () { | ||
fse.outputFileSync('dir/file.txt', 'abc'); | ||
fse.symlinkSync('dir/file.txt', 'dir/symlinked_file.txt'); | ||
} | ||
var expectations = function (data) { | ||
expect(data).toEqual({ | ||
name: 'dir', | ||
type: 'dir', | ||
size: 3, | ||
children: [{ | ||
name: 'file.txt', | ||
type: 'file', | ||
size: 3, | ||
},{ | ||
name: 'symlinked_file.txt', | ||
type: 'symlink', | ||
pointsAt: 'dir/file.txt', | ||
}] | ||
}); | ||
} | ||
preparations(); | ||
// SYNC | ||
var data = jetpack.inspectTree('dir'); | ||
expectations(data); | ||
// ASYNC | ||
jetpack.inspectTreeAsync('dir') | ||
.then(function (data) { | ||
expectations(data); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -86,26 +86,2 @@ "use strict"; | ||
it('can output file mode', function (done) { | ||
var preparations = function () { | ||
fse.outputFileSync('dir/file.txt', 'abc'); | ||
} | ||
var expectations = function (data) { | ||
expect(typeof data.mode).toBe('number'); | ||
} | ||
preparations(); | ||
// SYNC | ||
var data = jetpack.inspect('dir/file.txt', { mode: true }); | ||
expectations(data); | ||
// ASYNC | ||
jetpack.inspectAsync('dir/file.txt', { mode: true }) | ||
.then(function (data) { | ||
expectations(data); | ||
done(); | ||
}); | ||
}); | ||
it('can output file times (ctime, mtime, atime)', function (done) { | ||
@@ -242,2 +218,92 @@ | ||
describe('*nix specific', function () { | ||
if (process.platform === 'win32') { | ||
return; | ||
} | ||
it('can output file mode', function (done) { | ||
var preparations = function () { | ||
fse.outputFileSync('dir/file.txt', 'abc'); | ||
} | ||
var expectations = function (data) { | ||
expect(typeof data.mode).toBe('number'); | ||
} | ||
preparations(); | ||
// SYNC | ||
var data = jetpack.inspect('dir/file.txt', { mode: true }); | ||
expectations(data); | ||
// ASYNC | ||
jetpack.inspectAsync('dir/file.txt', { mode: true }) | ||
.then(function (data) { | ||
expectations(data); | ||
done(); | ||
}); | ||
}); | ||
it('follows symlink by default', function (done) { | ||
var preparations = function () { | ||
fse.outputFileSync('dir/file.txt', 'abc'); | ||
fse.symlinkSync('dir/file.txt', 'symlinked_file.txt'); | ||
} | ||
var expectations = function (data) { | ||
expect(data).toEqual({ | ||
name: 'symlinked_file.txt', | ||
type: 'file', | ||
size: 3, | ||
}); | ||
} | ||
preparations(); | ||
// SYNC | ||
var data = jetpack.inspect('symlinked_file.txt'); | ||
expectations(data); | ||
// ASYNC | ||
jetpack.inspectAsync('symlinked_file.txt') | ||
.then(function (data) { | ||
expectations(data); | ||
done(); | ||
}); | ||
}); | ||
it('stats symlink if option specified', function (done) { | ||
var preparations = function () { | ||
fse.outputFileSync('dir/file.txt', 'abc'); | ||
fse.symlinkSync('dir/file.txt', 'symlinked_file.txt'); | ||
} | ||
var expectations = function (data) { | ||
expect(data).toEqual({ | ||
name: 'symlinked_file.txt', | ||
type: 'symlink', | ||
pointsAt: 'dir/file.txt' | ||
}); | ||
} | ||
preparations(); | ||
// SYNC | ||
var data = jetpack.inspect('symlinked_file.txt', { symlinks: true }); | ||
expectations(data); | ||
// ASYNC | ||
jetpack.inspectAsync('symlinked_file.txt', { symlinks: true }) | ||
.then(function (data) { | ||
expectations(data); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -104,2 +104,40 @@ "use strict"; | ||
describe('*nix specific', function () { | ||
if (process.platform === 'win32') { | ||
return; | ||
} | ||
it('removes only symlinks, never real content where symlinks point', function (done) { | ||
var preparations = function () { | ||
helper.clearWorkingDir(); | ||
fse.outputFileSync('have_to_stay_file', 'abc'); | ||
fse.mkdirsSync('to_remove'); | ||
fse.symlinkSync('../have_to_stay_file', 'to_remove/symlink'); | ||
// Make sure we symlinked it properly. | ||
expect(fse.readFileSync('to_remove/symlink', 'utf8')).toBe('abc'); | ||
}; | ||
var expectations = function () { | ||
expect('have_to_stay_file').toBeFileWithContent('abc'); | ||
expect('to_remove').not.toExist(); | ||
}; | ||
// SYNC | ||
preparations(); | ||
jetpack.remove('to_remove'); | ||
expectations(); | ||
// ASYNC | ||
preparations(); | ||
jetpack.removeAsync('to_remove') | ||
.then(function () { | ||
expectations(); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
191066
2
46
4792
547
28