Skip to content
Permalink
9bfb9ba527
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
181 lines (141 sloc) 4.37 KB
'use strict';
const fs = require('fs');
const arrayUnion = require('array-union');
const merge2 = require('merge2');
const fastGlob = require('fast-glob');
const dirGlob = require('dir-glob');
const gitignore = require('./gitignore');
const {FilterStream, UniqueStream} = require('./stream-utils');
const DEFAULT_FILTER = () => false;
const isNegative = pattern => pattern[0] === '!';
const assertPatternsInput = patterns => {
if (!patterns.every(pattern => typeof pattern === 'string')) {
throw new TypeError('Patterns must be a string or an array of strings');
}
};
const checkCwdOption = (options = {}) => {
if (!options.cwd) {
return;
}
let stat;
try {
stat = fs.statSync(options.cwd);
} catch {
return;
}
if (!stat.isDirectory()) {
throw new Error('The `cwd` option must be a path to a directory');
}
};
const getPathString = p => p.stats instanceof fs.Stats ? p.path : p;
const generateGlobTasks = (patterns, taskOptions) => {
patterns = arrayUnion([].concat(patterns));
assertPatternsInput(patterns);
checkCwdOption(taskOptions);
const globTasks = [];
taskOptions = {
ignore: [],
expandDirectories: true,
...taskOptions
};
for (const [index, pattern] of patterns.entries()) {
if (isNegative(pattern)) {
continue;
}
const ignore = patterns
.slice(index)
.filter(pattern => isNegative(pattern))
.map(pattern => pattern.slice(1));
const options = {
...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 = {
...options,
files: task.options.expandDirectories
};
} else if (typeof task.options.expandDirectories === 'object') {
options = {
...options,
...task.options.expandDirectories
};
}
return fn(task.pattern, options);
};
const getPattern = (task, fn) => task.options.expandDirectories ? globDirs(task, fn) : [task.pattern];
const getFilterSync = options => {
return options && options.gitignore ?
gitignore.sync({cwd: options.cwd, ignore: options.ignore}) :
DEFAULT_FILTER;
};
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
};
};
module.exports = async (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
const getFilter = async () => {
return options && options.gitignore ?
gitignore({cwd: options.cwd, ignore: options.ignore}) :
DEFAULT_FILTER;
};
const getTasks = async () => {
const tasks = await Promise.all(globTasks.map(async task => {
const globs = await getPattern(task, dirGlob);
return Promise.all(globs.map(globToTask(task)));
}));
return arrayUnion(...tasks);
};
const [filter, tasks] = await Promise.all([getFilter(), getTasks()]);
const paths = await Promise.all(tasks.map(task => fastGlob(task.pattern, task.options)));
return arrayUnion(...paths).filter(path_ => !filter(getPathString(path_)));
};
module.exports.sync = (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
const tasks = [];
for (const task of globTasks) {
const newTask = getPattern(task, dirGlob.sync).map(globToTask(task));
tasks.push(...newTask);
}
const filter = getFilterSync(options);
let matches = [];
for (const task of tasks) {
matches = arrayUnion(matches, fastGlob.sync(task.pattern, task.options));
}
return matches.filter(path_ => !filter(path_));
};
module.exports.stream = (patterns, options) => {
const globTasks = generateGlobTasks(patterns, options);
const tasks = [];
for (const task of globTasks) {
const newTask = getPattern(task, dirGlob.sync).map(globToTask(task));
tasks.push(...newTask);
}
const filter = getFilterSync(options);
const filterStream = new FilterStream(p => !filter(p));
const uniqueStream = new UniqueStream();
return merge2(tasks.map(task => fastGlob.stream(task.pattern, task.options)))
.pipe(filterStream)
.pipe(uniqueStream);
};
module.exports.generateGlobTasks = generateGlobTasks;
module.exports.hasMagic = (patterns, options) => []
.concat(patterns)
.some(pattern => fastGlob.isDynamicPattern(pattern, options));
module.exports.gitignore = gitignore;