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.
		
		
		
		
		
			
		
			
				
					
					
						
							148 lines
						
					
					
						
							3.7 KiB
						
					
					
				
			
		
		
	
	
							148 lines
						
					
					
						
							3.7 KiB
						
					
					
				'use strict'; | 
						|
const fs = require('fs'); | 
						|
const arrayUnion = require('array-union'); | 
						|
const glob = require('glob'); | 
						|
const fastGlob = require('fast-glob'); | 
						|
const dirGlob = require('dir-glob'); | 
						|
const gitignore = require('./gitignore'); | 
						|
 | 
						|
const DEFAULT_FILTER = () => false; | 
						|
 | 
						|
const isNegative = pattern => pattern[0] === '!'; | 
						|
 | 
						|
const assertPatternsInput = patterns => { | 
						|
	if (!patterns.every(x => typeof x === 'string')) { | 
						|
		throw new TypeError('Patterns must be a string or an array of strings'); | 
						|
	} | 
						|
}; | 
						|
 | 
						|
const checkCwdOption = options => { | 
						|
	if (options && options.cwd && !fs.statSync(options.cwd).isDirectory()) { | 
						|
		throw new Error('The `cwd` option must be a path to a directory'); | 
						|
	} | 
						|
}; | 
						|
 | 
						|
const generateGlobTasks = (patterns, taskOptions) => { | 
						|
	patterns = arrayUnion([].concat(patterns)); | 
						|
	assertPatternsInput(patterns); | 
						|
	checkCwdOption(taskOptions); | 
						|
 | 
						|
	const globTasks = []; | 
						|
 | 
						|
	taskOptions = Object.assign({ | 
						|
		ignore: [], | 
						|
		expandDirectories: true | 
						|
	}, taskOptions); | 
						|
 | 
						|
	patterns.forEach((pattern, i) => { | 
						|
		if (isNegative(pattern)) { | 
						|
			return; | 
						|
		} | 
						|
 | 
						|
		const ignore = patterns | 
						|
			.slice(i) | 
						|
			.filter(isNegative) | 
						|
			.map(pattern => pattern.slice(1)); | 
						|
 | 
						|
		const options = Object.assign({}, taskOptions, { | 
						|
			ignore: taskOptions.ignore.concat(ignore) | 
						|
		}); | 
						|
 | 
						|
		globTasks.push({pattern, options}); | 
						|
	}); | 
						|
 | 
						|
	return globTasks; | 
						|
}; | 
						|
 | 
						|
const globDirs = (task, fn) => { | 
						|
	let options = {}; | 
						|
	if (task.options.cwd) { | 
						|
		options.cwd = task.options.cwd; | 
						|
	} | 
						|
 | 
						|
	if (Array.isArray(task.options.expandDirectories)) { | 
						|
		options = Object.assign(options, {files: task.options.expandDirectories}); | 
						|
	} else if (typeof task.options.expandDirectories === 'object') { | 
						|
		options = Object.assign(options, task.options.expandDirectories); | 
						|
	} | 
						|
 | 
						|
	return fn(task.pattern, options); | 
						|
}; | 
						|
 | 
						|
const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern]; | 
						|
 | 
						|
const globToTask = task => glob => { | 
						|
	const {options} = task; | 
						|
	if (options.ignore && Array.isArray(options.ignore) && options.expandDirectories) { | 
						|
		options.ignore = dirGlob.sync(options.ignore); | 
						|
	} | 
						|
 | 
						|
	return { | 
						|
		pattern: glob, | 
						|
		options | 
						|
	}; | 
						|
}; | 
						|
 | 
						|
const globby = (patterns, options) => { | 
						|
	let globTasks; | 
						|
 | 
						|
	try { | 
						|
		globTasks = generateGlobTasks(patterns, options); | 
						|
	} catch (error) { | 
						|
		return Promise.reject(error); | 
						|
	} | 
						|
 | 
						|
	const getTasks = Promise.all(globTasks.map(task => Promise.resolve(getPattern(task, dirGlob)) | 
						|
		.then(globs => Promise.all(globs.map(globToTask(task)))) | 
						|
	)) | 
						|
		.then(tasks => arrayUnion(...tasks)); | 
						|
 | 
						|
	const getFilter = () => { | 
						|
		return Promise.resolve( | 
						|
			options && options.gitignore ? | 
						|
				gitignore({cwd: options.cwd, ignore: options.ignore}) : | 
						|
				DEFAULT_FILTER | 
						|
		); | 
						|
	}; | 
						|
 | 
						|
	return getFilter() | 
						|
		.then(filter => { | 
						|
			return getTasks | 
						|
				.then(tasks => Promise.all(tasks.map(task => fastGlob(task.pattern, task.options)))) | 
						|
				.then(paths => arrayUnion(...paths)) | 
						|
				.then(paths => paths.filter(p => !filter(p))); | 
						|
		}); | 
						|
}; | 
						|
 | 
						|
module.exports = globby; | 
						|
// TODO: Remove this for the next major release | 
						|
module.exports.default = globby; | 
						|
 | 
						|
module.exports.sync = (patterns, options) => { | 
						|
	const globTasks = generateGlobTasks(patterns, options); | 
						|
 | 
						|
	const getFilter = () => { | 
						|
		return options && options.gitignore ? | 
						|
			gitignore.sync({cwd: options.cwd, ignore: options.ignore}) : | 
						|
			DEFAULT_FILTER; | 
						|
	}; | 
						|
 | 
						|
	const tasks = globTasks.reduce((tasks, task) => { | 
						|
		const newTask = getPattern(task, dirGlob.sync).map(globToTask(task)); | 
						|
		return tasks.concat(newTask); | 
						|
	}, []); | 
						|
 | 
						|
	const filter = getFilter(); | 
						|
	return tasks.reduce( | 
						|
		(matches, task) => arrayUnion(matches, fastGlob.sync(task.pattern, task.options)), | 
						|
		[] | 
						|
	).filter(p => !filter(p)); | 
						|
}; | 
						|
 | 
						|
module.exports.generateGlobTasks = generateGlobTasks; | 
						|
 | 
						|
module.exports.hasMagic = (patterns, options) => [] | 
						|
	.concat(patterns) | 
						|
	.some(pattern => glob.hasMagic(pattern, options)); | 
						|
 | 
						|
module.exports.gitignore = gitignore;
 | 
						|
 |