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
			| 
											2 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; | ||
|  | }; |