export function match()

in node/task.ts [1406:1532]


export function match(list: string[], patterns: string[] | string, patternRoot?: string, options?: MatchOptions): string[] {
    // trace parameters
    debug(`patternRoot: '${patternRoot}'`);
    options = options || _getDefaultMatchOptions(); // default match options
    _debugMatchOptions(options);

    // convert pattern to an array
    if (typeof patterns == 'string') {
        patterns = [patterns as string];
    }

    // hashtable to keep track of matches
    let map: { [item: string]: boolean } = {};

    let originalOptions = options;
    for (let pattern of patterns) {
        debug(`pattern: '${pattern}'`);

        // trim and skip empty
        pattern = (pattern || '').trim();
        if (!pattern) {
            debug('skipping empty pattern');
            continue;
        }

        // clone match options
        let options = im._cloneMatchOptions(originalOptions);

        // skip comments
        if (!options.nocomment && im._startsWith(pattern, '#')) {
            debug('skipping comment');
            continue;
        }

        // set nocomment - brace expansion could result in a leading '#'
        options.nocomment = true;

        // determine whether pattern is include or exclude
        let negateCount = 0;
        if (!options.nonegate) {
            while (pattern.charAt(negateCount) == '!') {
                negateCount++;
            }

            pattern = pattern.substring(negateCount); // trim leading '!'
            if (negateCount) {
                debug(`trimmed leading '!'. pattern: '${pattern}'`);
            }
        }

        let isIncludePattern = negateCount == 0 ||
            (negateCount % 2 == 0 && !options.flipNegate) ||
            (negateCount % 2 == 1 && options.flipNegate);

        // set nonegate - brace expansion could result in a leading '!'
        options.nonegate = true;
        options.flipNegate = false;

        // expand braces - required to accurately root patterns
        let expanded: string[];
        let preExpanded: string = pattern;
        if (options.nobrace) {
            expanded = [pattern];
        }
        else {
            // convert slashes on Windows before calling braceExpand(). unfortunately this means braces cannot
            // be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
            debug('expanding braces');
            let convertedPattern = process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern;
            expanded = (minimatch as any).braceExpand(convertedPattern);
        }

        // set nobrace
        options.nobrace = true;

        for (let pattern of expanded) {
            if (expanded.length != 1 || pattern != preExpanded) {
                debug(`pattern: '${pattern}'`);
            }

            // trim and skip empty
            pattern = (pattern || '').trim();
            if (!pattern) {
                debug('skipping empty pattern');
                continue;
            }

            // root the pattern when all of the following conditions are true:
            if (patternRoot &&          // patternRoot supplied
                !im._isRooted(pattern) &&  // AND pattern not rooted
                // AND matchBase:false or not basename only
                (!options.matchBase || (process.platform == 'win32' ? pattern.replace(/\\/g, '/') : pattern).indexOf('/') >= 0)) {

                pattern = im._ensureRooted(patternRoot, pattern);
                debug(`rooted pattern: '${pattern}'`);
            }

            if (isIncludePattern) {
                // apply the pattern
                debug('applying include pattern against original list');
                let matchResults: string[] = minimatch.match(list, pattern, options);
                debug(matchResults.length + ' matches');

                // union the results
                for (let matchResult of matchResults) {
                    map[matchResult] = true;
                }
            }
            else {
                // apply the pattern
                debug('applying exclude pattern against original list');
                let matchResults: string[] = minimatch.match(list, pattern, options);
                debug(matchResults.length + ' matches');

                // substract the results
                for (let matchResult of matchResults) {
                    delete map[matchResult];
                }
            }
        }
    }

    // return a filtered version of the original list (preserves order and prevents duplication)
    let result: string[] = list.filter((item: string) => map.hasOwnProperty(item));
    debug(result.length + ' final results');
    return result;
}