forked from mrmlnc/fast-glob
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tasks.ts
132 lines (107 loc) · 4.99 KB
/
tasks.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import Settings from '../settings';
import { Pattern, PatternsGroup } from '../types';
import * as utils from '../utils';
export type Task = {
base: string;
dynamic: boolean;
patterns: Pattern[];
positive: Pattern[];
negative: Pattern[];
};
export function generate(input: Pattern[], settings: Settings): Task[] {
const patterns = processPatterns(input, settings);
const ignore = processPatterns(settings.ignore, settings);
const positivePatterns = getPositivePatterns(patterns);
const negativePatterns = getNegativePatternsAsPositive(patterns, ignore);
const staticPatterns = positivePatterns.filter((pattern) => utils.pattern.isStaticPattern(pattern, settings));
const dynamicPatterns = positivePatterns.filter((pattern) => utils.pattern.isDynamicPattern(pattern, settings));
const staticTasks = convertPatternsToTasks(staticPatterns, negativePatterns, /* dynamic */ false);
const dynamicTasks = convertPatternsToTasks(dynamicPatterns, negativePatterns, /* dynamic */ true);
return staticTasks.concat(dynamicTasks);
}
function processPatterns(input: Pattern[], settings: Settings): Pattern[] {
let patterns: Pattern[] = input;
/**
* The original pattern like `{,*,**,a/*}` can lead to problems checking the depth when matching entry
* and some problems with the micromatch package (see fast-glob issues: #365, #394).
*
* To solve this problem, we expand all patterns containing brace expansion. This can lead to a slight slowdown
* in matching in the case of a large set of patterns after expansion.
*/
if (settings.braceExpansion) {
patterns = utils.pattern.expandPatternsWithBraceExpansion(patterns);
}
/**
* If the `baseNameMatch` option is enabled, we must add globstar to patterns, so that they can be used
* at any nesting level.
*
* We do this here, because otherwise we have to complicate the filtering logic. For example, we need to change
* the pattern in the filter before creating a regular expression. There is no need to change the patterns
* in the application. Only on the input.
*/
if (settings.baseNameMatch) {
patterns = patterns.map((pattern) => pattern.includes('/') ? pattern : `**/${pattern}`);
}
/**
* This method also removes duplicate slashes that may have been in the pattern or formed as a result of expansion.
*/
return patterns.map((pattern) => utils.pattern.removeDuplicateSlashes(pattern));
}
/**
* Returns tasks grouped by basic pattern directories.
*
* Patterns that can be found inside (`./`) and outside (`../`) the current directory are handled separately.
* This is necessary because directory traversal starts at the base directory and goes deeper.
*/
export function convertPatternsToTasks(positive: Pattern[], negative: Pattern[], dynamic: boolean): Task[] {
const tasks: Task[] = [];
const patternsOutsideCurrentDirectory = utils.pattern.getPatternsOutsideCurrentDirectory(positive);
const patternsInsideCurrentDirectory = utils.pattern.getPatternsInsideCurrentDirectory(positive);
const outsideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsOutsideCurrentDirectory);
const insideCurrentDirectoryGroup = groupPatternsByBaseDirectory(patternsInsideCurrentDirectory);
tasks.push(...convertPatternGroupsToTasks(outsideCurrentDirectoryGroup, negative, dynamic));
/*
* For the sake of reducing future accesses to the file system, we merge all tasks within the current directory
* into a global task, if at least one pattern refers to the root (`.`). In this case, the global task covers the rest.
*/
if ('.' in insideCurrentDirectoryGroup) {
tasks.push(convertPatternGroupToTask('.', patternsInsideCurrentDirectory, negative, dynamic));
} else {
tasks.push(...convertPatternGroupsToTasks(insideCurrentDirectoryGroup, negative, dynamic));
}
return tasks;
}
export function getPositivePatterns(patterns: Pattern[]): Pattern[] {
return utils.pattern.getPositivePatterns(patterns);
}
export function getNegativePatternsAsPositive(patterns: Pattern[], ignore: Pattern[]): Pattern[] {
const negative = utils.pattern.getNegativePatterns(patterns).concat(ignore);
const positive = negative.map(utils.pattern.convertToPositivePattern);
return positive;
}
export function groupPatternsByBaseDirectory(patterns: Pattern[]): PatternsGroup {
const group: PatternsGroup = {};
return patterns.reduce((collection, pattern) => {
const base = utils.pattern.getBaseDirectory(pattern);
if (base in collection) {
collection[base].push(pattern);
} else {
collection[base] = [pattern];
}
return collection;
}, group);
}
export function convertPatternGroupsToTasks(positive: PatternsGroup, negative: Pattern[], dynamic: boolean): Task[] {
return Object.keys(positive).map((base) => {
return convertPatternGroupToTask(base, positive[base], negative, dynamic);
});
}
export function convertPatternGroupToTask(base: string, positive: Pattern[], negative: Pattern[], dynamic: boolean): Task {
return {
dynamic,
positive,
negative,
base,
patterns: ([] as Pattern[]).concat(positive, negative.map(utils.pattern.convertToNegativePattern))
};
}