Permalink
Cannot retrieve contributors at this time
255 lines (255 sloc)
10.9 KB
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?
codeql-action/node_modules/@actions/glob/lib/internal-pattern.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | |
if (k2 === undefined) k2 = k; | |
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | |
}) : (function(o, m, k, k2) { | |
if (k2 === undefined) k2 = k; | |
o[k2] = m[k]; | |
})); | |
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | |
Object.defineProperty(o, "default", { enumerable: true, value: v }); | |
}) : function(o, v) { | |
o["default"] = v; | |
}); | |
var __importStar = (this && this.__importStar) || function (mod) { | |
if (mod && mod.__esModule) return mod; | |
var result = {}; | |
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | |
__setModuleDefault(result, mod); | |
return result; | |
}; | |
var __importDefault = (this && this.__importDefault) || function (mod) { | |
return (mod && mod.__esModule) ? mod : { "default": mod }; | |
}; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.Pattern = void 0; | |
const os = __importStar(require("os")); | |
const path = __importStar(require("path")); | |
const pathHelper = __importStar(require("./internal-path-helper")); | |
const assert_1 = __importDefault(require("assert")); | |
const minimatch_1 = require("minimatch"); | |
const internal_match_kind_1 = require("./internal-match-kind"); | |
const internal_path_1 = require("./internal-path"); | |
const IS_WINDOWS = process.platform === 'win32'; | |
class Pattern { | |
constructor(patternOrNegate, isImplicitPattern = false, segments, homedir) { | |
/** | |
* Indicates whether matches should be excluded from the result set | |
*/ | |
this.negate = false; | |
// Pattern overload | |
let pattern; | |
if (typeof patternOrNegate === 'string') { | |
pattern = patternOrNegate.trim(); | |
} | |
// Segments overload | |
else { | |
// Convert to pattern | |
segments = segments || []; | |
assert_1.default(segments.length, `Parameter 'segments' must not empty`); | |
const root = Pattern.getLiteral(segments[0]); | |
assert_1.default(root && pathHelper.hasAbsoluteRoot(root), `Parameter 'segments' first element must be a root path`); | |
pattern = new internal_path_1.Path(segments).toString().trim(); | |
if (patternOrNegate) { | |
pattern = `!${pattern}`; | |
} | |
} | |
// Negate | |
while (pattern.startsWith('!')) { | |
this.negate = !this.negate; | |
pattern = pattern.substr(1).trim(); | |
} | |
// Normalize slashes and ensures absolute root | |
pattern = Pattern.fixupPattern(pattern, homedir); | |
// Segments | |
this.segments = new internal_path_1.Path(pattern).segments; | |
// Trailing slash indicates the pattern should only match directories, not regular files | |
this.trailingSeparator = pathHelper | |
.normalizeSeparators(pattern) | |
.endsWith(path.sep); | |
pattern = pathHelper.safeTrimTrailingSeparator(pattern); | |
// Search path (literal path prior to the first glob segment) | |
let foundGlob = false; | |
const searchSegments = this.segments | |
.map(x => Pattern.getLiteral(x)) | |
.filter(x => !foundGlob && !(foundGlob = x === '')); | |
this.searchPath = new internal_path_1.Path(searchSegments).toString(); | |
// Root RegExp (required when determining partial match) | |
this.rootRegExp = new RegExp(Pattern.regExpEscape(searchSegments[0]), IS_WINDOWS ? 'i' : ''); | |
this.isImplicitPattern = isImplicitPattern; | |
// Create minimatch | |
const minimatchOptions = { | |
dot: true, | |
nobrace: true, | |
nocase: IS_WINDOWS, | |
nocomment: true, | |
noext: true, | |
nonegate: true | |
}; | |
pattern = IS_WINDOWS ? pattern.replace(/\\/g, '/') : pattern; | |
this.minimatch = new minimatch_1.Minimatch(pattern, minimatchOptions); | |
} | |
/** | |
* Matches the pattern against the specified path | |
*/ | |
match(itemPath) { | |
// Last segment is globstar? | |
if (this.segments[this.segments.length - 1] === '**') { | |
// Normalize slashes | |
itemPath = pathHelper.normalizeSeparators(itemPath); | |
// Append a trailing slash. Otherwise Minimatch will not match the directory immediately | |
// preceding the globstar. For example, given the pattern `/foo/**`, Minimatch returns | |
// false for `/foo` but returns true for `/foo/`. Append a trailing slash to handle that quirk. | |
if (!itemPath.endsWith(path.sep) && this.isImplicitPattern === false) { | |
// Note, this is safe because the constructor ensures the pattern has an absolute root. | |
// For example, formats like C: and C:foo on Windows are resolved to an absolute root. | |
itemPath = `${itemPath}${path.sep}`; | |
} | |
} | |
else { | |
// Normalize slashes and trim unnecessary trailing slash | |
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath); | |
} | |
// Match | |
if (this.minimatch.match(itemPath)) { | |
return this.trailingSeparator ? internal_match_kind_1.MatchKind.Directory : internal_match_kind_1.MatchKind.All; | |
} | |
return internal_match_kind_1.MatchKind.None; | |
} | |
/** | |
* Indicates whether the pattern may match descendants of the specified path | |
*/ | |
partialMatch(itemPath) { | |
// Normalize slashes and trim unnecessary trailing slash | |
itemPath = pathHelper.safeTrimTrailingSeparator(itemPath); | |
// matchOne does not handle root path correctly | |
if (pathHelper.dirname(itemPath) === itemPath) { | |
return this.rootRegExp.test(itemPath); | |
} | |
return this.minimatch.matchOne(itemPath.split(IS_WINDOWS ? /\\+/ : /\/+/), this.minimatch.set[0], true); | |
} | |
/** | |
* Escapes glob patterns within a path | |
*/ | |
static globEscape(s) { | |
return (IS_WINDOWS ? s : s.replace(/\\/g, '\\\\')) // escape '\' on Linux/macOS | |
.replace(/(\[)(?=[^/]+\])/g, '[[]') // escape '[' when ']' follows within the path segment | |
.replace(/\?/g, '[?]') // escape '?' | |
.replace(/\*/g, '[*]'); // escape '*' | |
} | |
/** | |
* Normalizes slashes and ensures absolute root | |
*/ | |
static fixupPattern(pattern, homedir) { | |
// Empty | |
assert_1.default(pattern, 'pattern cannot be empty'); | |
// Must not contain `.` segment, unless first segment | |
// Must not contain `..` segment | |
const literalSegments = new internal_path_1.Path(pattern).segments.map(x => Pattern.getLiteral(x)); | |
assert_1.default(literalSegments.every((x, i) => (x !== '.' || i === 0) && x !== '..'), `Invalid pattern '${pattern}'. Relative pathing '.' and '..' is not allowed.`); | |
// Must not contain globs in root, e.g. Windows UNC path \\foo\b*r | |
assert_1.default(!pathHelper.hasRoot(pattern) || literalSegments[0], `Invalid pattern '${pattern}'. Root segment must not contain globs.`); | |
// Normalize slashes | |
pattern = pathHelper.normalizeSeparators(pattern); | |
// Replace leading `.` segment | |
if (pattern === '.' || pattern.startsWith(`.${path.sep}`)) { | |
pattern = Pattern.globEscape(process.cwd()) + pattern.substr(1); | |
} | |
// Replace leading `~` segment | |
else if (pattern === '~' || pattern.startsWith(`~${path.sep}`)) { | |
homedir = homedir || os.homedir(); | |
assert_1.default(homedir, 'Unable to determine HOME directory'); | |
assert_1.default(pathHelper.hasAbsoluteRoot(homedir), `Expected HOME directory to be a rooted path. Actual '${homedir}'`); | |
pattern = Pattern.globEscape(homedir) + pattern.substr(1); | |
} | |
// Replace relative drive root, e.g. pattern is C: or C:foo | |
else if (IS_WINDOWS && | |
(pattern.match(/^[A-Z]:$/i) || pattern.match(/^[A-Z]:[^\\]/i))) { | |
let root = pathHelper.ensureAbsoluteRoot('C:\\dummy-root', pattern.substr(0, 2)); | |
if (pattern.length > 2 && !root.endsWith('\\')) { | |
root += '\\'; | |
} | |
pattern = Pattern.globEscape(root) + pattern.substr(2); | |
} | |
// Replace relative root, e.g. pattern is \ or \foo | |
else if (IS_WINDOWS && (pattern === '\\' || pattern.match(/^\\[^\\]/))) { | |
let root = pathHelper.ensureAbsoluteRoot('C:\\dummy-root', '\\'); | |
if (!root.endsWith('\\')) { | |
root += '\\'; | |
} | |
pattern = Pattern.globEscape(root) + pattern.substr(1); | |
} | |
// Otherwise ensure absolute root | |
else { | |
pattern = pathHelper.ensureAbsoluteRoot(Pattern.globEscape(process.cwd()), pattern); | |
} | |
return pathHelper.normalizeSeparators(pattern); | |
} | |
/** | |
* Attempts to unescape a pattern segment to create a literal path segment. | |
* Otherwise returns empty string. | |
*/ | |
static getLiteral(segment) { | |
let literal = ''; | |
for (let i = 0; i < segment.length; i++) { | |
const c = segment[i]; | |
// Escape | |
if (c === '\\' && !IS_WINDOWS && i + 1 < segment.length) { | |
literal += segment[++i]; | |
continue; | |
} | |
// Wildcard | |
else if (c === '*' || c === '?') { | |
return ''; | |
} | |
// Character set | |
else if (c === '[' && i + 1 < segment.length) { | |
let set = ''; | |
let closed = -1; | |
for (let i2 = i + 1; i2 < segment.length; i2++) { | |
const c2 = segment[i2]; | |
// Escape | |
if (c2 === '\\' && !IS_WINDOWS && i2 + 1 < segment.length) { | |
set += segment[++i2]; | |
continue; | |
} | |
// Closed | |
else if (c2 === ']') { | |
closed = i2; | |
break; | |
} | |
// Otherwise | |
else { | |
set += c2; | |
} | |
} | |
// Closed? | |
if (closed >= 0) { | |
// Cannot convert | |
if (set.length > 1) { | |
return ''; | |
} | |
// Convert to literal | |
if (set) { | |
literal += set; | |
i = closed; | |
continue; | |
} | |
} | |
// Otherwise fall thru | |
} | |
// Append | |
literal += c; | |
} | |
return literal; | |
} | |
/** | |
* Escapes regexp special characters | |
* https://javascript.info/regexp-escaping | |
*/ | |
static regExpEscape(s) { | |
return s.replace(/[[\\^$.|?*+()]/g, '\\$&'); | |
} | |
} | |
exports.Pattern = Pattern; | |
//# sourceMappingURL=internal-pattern.js.map |