Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

powerwalk

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

powerwalk - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

benchmark/benchmark-powerwalk-pipe.js

311

index.js

@@ -0,93 +1,282 @@

const debug = require('debug')('powerwalk')
const path = require('path')
const Transform = require('readable-stream/transform')
const eos = require('end-of-stream')
const inherits = require('inherits')
const prr = require('prr')
const objectType = require('./object-type')
const extend = require('xtend')
const errno = require('errno')
const format = require('util').format
const defaults = {
symlinks: false,
highWaterMark: 16,
emit: 'file',
fs: require('graceful-fs')
}
var through2 = require('through2')
, glob = require('glob')
, fs = require('graceful-fs')
, stat = fs.stat
, path = require('path')
module.exports = walk
module.exports.Powerwalk = Powerwalk
module.exports = function(dirname){
var stream = through2(write, flush)
, options = { cwd: dirname
, strict: true
, nosort: true
}
, queue = []
fs.exists(dirname, function(exists){
if (! exists) {
return stream.emit('error', new Error(dirname + ' does not exist'))
function walk(dirname, options, callback) {
var length = arguments.length
for (var i = 0; i < length; i++) {
switch (typeof arguments[i]) {
case 'string':
dirname = arguments[i]
break;
case 'object':
options = arguments[i]
break;
case 'function':
callback = arguments[i]
break;
}
}
// NOTE: this used to intentionally wait until the glob end event, there is some
// clean up that happens there which prevents things like double entries etc.
// see glob option nounique if this becomes an issue again.
glob('**', options)
.on('error', function(err){ stream.emit('error', err) })
.on('match', onmatch)
})
debug('starting walk at %s', dirname)
// For non pipe/stream consumption, end will not emit without a consumer
stream.on('data', function(chunk) {
stream.emit('file', chunk.toString())
})
var stream = new Powerwalk(options)
if (callback) {
var results = []
stream.on('data', push(results))
eos(stream, function endofstream(err) {
if (err) return callback(err)
else return callback(err, results)
})
}
// maybe do an fs.exisits to provide a non-mysterious error here.
if (dirname) {
// TODO: move this resolution into the _transform method
dirname = path.resolve(dirname || '')
stream.write(dirname)
}
return stream
}
function onmatch(match) {
// don't stat empty strings
if (match.length === 0) return
function Powerwalk(options) {
if (! (this instanceof Powerwalk)) {
return new Powerwalk(options)
}
var pathname = path.resolve(options.cwd, match)
options = extend(defaults, options)
stream.write(pathname)
if (!(options.ignore instanceof Array)) {
options.ignore = [ options.ignore ]
}
function write(chunk, enc, callback) {
var pathname = chunk.toString()
// TODO: gaurd against invalid object types so options.emit: 'garabage'
// doesn't cause problems
// TODO: assert options.depth is a number
queue.push(pathname)
debug('initializing: %o', options)
stat(pathname, function(err, stats) {
dequeue(pathname)
var powerwalk = this
if (err) return callback(err)
if (! stats.isFile()) return callback()
Transform.call(powerwalk, options)
var file = {
filename: pathname,
stats: stats
}
prr(powerwalk, 'options', options)
prr(powerwalk, 'depth', 0, { writable: true })
prr(powerwalk, '_q', [])
prr(powerwalk, '_walked', [])
if (wants('stat')) stream.emit('stat', file)
powerwalk.on('path', push(powerwalk._walked))
}
if (wants('read')) read(file, callback)
else callback(null, pathname)
inherits(Powerwalk, Transform)
if (queue.length === 0) stream.end()
})
}
Powerwalk.prototype._transform = function (buffer, enc, callback) {
debug('transform %s', buffer)
function flush(callback) {
var powerwalk = this
var options = powerwalk.options
var pathname = buffer.toString()
var fs = powerwalk.options.fs
if (contains(powerwalk.options.ignore, pathname)) {
debug('ignoring: %s', pathname)
callback()
return
}
function wants(event){
return stream.listeners(event).length > 0
// // before anything setup things on first write
// // * path resolver
// if (! powerwalk._started) {
// powerwalk._started = true
// }
// // end first write setup
powerwalk.queue(pathname)
fs.lstat(pathname, function(err, stats) {
if (err) {
return callback(error(err, 'lstat', pathname))
}
powerwalk.emit('stat', pathname, stats)
var type = objectType(stats)
switch (type) {
case 'file':
powerwalk.dequeue(pathname, type, callback)
break
case 'directory':
powerwalk.depth++
debug('depth: %s', powerwalk.depth)
// stop recursing if depth has been reached...
if (powerwalk.options.depth && powerwalk.options.depth === powerwalk.depth) {
powerwalk.dequeue(pathname, type, callback)
break
}
fs.readdir(pathname, function ondir(err, results) {
if (err) return callback(err)
var length = results.length
for (var i = 0; i < length; i++) {
var resolved = path.resolve(pathname, results[i])
powerwalk.write(resolved)
}
powerwalk.dequeue(pathname, type, callback)
})
break
case 'symlink':
// On a symlink there are two properties:
// * The linkname
// * the actual path of the link
//
// For instance one/two-symlink is actually ../two
//
// This should be kept track of for each symlink to possilby prevent recurrion
// loops.
//
// Or keep track of emitted paths and DRY
var walked = powerwalk.walked(pathname)
var shouldSkip = ! options.symlinks || walked
debug('shouldSkip: %s', shouldSkip)
if (shouldSkip) {
debug('skipping link: %s', pathname)
powerwalk.dequeue(pathname, type, callback)
break
}
fs.readlink(pathname, function onlinl(err, link) {
if (err) {
return callback(error(err, 'readlink', pathname))
}
var dirname = path.dirname(pathname)
var resolved = path.resolve(dirname, link)
debug('symlink %s', pathname)
debug('symlink resolved: %s', resolved)
powerwalk.write(resolved)
powerwalk.dequeue(pathname, type, callback)
})
break
default:
powerwalk.dequeue(pathname, type, callback)
break
}
})
}
// NOTE: this is to keep track of walked symlinks, instead of tracking every
// path it would be better to only treat symlinks in this way.
Powerwalk.prototype.walked = function(pathname) {
return contains(this._walked, pathname)
}
Powerwalk.prototype.queue = function(pathname) {
this._q.push(pathname)
}
Powerwalk.prototype.dequeue = function(pathname, type, callback) {
var powerwalk = this
var start = powerwalk._q.indexOf(pathname)
var deleteCount = 1
var removed = powerwalk._q.splice(start, deleteCount)[0]
if (! removed) {
var err = new Error('Can not dequeue items that have not been queued.')
powerwalk.emit('error', err)
return
}
function dequeue(pathname) {
queue.splice(queue.indexOf(pathname), 1)
if (! powerwalk.walked(pathname)) {
powerwalk.emit('path', pathname)
powerwalk.emit(type, pathname)
}
function read(file, callback){
fs.readFile(file.filename, 'utf8', function(err, data){
if (err) return callback(err)
if (type === powerwalk.options.emit) {
debug('%s: %s', type, pathname)
callback(null, pathname)
} else {
callback()
}
file.data = data
if (powerwalk._q.length === 0) {
powerwalk.end()
}
stream.emit('read', file)
return removed
}
callback(null, file.filename)
})
Powerwalk.prototype._flush = function(callback) {
debug('_flush')
var powerwalk = this
// Experimental: This might be a bad idea since data events are queued and the
// read stream might not be hooked up til later.
// if (powerwalk.listeners('data').length === 0) {
// powerwalk.on('data', noop)
// }
callback()
}
function contains(array, item) {
return array.indexOf(item) !== -1
}
function push(array) {
return callback
function callback(buffer) {
array.push(buffer.toString())
}
}
function noop(){}
function error(err, method, pathname) {
var code = err.code || -1
var description = ''
if (errno.code[code]) {
description = errno.code[code].description
} else {
description = 'unknown error'
}
var message = format('%s "%s" failed: %s', method, pathname, description)
err.message = message
err.pathname = pathname
return err
}

18

package.json
{
"name": "powerwalk",
"version": "1.0.0",
"version": "2.0.0",
"description": "Recursively walks a directory and emits filenames. Supports additional stat and read events (if you want them).",

@@ -21,11 +21,19 @@ "main": "index.js",

],
"author": "Jason Campbell <jason@js.la> (http://artifact.sh)",
"author": "Jason Campbell <jasoncampbell@google.com> (http://artifact.sh)",
"license": "MIT",
"dependencies": {
"glob": "^4.0.5",
"debug": "^2.2.0",
"end-of-stream": "^1.1.0",
"errno": "^0.1.2",
"graceful-fs": "^3.0.2",
"through2": "^0.6.1"
"inherits": "^2.0.1",
"prr": "^1.0.1",
"readable-stream": "^2.0.0",
"xtend": "^4.0.0"
},
"devDependencies": {
"prova": "^1.14.0"
"coveralls": "^2.11.2",
"istanbul": "^0.3.17",
"tape": "^4.0.0",
"through2": "^0.6.5"
},

@@ -32,0 +40,0 @@ "bugs": {

@@ -1,27 +0,22 @@

var powerwalk = require('../')
var test = require('prova')
var path = require('path')
var fixtures = path.resolve(__dirname, './fixtures')
var through2 = require('through2')
var fs = require('graceful-fs')
var test = require('tape')
var EventEmitter = require('events').EventEmitter
var Stream = require('stream').Stream
var helpers = require('./helpers')
test('powerwalk(source).pipe(stream)', function(assert) {
var stream = through2(write)
test('var stream = powerwalk(options)', function(t) {
t.ok(powerwalk() instanceof EventEmitter, 'should be an event emitter')
t.ok(powerwalk() instanceof Stream, 'should be a stream')
t.end()
})
assert.plan(8)
test('powerwalk(dirname, callback)', function(t) {
var dirname = helpers.resolve('dreams')
var expected = helpers.expected('dreams')
powerwalk(fixtures)
.pipe(stream)
function write(chunk, enc, callback){
var filename = chunk.toString()
fs.exists(filename, function(exists) {
assert.ok(exists, 'filename should exist')
assert.ok(filename.match(/fixtures\/(.*)\.md$/), 'should be a fixture')
})
callback()
}
powerwalk(dirname, function(err, results) {
t.error(err)
t.same(results.sort(), expected('files'), 'should callback with files')
t.end()
})
})

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc