You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

172 lines
5.5 KiB

/*
* globule
* https://github.com/cowboy/node-globule
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
*/
'use strict';
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var glob = require('glob');
var minimatch = require('minimatch');
// The module.
var globule = exports;
// Process specified wildcard glob patterns or filenames against a
// callback, excluding and uniquing files in the result set.
function processPatterns(patterns, fn) {
return _.flatten(patterns).reduce(function(result, pattern) {
if (pattern.indexOf('!') === 0) {
// If the first character is ! all matches via this pattern should be
// removed from the result set.
pattern = pattern.slice(1);
return _.difference(result, fn(pattern));
} else {
// Otherwise, add all matching filepaths to the result set.
return _.union(result, fn(pattern));
}
}, []);
}
// Match a filepath or filepaths against one or more wildcard patterns. Returns
// all matching filepaths. This behaves just like minimatch.match, but supports
// any number of patterns.
globule.match = function(patterns, filepaths, options) {
// Return empty set if either patterns or filepaths was omitted.
if (patterns == null || filepaths == null) { return []; }
// Normalize patterns and filepaths to arrays.
if (!_.isArray(patterns)) { patterns = [patterns]; }
if (!_.isArray(filepaths)) { filepaths = [filepaths]; }
// Return empty set if there are no patterns or filepaths.
if (patterns.length === 0 || filepaths.length === 0) { return []; }
// Return all matching filepaths.
return processPatterns(patterns, function(pattern) {
return minimatch.match(filepaths, pattern, options || {});
});
};
// Match a filepath or filepaths against one or more wildcard patterns. Returns
// true if any of the patterns match.
globule.isMatch = function() {
return globule.match.apply(null, arguments).length > 0;
};
// Return an array of all file paths that match the given wildcard patterns.
globule.find = function() {
var args = _.toArray(arguments);
// If the last argument is an options object, remove it from args.
var options = _.isPlainObject(args[args.length - 1]) ? args.pop() : {};
// Use the first argument if it's an Array, otherwise use all arguments.
var patterns = _.isArray(args[0]) ? args[0] : args;
// Return empty set if there are no patterns or filepaths.
if (patterns.length === 0) { return []; }
var srcBase = options.srcBase || options.cwd;
// Create glob-specific options object.
var globOptions = _.extend({}, options);
if (srcBase) {
globOptions.cwd = srcBase;
}
// Get all matching filepaths.
var matches = processPatterns(patterns, function(pattern) {
return glob.sync(pattern, globOptions);
});
// If srcBase and prefixBase were specified, prefix srcBase to matched paths.
if (srcBase && options.prefixBase) {
matches = matches.map(function(filepath) {
return path.join(srcBase, filepath);
});
}
// Filter result set?
if (options.filter) {
matches = matches.filter(function(filepath) {
// If srcBase was specified but prefixBase was NOT, prefix srcBase
// temporarily, for filtering.
if (srcBase && !options.prefixBase) {
filepath = path.join(srcBase, filepath);
}
try {
if (_.isFunction(options.filter)) {
return options.filter(filepath, options);
} else {
// If the file is of the right type and exists, this should work.
return fs.statSync(filepath)[options.filter]();
}
} catch(err) {
// Otherwise, it's probably not the right type.
return false;
}
});
}
return matches;
};
var pathSeparatorRe = /[\/\\]/g;
var extDotRe = {
first: /(\.[^\/]*)?$/,
last: /(\.[^\/\.]*)?$/,
};
function rename(dest, options) {
// Flatten path?
if (options.flatten) {
dest = path.basename(dest);
}
// Change the extension?
if (options.ext) {
dest = dest.replace(extDotRe[options.extDot], options.ext);
}
// Join dest and destBase?
if (options.destBase) {
dest = path.join(options.destBase, dest);
}
return dest;
}
// Build a mapping of src-dest filepaths from the given set of filepaths.
globule.mapping = function(filepaths, options) {
// Return empty set if filepaths was omitted.
if (filepaths == null) { return []; }
options = _.defaults({}, options, {
extDot: 'first',
rename: rename,
});
var files = [];
var fileByDest = {};
// Find all files matching pattern, using passed-in options.
filepaths.forEach(function(src) {
// Generate destination filename.
var dest = options.rename(src, options);
// Prepend srcBase to all src paths.
if (options.srcBase) {
src = path.join(options.srcBase, src);
}
// Normalize filepaths to be unix-style.
dest = dest.replace(pathSeparatorRe, '/');
src = src.replace(pathSeparatorRe, '/');
// Map correct src path to dest path.
if (fileByDest[dest]) {
// If dest already exists, push this src onto that dest's src array.
fileByDest[dest].src.push(src);
} else {
// Otherwise create a new src-dest file mapping object.
files.push({
src: [src],
dest: dest,
});
// And store a reference for later use.
fileByDest[dest] = files[files.length - 1];
}
});
return files;
};
// Return a mapping of src-dest filepaths from files matching the given
// wildcard patterns.
globule.findMapping = function(patterns, options) {
return globule.mapping(globule.find(patterns, options), options);
};