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

broccoli-funnel

Package Overview
Dependencies
Maintainers
2
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

broccoli-funnel - npm Package Compare versions

Comparing version 0.2.10 to 0.2.11

147

index.js
'use strict';
var fs = require('fs');
var path = require('path');
var path = require('path-posix');
var mkdirp = require('mkdirp');

@@ -12,2 +12,4 @@ var walkSync = require('walk-sync');

var debug = require('debug');
var FSTree = require('fs-tree-diff');
var rimraf = require('rimraf');

@@ -44,4 +46,7 @@ function makeDictionary() {

this._persistentOutput = true;
this._includeFileCache = makeDictionary();
this._destinationPathCache = makeDictionary();
this._currentTree = new FSTree();

@@ -55,2 +60,3 @@ var keys = Object.keys(options || {});

this.destDir = this.destDir || '/';
this.count = 0;

@@ -158,3 +164,3 @@ if (this.files && typeof this.files === 'function') {

if (fs.existsSync(inputPath)) {
fs.rmdirSync(this.outputPath);
rimraf.sync(this.outputPath);
this._copy(inputPath, this.destPath);

@@ -176,35 +182,80 @@ } else if (this.allowEmpty) {

function ensureRelative(string) {
if (string.charAt(0) === '/') {
return string.substring(1);
}
return string;
}
Funnel.prototype._processEntries = function(entries) {
return entries.filter(function(entry) {
// support the second set of filters walk-sync does not support
// * regexp
// * excludes
return this.includeFile(entry.relativePath);
}, this).map(function(entry) {
var relativePath = entry.relativePath;
// the destination paths "absolute" is actually stlil relative to the FSTree
entry.relativePath = ensureRelative(this.lookupDestinationPath(ensureRelative(path.join(this.destDir, relativePath))));
this.outputToInputMappings[entry.relativePath] = relativePath;
return entry;
}, this);
};
Funnel.prototype._processPaths = function(paths, outputToInputMappings) {
return paths.
slice(0).
filter(this.includeFile, this).
map(function(relativePath) {
var output = ensureRelative(this.lookupDestinationPath(ensureRelative(path.join(this.destDir, relativePath))));
this.outputToInputMappings[output] = relativePath;
return output;
}, this);
};
Funnel.prototype.processFilters = function(inputPath) {
var files;
var nextTree;
this.outputToInputMappings = {}; // we allow users to rename files
if (this.files && !this.exclude && !this.include) {
files = this.files.slice(0); //clone to be compatible with walkSync
// clone to be compatible with walkSync
nextTree = FSTree.fromPaths(this._processPaths(this.files));
} else {
var entries;
if (this._matchedWalk) {
files = walkSync(inputPath, this.include);
entries = walkSync.entries(inputPath, undefined, this.include);
} else {
files = walkSync(inputPath);
entries = walkSync.entries(inputPath);
}
nextTree = new FSTree({
entries: this._processEntries(entries)
});
}
var relativePath, destRelativePath, fullInputPath, fullOutputPath;
var patch = this._currentTree.calculatePatch(nextTree);
var count = 0;
for (var i = 0, l = files.length; i < l; i++) {
relativePath = files[i];
this._currentTree = nextTree;
if (this.includeFile(relativePath)) {
count++;
fullInputPath = path.join(inputPath, relativePath);
destRelativePath = this.lookupDestinationPath(relativePath);
fullOutputPath = path.join(this.destPath, destRelativePath);
this._debug('patch: %o', patch);
this.processFile(fullInputPath, fullOutputPath, relativePath);
}
}
var outputPath = this.outputPath;
patch.forEach(function(entry) {
this._applyPatch(entry, inputPath, outputPath);
}, this);
var count = nextTree.size;
this._debug('processFilters %o', {
in: new Date() - this._buildStart + 'ms',
filesFound: files.length,
filesFound: this._currentTree.size,
filesProcessed: count,
operations: patch.length,
inputPath: inputPath,

@@ -215,2 +266,41 @@ destPath: this.destPath

Funnel.prototype._applyPatch = function applyPatch(entry, inputPath, _outputPath) {
var outputToInput = this.outputToInputMappings;
var operation = entry[0];
var outputRelative = entry[1];
if (!outputRelative) {
// broccoli itself maintains the roots, we can skip any operation on them
return;
}
var outputPath = _outputPath + '/' + outputRelative;
this._debug('%s %s', operation, outputPath);
if (operation === 'change') {
operation = 'create';
}
switch (operation) {
case 'unlink' :
fs.unlinkSync(outputPath);
break;
case 'rmdir' :
fs.rmdirSync(outputPath);
break;
case 'mkdir' :
fs.mkdirSync(outputPath);
break;
case 'create'/* also change */ :
var relativePath = outputToInput[outputRelative];
if (relativePath === undefined) {
relativePath = outputToInput['/' + outputRelative];
}
this.processFile(inputPath + '/' + relativePath, outputPath, relativePath);
break;
default: throw new Error('Unknown operation: ' + operation);
}
};
Funnel.prototype.lookupDestinationPath = function(relativePath) {

@@ -296,10 +386,19 @@ if (this._destinationPathCache[relativePath] !== undefined) {

Funnel.prototype._copy = function(sourcePath, destPath) {
var destDir = path.dirname(destPath);
if (!fs.existsSync(destDir)) {
mkdirp.sync(destDir);
var destDir = path.dirname(destPath);
try {
symlinkOrCopy.sync(sourcePath, destPath);
} catch(e) {
if (!fs.existsSync(destDir)) {
mkdirp.sync(destDir);
}
try {
fs.unlinkSync(destPath);
} catch(e) {
}
symlinkOrCopy.sync(sourcePath, destPath);
}
symlinkOrCopy.sync(sourcePath, destPath);
};
module.exports = Funnel;

13

package.json
{
"name": "broccoli-funnel",
"version": "0.2.10",
"version": "0.2.11",
"description": "Broccoli plugin that allows you to filter files selected from an input node down based on regular expressions.",

@@ -24,4 +24,8 @@ "main": "index.js",

"debug": "^2.2.0",
"fast-ordered-set": "^1.0.0",
"fs-tree-diff": "0.3.0",
"minimatch": "^2.0.1",
"mkdirp": "^0.5.0",
"path-posix": "^1.0.0",
"rimraf": "^2.4.3",
"symlink-or-copy": "^1.0.0",

@@ -32,8 +36,9 @@ "walk-sync": "^0.2.5"

"broccoli": "^0.15.0",
"rimraf": "^2.3.2",
"rsvp": "^3.0.14",
"chai": "^3.2.0",
"expect.js": "^0.3.1",
"mocha": "~1.18.2",
"mocha-jshint": "0.0.9"
"mocha-jshint": "0.0.9",
"rimraf": "^2.3.2",
"rsvp": "^3.0.14"
}
}

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

describe('broccoli-funnel', function(){
var fixturePath = path.join(__dirname, 'fixtures');
var fixturePath = __dirname + '/fixtures';
var builder;

@@ -26,5 +26,32 @@

describe('rebuilding', function() {
it('correctly rebuilds', function() {
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {
include: ['**/*.js']
});
builder = new broccoli.Builder(node);
return builder.build()
.then(function(results) {
var outputPath = results.directory;
expect(walkSync(outputPath, ['**/*.js'])).to.eql(walkSync(inputPath, ['**/*.js']));
var mutatedFile = inputPath + '/' + 'subdir1/subsubdir2/some.js';
fs.writeFileSync(mutatedFile, fs.readFileSync(mutatedFile));
return builder.build();
})
.then(function(results) {
var outputPath = results.directory;
expect(walkSync(outputPath, ['**/*.js'])).to.eql(walkSync(inputPath, ['**/*.js']));
});
});
});
describe('processFile', function() {
it('is not called when simply linking roots (aka no include/exclude)', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -48,3 +75,3 @@ processFile: function() {

var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -57,3 +84,8 @@ include: [ /.png$/, /.js$/ ],

var relDestPath = destPath.replace(this.outputPath, '__output_path__');
processFileArguments.push([relSourcePath, relDestPath, relativePath]);
processFileArguments.push([
relSourcePath,
relDestPath,
relativePath
]);
}

@@ -65,9 +97,12 @@ });

.then(function(results) {
var expected = [
[ path.join('__input_path__', 'subdir1/subsubdir1/foo.png'),
path.join('__output_path__', 'foo/subdir1/subsubdir1/foo.png'),
'subdir1/subsubdir1/foo.png' ],
[ path.join('__input_path__', 'subdir1/subsubdir2/some.js'),
path.join('__output_path__', 'foo/subdir1/subsubdir2/some.js'),
'subdir1/subsubdir2/some.js' ]
[ '__input_path__/subdir1/subsubdir1/foo.png',
'__output_path__/foo/subdir1/subsubdir1/foo.png',
'subdir1/subsubdir1/foo.png'
],
[ '__input_path__/subdir1/subsubdir2/some.js',
'__output_path__/foo/subdir1/subsubdir2/some.js',
'subdir1/subsubdir2/some.js'
]
];

@@ -80,3 +115,4 @@

it('is responsible for generating files in the destDir', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -96,3 +132,9 @@ include: [ /.png$/, /.js$/ ],

expect(walkSync(outputPath)).to.eql([]);
expect(walkSync(outputPath)).to.eql([
// only folders exist
'foo/',
'foo/subdir1/',
'foo/subdir1/subsubdir1/',
'foo/subdir1/subsubdir2/'
]);
});

@@ -102,3 +144,3 @@ });

it('works with mixed glob and RegExp includes', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -118,3 +160,9 @@ include: [ '**/*.png', /.js$/ ],

expect(walkSync(outputPath)).to.eql([]);
expect(walkSync(outputPath)).to.eql([
// only dir exist
'foo/',
'foo/subdir1/',
'foo/subdir1/subsubdir1/',
'foo/subdir1/subsubdir2/'
]);
});

@@ -125,3 +173,3 @@ });

it('correctly chooses _matchedWalk scenario', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node;

@@ -140,3 +188,3 @@ node = new Funnel(inputPath, { include: [ '**/*.png', /.js$/ ] });

it('linking roots without srcDir/destDir, can rebuild without error', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath);

@@ -161,3 +209,3 @@

it('simply returns a copy of the input node', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath);

@@ -175,3 +223,3 @@

it('simply returns a copy of the input node at a nested destination', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -184,3 +232,3 @@ destDir: 'some-random'

.then(function(results) {
var outputPath = path.join(results.directory, 'some-random');
var outputPath = results.directory + '/some-random';

@@ -193,3 +241,3 @@ expect(walkSync(outputPath)).to.eql(walkSync(inputPath));

.then(function(results) {
var outputPath = path.join(results.directory, 'some-random');
var outputPath = results.directory + '/some-random';

@@ -201,3 +249,3 @@ expect(walkSync(outputPath)).to.eql(walkSync(inputPath));

it('can properly handle the output path being a broken symlink', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -219,3 +267,3 @@ srcDir: 'subdir1'

.then(function(results) {
var restrictedInputPath = path.join(inputPath, 'subdir1');
var restrictedInputPath = inputPath + '/subdir1';
var outputPath = results.directory;

@@ -228,3 +276,3 @@

it('simply returns a copy of the input node at a nested source', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -237,3 +285,3 @@ srcDir: 'subdir1'

.then(function(results) {
var restrictedInputPath = path.join(inputPath, 'subdir1');
var restrictedInputPath = inputPath + '/subdir1';
var outputPath = results.directory;

@@ -247,3 +295,3 @@

.then(function(results) {
var restrictedInputPath = path.join(inputPath, 'subdir1');
var restrictedInputPath = inputPath + '/subdir1';
var outputPath = results.directory;

@@ -256,3 +304,3 @@

it('matches *.css', function() {
var inputPath = path.join(fixturePath, 'dir1/subdir2');
var inputPath = fixturePath + '/dir1/subdir2';
var node = new Funnel(inputPath, {

@@ -266,3 +314,6 @@ include: ['*.css']

var outputPath = results.directory;
expect(walkSync(outputPath)).to.eql(['bar.css']);
expect(walkSync(outputPath)).to.eql([
'bar.css'
]);
});

@@ -272,3 +323,3 @@ });

it('matches the deprecated: files *.css', function() {
var inputPath = path.join(fixturePath, 'dir1/subdir2');
var inputPath = fixturePath + '/dir1/subdir2';
var oldWarn = console.warn;

@@ -303,3 +354,3 @@ var message;

it('does not error with input node at a missing nested source', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -332,3 +383,3 @@ srcDir: 'subdir3',

function testFiltering(includes, excludes, files, expected) {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -363,3 +414,3 @@ include: includes,

it('can take a list of files', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -392,3 +443,3 @@ files: [

it('so error if `files` and `include` are set', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';

@@ -404,3 +455,3 @@ expect(function() {

it('so error if `files` and `exclude` are set', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';

@@ -418,5 +469,5 @@ expect(function() {

it('can take files as a function', function() {
var inputPath = path.join(fixturePath, 'dir1');
var filesCounter = 0;
var inputPath = fixturePath + '/dir1';
var filesByCounter = [
// rebuild 1:
[

@@ -426,4 +477,10 @@ 'subdir1/subsubdir1/foo.png',

],
// rebuild 2:
[ 'subdir1/subsubdir1/foo.png' ],
// rebuild 3:
[],
// rebuild 4:
['subdir1/subsubdir2/some.js']

@@ -434,3 +491,3 @@ ];

files: function() {
return filesByCounter[filesCounter++];
return filesByCounter.shift();
}

@@ -496,3 +553,3 @@ });

it('can take files as a function with exclude (includeCache needs to be cleared)', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var filesCounter = 0;

@@ -631,3 +688,3 @@ var filesByCounter = [

it('combined filtering', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -652,3 +709,3 @@ exclude: [ /.png$/, /.js$/ ],

it('creates its output directory even if no files are matched', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath, {

@@ -670,7 +727,7 @@ exclude: [ /.*/ ]

it('uses custom getDestinationPath function if provided', function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';
var node = new Funnel(inputPath);
node.getDestinationPath = function(relativePath) {
return path.join('foo', relativePath);
return 'foo/' + relativePath;
};

@@ -683,3 +740,3 @@

expect(walkSync(path.join(outputPath, 'foo'))).to.eql(walkSync(inputPath));
expect(walkSync(outputPath + '/foo')).to.eql(walkSync(inputPath));
});

@@ -693,3 +750,3 @@ });

beforeEach(function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';

@@ -739,3 +796,3 @@ node = new Funnel(inputPath);

beforeEach(function() {
var inputPath = path.join(fixturePath, 'dir1');
var inputPath = fixturePath + '/dir1';

@@ -742,0 +799,0 @@ node = new Funnel(inputPath);

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