123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /**
- * archiver-utils
- *
- * Copyright (c) 2012-2014 Chris Talkington, contributors.
- * Licensed under the MIT license.
- * https://github.com/archiverjs/node-archiver/blob/master/LICENSE-MIT
- */
- var fs = require('graceful-fs');
- var path = require('path');
-
- var _ = require('lodash');
- var glob = require('glob');
-
- var file = module.exports = {};
-
- var pathSeparatorRe = /[\/\\]/g;
-
- // Process specified wildcard glob patterns or filenames against a
- // callback, excluding and uniquing files in the result set.
- var processPatterns = function(patterns, fn) {
- // Filepaths to return.
- var result = [];
- // Iterate over flattened patterns array.
- _.flatten(patterns).forEach(function(pattern) {
- // If the first character is ! it should be omitted
- var exclusion = pattern.indexOf('!') === 0;
- // If the pattern is an exclusion, remove the !
- if (exclusion) { pattern = pattern.slice(1); }
- // Find all matching files for this pattern.
- var matches = fn(pattern);
- if (exclusion) {
- // If an exclusion, remove matching files.
- result = _.difference(result, matches);
- } else {
- // Otherwise add matching files.
- result = _.union(result, matches);
- }
- });
- return result;
- };
-
- // True if the file path exists.
- file.exists = function() {
- var filepath = path.join.apply(path, arguments);
- return fs.existsSync(filepath);
- };
-
- // Return an array of all file paths that match the given wildcard patterns.
- file.expand = function() {
- var args = _.toArray(arguments);
- // If the first argument is an options object, save those options to pass
- // into the File.prototype.glob.sync method.
- var options = _.isPlainObject(args[0]) ? args.shift() : {};
- // Use the first argument if it's an Array, otherwise convert the arguments
- // object to an array and use that.
- var patterns = Array.isArray(args[0]) ? args[0] : args;
- // Return empty set if there are no patterns or filepaths.
- if (patterns.length === 0) { return []; }
- // Return all matching filepaths.
- var matches = processPatterns(patterns, function(pattern) {
- // Find all matching files for this pattern.
- return glob.sync(pattern, options);
- });
- // Filter result set?
- if (options.filter) {
- matches = matches.filter(function(filepath) {
- filepath = path.join(options.cwd || '', filepath);
- try {
- if (typeof options.filter === 'function') {
- return options.filter(filepath);
- } else {
- // If the file is of the right type and exists, this should work.
- return fs.statSync(filepath)[options.filter]();
- }
- } catch(e) {
- // Otherwise, it's probably not the right type.
- return false;
- }
- });
- }
- return matches;
- };
-
- // Build a multi task "files" object dynamically.
- file.expandMapping = function(patterns, destBase, options) {
- options = _.defaults({}, options, {
- rename: function(destBase, destPath) {
- return path.join(destBase || '', destPath);
- }
- });
- var files = [];
- var fileByDest = {};
- // Find all files matching pattern, using passed-in options.
- file.expand(options, patterns).forEach(function(src) {
- var destPath = src;
- // Flatten?
- if (options.flatten) {
- destPath = path.basename(destPath);
- }
- // Change the extension?
- if (options.ext) {
- destPath = destPath.replace(/(\.[^\/]*)?$/, options.ext);
- }
- // Generate destination filename.
- var dest = options.rename(destBase, destPath, options);
- // Prepend cwd to src path if necessary.
- if (options.cwd) { src = path.join(options.cwd, 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;
- };
-
- // reusing bits of grunt's multi-task source normalization
- file.normalizeFilesArray = function(data) {
- var files = [];
-
- data.forEach(function(obj) {
- var prop;
- if ('src' in obj || 'dest' in obj) {
- files.push(obj);
- }
- });
-
- if (files.length === 0) {
- return [];
- }
-
- files = _(files).chain().forEach(function(obj) {
- if (!('src' in obj) || !obj.src) { return; }
- // Normalize .src properties to flattened array.
- if (Array.isArray(obj.src)) {
- obj.src = _.flatten(obj.src);
- } else {
- obj.src = [obj.src];
- }
- }).map(function(obj) {
- // Build options object, removing unwanted properties.
- var expandOptions = _.extend({}, obj);
- delete expandOptions.src;
- delete expandOptions.dest;
-
- // Expand file mappings.
- if (obj.expand) {
- return file.expandMapping(obj.src, obj.dest, expandOptions).map(function(mapObj) {
- // Copy obj properties to result.
- var result = _.extend({}, obj);
- // Make a clone of the orig obj available.
- result.orig = _.extend({}, obj);
- // Set .src and .dest, processing both as templates.
- result.src = mapObj.src;
- result.dest = mapObj.dest;
- // Remove unwanted properties.
- ['expand', 'cwd', 'flatten', 'rename', 'ext'].forEach(function(prop) {
- delete result[prop];
- });
- return result;
- });
- }
-
- // Copy obj properties to result, adding an .orig property.
- var result = _.extend({}, obj);
- // Make a clone of the orig obj available.
- result.orig = _.extend({}, obj);
-
- if ('src' in result) {
- // Expose an expand-on-demand getter method as .src.
- Object.defineProperty(result, 'src', {
- enumerable: true,
- get: function fn() {
- var src;
- if (!('result' in fn)) {
- src = obj.src;
- // If src is an array, flatten it. Otherwise, make it into an array.
- src = Array.isArray(src) ? _.flatten(src) : [src];
- // Expand src files, memoizing result.
- fn.result = file.expand(expandOptions, src);
- }
- return fn.result;
- }
- });
- }
-
- if ('dest' in result) {
- result.dest = obj.dest;
- }
-
- return result;
- }).flatten().value();
-
- return files;
- };
|