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.
		
		
		
		
		
			
		
			
				
					210 lines
				
				6.7 KiB
			
		
		
			
		
	
	
					210 lines
				
				6.7 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * 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 flatten = require('lodash.flatten');
							 | 
						||
| 
								 | 
							
								var difference = require('lodash.difference');
							 | 
						||
| 
								 | 
							
								var union = require('lodash.union');
							 | 
						||
| 
								 | 
							
								var isPlainObject = require('lodash.isplainobject');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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(...args) {
							 | 
						||
| 
								 | 
							
								  // 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 = Object.assign({
							 | 
						||
| 
								 | 
							
								    rename: function(destBase, destPath) {
							 | 
						||
| 
								 | 
							
								      return path.join(destBase || '', destPath);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }, options);
							 | 
						||
| 
								 | 
							
								  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 = Object.assign({}, 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 = Object.assign({}, obj);
							 | 
						||
| 
								 | 
							
								        // Make a clone of the orig obj available.
							 | 
						||
| 
								 | 
							
								        result.orig = Object.assign({}, 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 = Object.assign({}, obj);
							 | 
						||
| 
								 | 
							
								    // Make a clone of the orig obj available.
							 | 
						||
| 
								 | 
							
								    result.orig = Object.assign({}, 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;
							 | 
						||
| 
								 | 
							
								};
							 |