mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			210 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			210 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * 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;
 | |
| };
 |