diff --git a/.gitignore b/.gitignore index 2973ef9..99a79d5 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ lib/ *.map .DS_Store .github/*.md +dist/cli.js diff --git a/dist/cli.js b/dist/cli.js deleted file mode 100755 index 15071a3..0000000 --- a/dist/cli.js +++ /dev/null @@ -1,2318 +0,0 @@ -#!/usr/bin/env node -"use strict"; -var __create = Object.create; -var __defProp = Object.defineProperty; -var __getOwnPropDesc = Object.getOwnPropertyDescriptor; -var __getOwnPropNames = Object.getOwnPropertyNames; -var __getProtoOf = Object.getPrototypeOf; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __copyProps = (to, from, except, desc) => { - if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); - } - return to; -}; -var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( - // If the importer is in node compatibility mode or this is not an ESM - // file that has been converted to a CommonJS file using a Babel- - // compatible transform (i.e. "__esModule" has not been set), then set - // "default" to the CommonJS "module.exports" for node compatibility. - isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, - mod -)); - -// src/cli.ts -var path4 = __toESM(require("path")); -var fs3 = __toESM(require("fs")); -var os2 = __toESM(require("os")); -var import_child_process2 = require("child_process"); - -// src/core/platform.ts -var os = __toESM(require("os")); -var systemPatterns = { - linux: "linux", - darwin: "(darwin|macos|mac|osx)", - win32: "(windows|win)" -}; -var archPatterns = { - x64: "(x86_64|x64|amd64)", - arm64: "(aarch64|arm64)" -}; -function getPlatformInfo(overrides) { - const system = (overrides?.system || os.platform()).toLowerCase(); - const arch2 = (overrides?.arch || os.arch()).toLowerCase(); - return { - system, - arch: arch2, - systemPattern: systemPatterns[system] || system, - archPattern: archPatterns[arch2] || arch2 - }; -} - -// node_modules/balanced-match/dist/esm/index.js -var balanced = (a, b, str) => { - const ma = a instanceof RegExp ? maybeMatch(a, str) : a; - const mb = b instanceof RegExp ? maybeMatch(b, str) : b; - const r = ma !== null && mb != null && range(ma, mb, str); - return r && { - start: r[0], - end: r[1], - pre: str.slice(0, r[0]), - body: str.slice(r[0] + ma.length, r[1]), - post: str.slice(r[1] + mb.length) - }; -}; -var maybeMatch = (reg, str) => { - const m = str.match(reg); - return m ? m[0] : null; -}; -var range = (a, b, str) => { - let begs, beg, left, right = void 0, result; - let ai = str.indexOf(a); - let bi = str.indexOf(b, ai + 1); - let i = ai; - if (ai >= 0 && bi > 0) { - if (a === b) { - return [ai, bi]; - } - begs = []; - left = str.length; - while (i >= 0 && !result) { - if (i === ai) { - begs.push(i); - ai = str.indexOf(a, i + 1); - } else if (begs.length === 1) { - const r = begs.pop(); - if (r !== void 0) - result = [r, bi]; - } else { - beg = begs.pop(); - if (beg !== void 0 && beg < left) { - left = beg; - right = bi; - } - bi = str.indexOf(b, i + 1); - } - i = ai < bi && ai >= 0 ? ai : bi; - } - if (begs.length && right !== void 0) { - result = [left, right]; - } - } - return result; -}; - -// node_modules/brace-expansion/dist/esm/index.js -var escSlash = "\0SLASH" + Math.random() + "\0"; -var escOpen = "\0OPEN" + Math.random() + "\0"; -var escClose = "\0CLOSE" + Math.random() + "\0"; -var escComma = "\0COMMA" + Math.random() + "\0"; -var escPeriod = "\0PERIOD" + Math.random() + "\0"; -var escSlashPattern = new RegExp(escSlash, "g"); -var escOpenPattern = new RegExp(escOpen, "g"); -var escClosePattern = new RegExp(escClose, "g"); -var escCommaPattern = new RegExp(escComma, "g"); -var escPeriodPattern = new RegExp(escPeriod, "g"); -var slashPattern = /\\\\/g; -var openPattern = /\\{/g; -var closePattern = /\\}/g; -var commaPattern = /\\,/g; -var periodPattern = /\\\./g; -var EXPANSION_MAX = 1e5; -function numeric(str) { - return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0); -} -function escapeBraces(str) { - return str.replace(slashPattern, escSlash).replace(openPattern, escOpen).replace(closePattern, escClose).replace(commaPattern, escComma).replace(periodPattern, escPeriod); -} -function unescapeBraces(str) { - return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, "."); -} -function parseCommaParts(str) { - if (!str) { - return [""]; - } - const parts = []; - const m = balanced("{", "}", str); - if (!m) { - return str.split(","); - } - const { pre, body, post } = m; - const p = pre.split(","); - p[p.length - 1] += "{" + body + "}"; - const postParts = parseCommaParts(post); - if (post.length) { - ; - p[p.length - 1] += postParts.shift(); - p.push.apply(p, postParts); - } - parts.push.apply(parts, p); - return parts; -} -function expand(str, options = {}) { - if (!str) { - return []; - } - const { max = EXPANSION_MAX } = options; - if (str.slice(0, 2) === "{}") { - str = "\\{\\}" + str.slice(2); - } - return expand_(escapeBraces(str), max, true).map(unescapeBraces); -} -function embrace(str) { - return "{" + str + "}"; -} -function isPadded(el) { - return /^-?0\d/.test(el); -} -function lte(i, y) { - return i <= y; -} -function gte(i, y) { - return i >= y; -} -function expand_(str, max, isTop) { - const expansions = []; - const m = balanced("{", "}", str); - if (!m) - return [str]; - const pre = m.pre; - const post = m.post.length ? expand_(m.post, max, false) : [""]; - if (/\$$/.test(m.pre)) { - for (let k = 0; k < post.length && k < max; k++) { - const expansion = pre + "{" + m.body + "}" + post[k]; - expansions.push(expansion); - } - } else { - const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); - const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); - const isSequence = isNumericSequence || isAlphaSequence; - const isOptions = m.body.indexOf(",") >= 0; - if (!isSequence && !isOptions) { - if (m.post.match(/,(?!,).*\}/)) { - str = m.pre + "{" + m.body + escClose + m.post; - return expand_(str, max, true); - } - return [str]; - } - let n; - if (isSequence) { - n = m.body.split(/\.\./); - } else { - n = parseCommaParts(m.body); - if (n.length === 1 && n[0] !== void 0) { - n = expand_(n[0], max, false).map(embrace); - if (n.length === 1) { - return post.map((p) => m.pre + n[0] + p); - } - } - } - let N; - if (isSequence && n[0] !== void 0 && n[1] !== void 0) { - const x = numeric(n[0]); - const y = numeric(n[1]); - const width = Math.max(n[0].length, n[1].length); - let incr = n.length === 3 && n[2] !== void 0 ? Math.max(Math.abs(numeric(n[2])), 1) : 1; - let test = lte; - const reverse = y < x; - if (reverse) { - incr *= -1; - test = gte; - } - const pad = n.some(isPadded); - N = []; - for (let i = x; test(i, y); i += incr) { - let c; - if (isAlphaSequence) { - c = String.fromCharCode(i); - if (c === "\\") { - c = ""; - } - } else { - c = String(i); - if (pad) { - const need = width - c.length; - if (need > 0) { - const z = new Array(need + 1).join("0"); - if (i < 0) { - c = "-" + z + c.slice(1); - } else { - c = z + c; - } - } - } - } - N.push(c); - } - } else { - N = []; - for (let j = 0; j < n.length; j++) { - N.push.apply(N, expand_(n[j], max, false)); - } - } - for (let j = 0; j < N.length; j++) { - for (let k = 0; k < post.length && expansions.length < max; k++) { - const expansion = pre + N[j] + post[k]; - if (!isTop || isSequence || expansion) { - expansions.push(expansion); - } - } - } - } - return expansions; -} - -// node_modules/minimatch/dist/esm/assert-valid-pattern.js -var MAX_PATTERN_LENGTH = 1024 * 64; -var assertValidPattern = (pattern) => { - if (typeof pattern !== "string") { - throw new TypeError("invalid pattern"); - } - if (pattern.length > MAX_PATTERN_LENGTH) { - throw new TypeError("pattern is too long"); - } -}; - -// node_modules/minimatch/dist/esm/brace-expressions.js -var posixClasses = { - "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true], - "[:alpha:]": ["\\p{L}\\p{Nl}", true], - "[:ascii:]": ["\\x00-\\x7f", false], - "[:blank:]": ["\\p{Zs}\\t", true], - "[:cntrl:]": ["\\p{Cc}", true], - "[:digit:]": ["\\p{Nd}", true], - "[:graph:]": ["\\p{Z}\\p{C}", true, true], - "[:lower:]": ["\\p{Ll}", true], - "[:print:]": ["\\p{C}", true], - "[:punct:]": ["\\p{P}", true], - "[:space:]": ["\\p{Z}\\t\\r\\n\\v\\f", true], - "[:upper:]": ["\\p{Lu}", true], - "[:word:]": ["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}", true], - "[:xdigit:]": ["A-Fa-f0-9", false] -}; -var braceEscape = (s) => s.replace(/[[\]\\-]/g, "\\$&"); -var regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); -var rangesToString = (ranges) => ranges.join(""); -var parseClass = (glob, position) => { - const pos = position; - if (glob.charAt(pos) !== "[") { - throw new Error("not in a brace expression"); - } - const ranges = []; - const negs = []; - let i = pos + 1; - let sawStart = false; - let uflag = false; - let escaping = false; - let negate = false; - let endPos = pos; - let rangeStart = ""; - WHILE: while (i < glob.length) { - const c = glob.charAt(i); - if ((c === "!" || c === "^") && i === pos + 1) { - negate = true; - i++; - continue; - } - if (c === "]" && sawStart && !escaping) { - endPos = i + 1; - break; - } - sawStart = true; - if (c === "\\") { - if (!escaping) { - escaping = true; - i++; - continue; - } - } - if (c === "[" && !escaping) { - for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) { - if (glob.startsWith(cls, i)) { - if (rangeStart) { - return ["$.", false, glob.length - pos, true]; - } - i += cls.length; - if (neg) - negs.push(unip); - else - ranges.push(unip); - uflag = uflag || u; - continue WHILE; - } - } - } - escaping = false; - if (rangeStart) { - if (c > rangeStart) { - ranges.push(braceEscape(rangeStart) + "-" + braceEscape(c)); - } else if (c === rangeStart) { - ranges.push(braceEscape(c)); - } - rangeStart = ""; - i++; - continue; - } - if (glob.startsWith("-]", i + 1)) { - ranges.push(braceEscape(c + "-")); - i += 2; - continue; - } - if (glob.startsWith("-", i + 1)) { - rangeStart = c; - i += 2; - continue; - } - ranges.push(braceEscape(c)); - i++; - } - if (endPos < i) { - return ["", false, 0, false]; - } - if (!ranges.length && !negs.length) { - return ["$.", false, glob.length - pos, true]; - } - if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) { - const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]; - return [regexpEscape(r), false, endPos - pos, false]; - } - const sranges = "[" + (negate ? "^" : "") + rangesToString(ranges) + "]"; - const snegs = "[" + (negate ? "" : "^") + rangesToString(negs) + "]"; - const comb = ranges.length && negs.length ? "(" + sranges + "|" + snegs + ")" : ranges.length ? sranges : snegs; - return [comb, uflag, endPos - pos, true]; -}; - -// node_modules/minimatch/dist/esm/unescape.js -var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => { - if (magicalBraces) { - return windowsPathsNoEscape ? s.replace(/\[([^/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^/\\])\]/g, "$1$2").replace(/\\([^/])/g, "$1"); - } - return windowsPathsNoEscape ? s.replace(/\[([^/\\{}])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^/\\{}])\]/g, "$1$2").replace(/\\([^/{}])/g, "$1"); -}; - -// node_modules/minimatch/dist/esm/ast.js -var _a; -var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]); -var isExtglobType = (c) => types.has(c); -var isExtglobAST = (c) => isExtglobType(c.type); -var adoptionMap = /* @__PURE__ */ new Map([ - ["!", ["@"]], - ["?", ["?", "@"]], - ["@", ["@"]], - ["*", ["*", "+", "?", "@"]], - ["+", ["+", "@"]] -]); -var adoptionWithSpaceMap = /* @__PURE__ */ new Map([ - ["!", ["?"]], - ["@", ["?"]], - ["+", ["?", "*"]] -]); -var adoptionAnyMap = /* @__PURE__ */ new Map([ - ["!", ["?", "@"]], - ["?", ["?", "@"]], - ["@", ["?", "@"]], - ["*", ["*", "+", "?", "@"]], - ["+", ["+", "@", "?", "*"]] -]); -var usurpMap = /* @__PURE__ */ new Map([ - ["!", /* @__PURE__ */ new Map([["!", "@"]])], - [ - "?", - /* @__PURE__ */ new Map([ - ["*", "*"], - ["+", "*"] - ]) - ], - [ - "@", - /* @__PURE__ */ new Map([ - ["!", "!"], - ["?", "?"], - ["@", "@"], - ["*", "*"], - ["+", "+"] - ]) - ], - [ - "+", - /* @__PURE__ */ new Map([ - ["?", "*"], - ["*", "*"] - ]) - ] -]); -var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))"; -var startNoDot = "(?!\\.)"; -var addPatternStart = /* @__PURE__ */ new Set(["[", "."]); -var justDots = /* @__PURE__ */ new Set(["..", "."]); -var reSpecials = new Set("().*{}+?[]^$\\!"); -var regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); -var qmark = "[^/]"; -var star = qmark + "*?"; -var starNoEmpty = qmark + "+?"; -var ID = 0; -var AST = class { - type; - #root; - #hasMagic; - #uflag = false; - #parts = []; - #parent; - #parentIndex; - #negs; - #filledNegs = false; - #options; - #toString; - // set to true if it's an extglob with no children - // (which really means one child of '') - #emptyExt = false; - id = ++ID; - get depth() { - return (this.#parent?.depth ?? -1) + 1; - } - [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() { - return { - "@@type": "AST", - id: this.id, - type: this.type, - root: this.#root.id, - parent: this.#parent?.id, - depth: this.depth, - partsLength: this.#parts.length, - parts: this.#parts - }; - } - constructor(type, parent, options = {}) { - this.type = type; - if (type) - this.#hasMagic = true; - this.#parent = parent; - this.#root = this.#parent ? this.#parent.#root : this; - this.#options = this.#root === this ? options : this.#root.#options; - this.#negs = this.#root === this ? [] : this.#root.#negs; - if (type === "!" && !this.#root.#filledNegs) - this.#negs.push(this); - this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0; - } - get hasMagic() { - if (this.#hasMagic !== void 0) - return this.#hasMagic; - for (const p of this.#parts) { - if (typeof p === "string") - continue; - if (p.type || p.hasMagic) - return this.#hasMagic = true; - } - return this.#hasMagic; - } - // reconstructs the pattern - toString() { - return this.#toString !== void 0 ? this.#toString : !this.type ? this.#toString = this.#parts.map((p) => String(p)).join("") : this.#toString = this.type + "(" + this.#parts.map((p) => String(p)).join("|") + ")"; - } - #fillNegs() { - if (this !== this.#root) - throw new Error("should only call on root"); - if (this.#filledNegs) - return this; - this.toString(); - this.#filledNegs = true; - let n; - while (n = this.#negs.pop()) { - if (n.type !== "!") - continue; - let p = n; - let pp = p.#parent; - while (pp) { - for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) { - for (const part of n.#parts) { - if (typeof part === "string") { - throw new Error("string part in extglob AST??"); - } - part.copyIn(pp.#parts[i]); - } - } - p = pp; - pp = p.#parent; - } - } - return this; - } - push(...parts) { - for (const p of parts) { - if (p === "") - continue; - if (typeof p !== "string" && !(p instanceof _a && p.#parent === this)) { - throw new Error("invalid part: " + p); - } - this.#parts.push(p); - } - } - toJSON() { - const ret = this.type === null ? this.#parts.slice().map((p) => typeof p === "string" ? p : p.toJSON()) : [this.type, ...this.#parts.map((p) => p.toJSON())]; - if (this.isStart() && !this.type) - ret.unshift([]); - if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && this.#parent?.type === "!")) { - ret.push({}); - } - return ret; - } - isStart() { - if (this.#root === this) - return true; - if (!this.#parent?.isStart()) - return false; - if (this.#parentIndex === 0) - return true; - const p = this.#parent; - for (let i = 0; i < this.#parentIndex; i++) { - const pp = p.#parts[i]; - if (!(pp instanceof _a && pp.type === "!")) { - return false; - } - } - return true; - } - isEnd() { - if (this.#root === this) - return true; - if (this.#parent?.type === "!") - return true; - if (!this.#parent?.isEnd()) - return false; - if (!this.type) - return this.#parent?.isEnd(); - const pl = this.#parent ? this.#parent.#parts.length : 0; - return this.#parentIndex === pl - 1; - } - copyIn(part) { - if (typeof part === "string") - this.push(part); - else - this.push(part.clone(this)); - } - clone(parent) { - const c = new _a(this.type, parent); - for (const p of this.#parts) { - c.copyIn(p); - } - return c; - } - static #parseAST(str, ast, pos, opt, extDepth) { - const maxDepth = opt.maxExtglobRecursion ?? 2; - let escaping = false; - let inBrace = false; - let braceStart = -1; - let braceNeg = false; - if (ast.type === null) { - let i2 = pos; - let acc2 = ""; - while (i2 < str.length) { - const c = str.charAt(i2++); - if (escaping || c === "\\") { - escaping = !escaping; - acc2 += c; - continue; - } - if (inBrace) { - if (i2 === braceStart + 1) { - if (c === "^" || c === "!") { - braceNeg = true; - } - } else if (c === "]" && !(i2 === braceStart + 2 && braceNeg)) { - inBrace = false; - } - acc2 += c; - continue; - } else if (c === "[") { - inBrace = true; - braceStart = i2; - braceNeg = false; - acc2 += c; - continue; - } - const doRecurse = !opt.noext && isExtglobType(c) && str.charAt(i2) === "(" && extDepth <= maxDepth; - if (doRecurse) { - ast.push(acc2); - acc2 = ""; - const ext2 = new _a(c, ast); - i2 = _a.#parseAST(str, ext2, i2, opt, extDepth + 1); - ast.push(ext2); - continue; - } - acc2 += c; - } - ast.push(acc2); - return i2; - } - let i = pos + 1; - let part = new _a(null, ast); - const parts = []; - let acc = ""; - while (i < str.length) { - const c = str.charAt(i++); - if (escaping || c === "\\") { - escaping = !escaping; - acc += c; - continue; - } - if (inBrace) { - if (i === braceStart + 1) { - if (c === "^" || c === "!") { - braceNeg = true; - } - } else if (c === "]" && !(i === braceStart + 2 && braceNeg)) { - inBrace = false; - } - acc += c; - continue; - } else if (c === "[") { - inBrace = true; - braceStart = i; - braceNeg = false; - acc += c; - continue; - } - const doRecurse = !opt.noext && isExtglobType(c) && str.charAt(i) === "(" && /* c8 ignore start - the maxDepth is sufficient here */ - (extDepth <= maxDepth || ast && ast.#canAdoptType(c)); - if (doRecurse) { - const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1; - part.push(acc); - acc = ""; - const ext2 = new _a(c, part); - part.push(ext2); - i = _a.#parseAST(str, ext2, i, opt, extDepth + depthAdd); - continue; - } - if (c === "|") { - part.push(acc); - acc = ""; - parts.push(part); - part = new _a(null, ast); - continue; - } - if (c === ")") { - if (acc === "" && ast.#parts.length === 0) { - ast.#emptyExt = true; - } - part.push(acc); - acc = ""; - ast.push(...parts, part); - return i; - } - acc += c; - } - ast.type = null; - ast.#hasMagic = void 0; - ast.#parts = [str.substring(pos - 1)]; - return i; - } - #canAdoptWithSpace(child) { - return this.#canAdopt(child, adoptionWithSpaceMap); - } - #canAdopt(child, map = adoptionMap) { - if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null) { - return false; - } - const gc = child.#parts[0]; - if (!gc || typeof gc !== "object" || gc.type === null) { - return false; - } - return this.#canAdoptType(gc.type, map); - } - #canAdoptType(c, map = adoptionAnyMap) { - return !!map.get(this.type)?.includes(c); - } - #adoptWithSpace(child, index) { - const gc = child.#parts[0]; - const blank = new _a(null, gc, this.options); - blank.#parts.push(""); - gc.push(blank); - this.#adopt(child, index); - } - #adopt(child, index) { - const gc = child.#parts[0]; - this.#parts.splice(index, 1, ...gc.#parts); - for (const p of gc.#parts) { - if (typeof p === "object") - p.#parent = this; - } - this.#toString = void 0; - } - #canUsurpType(c) { - const m = usurpMap.get(this.type); - return !!m?.has(c); - } - #canUsurp(child) { - if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null || this.#parts.length !== 1) { - return false; - } - const gc = child.#parts[0]; - if (!gc || typeof gc !== "object" || gc.type === null) { - return false; - } - return this.#canUsurpType(gc.type); - } - #usurp(child) { - const m = usurpMap.get(this.type); - const gc = child.#parts[0]; - const nt = m?.get(gc.type); - if (!nt) - return false; - this.#parts = gc.#parts; - for (const p of this.#parts) { - if (typeof p === "object") { - p.#parent = this; - } - } - this.type = nt; - this.#toString = void 0; - this.#emptyExt = false; - } - static fromGlob(pattern, options = {}) { - const ast = new _a(null, void 0, options); - _a.#parseAST(pattern, ast, 0, options, 0); - return ast; - } - // returns the regular expression if there's magic, or the unescaped - // string if not. - toMMPattern() { - if (this !== this.#root) - return this.#root.toMMPattern(); - const glob = this.toString(); - const [re, body, hasMagic, uflag] = this.toRegExpSource(); - const anyMagic = hasMagic || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly && glob.toUpperCase() !== glob.toLowerCase(); - if (!anyMagic) { - return body; - } - const flags = (this.#options.nocase ? "i" : "") + (uflag ? "u" : ""); - return Object.assign(new RegExp(`^${re}$`, flags), { - _src: re, - _glob: glob - }); - } - get options() { - return this.#options; - } - // returns the string match, the regexp source, whether there's magic - // in the regexp (so a regular expression is required) and whether or - // not the uflag is needed for the regular expression (for posix classes) - // TODO: instead of injecting the start/end at this point, just return - // the BODY of the regexp, along with the start/end portions suitable - // for binding the start/end in either a joined full-path makeRe context - // (where we bind to (^|/), or a standalone matchPart context (where - // we bind to ^, and not /). Otherwise slashes get duped! - // - // In part-matching mode, the start is: - // - if not isStart: nothing - // - if traversal possible, but not allowed: ^(?!\.\.?$) - // - if dots allowed or not possible: ^ - // - if dots possible and not allowed: ^(?!\.) - // end is: - // - if not isEnd(): nothing - // - else: $ - // - // In full-path matching mode, we put the slash at the START of the - // pattern, so start is: - // - if first pattern: same as part-matching mode - // - if not isStart(): nothing - // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/)) - // - if dots allowed or not possible: / - // - if dots possible and not allowed: /(?!\.) - // end is: - // - if last pattern, same as part-matching mode - // - else nothing - // - // Always put the (?:$|/) on negated tails, though, because that has to be - // there to bind the end of the negated pattern portion, and it's easier to - // just stick it in now rather than try to inject it later in the middle of - // the pattern. - // - // We can just always return the same end, and leave it up to the caller - // to know whether it's going to be used joined or in parts. - // And, if the start is adjusted slightly, can do the same there: - // - if not isStart: nothing - // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$) - // - if dots allowed or not possible: (?:/|^) - // - if dots possible and not allowed: (?:/|^)(?!\.) - // - // But it's better to have a simpler binding without a conditional, for - // performance, so probably better to return both start options. - // - // Then the caller just ignores the end if it's not the first pattern, - // and the start always gets applied. - // - // But that's always going to be $ if it's the ending pattern, or nothing, - // so the caller can just attach $ at the end of the pattern when building. - // - // So the todo is: - // - better detect what kind of start is needed - // - return both flavors of starting pattern - // - attach $ at the end of the pattern when creating the actual RegExp - // - // Ah, but wait, no, that all only applies to the root when the first pattern - // is not an extglob. If the first pattern IS an extglob, then we need all - // that dot prevention biz to live in the extglob portions, because eg - // +(*|.x*) can match .xy but not .yx. - // - // So, return the two flavors if it's #root and the first child is not an - // AST, otherwise leave it to the child AST to handle it, and there, - // use the (?:^|/) style of start binding. - // - // Even simplified further: - // - Since the start for a join is eg /(?!\.) and the start for a part - // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root - // or start or whatever) and prepend ^ or / at the Regexp construction. - toRegExpSource(allowDot) { - const dot = allowDot ?? !!this.#options.dot; - if (this.#root === this) { - this.#flatten(); - this.#fillNegs(); - } - if (!isExtglobAST(this)) { - const noEmpty = this.isStart() && this.isEnd() && !this.#parts.some((s) => typeof s !== "string"); - const src = this.#parts.map((p) => { - const [re, _, hasMagic, uflag] = typeof p === "string" ? _a.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot); - this.#hasMagic = this.#hasMagic || hasMagic; - this.#uflag = this.#uflag || uflag; - return re; - }).join(""); - let start2 = ""; - if (this.isStart()) { - if (typeof this.#parts[0] === "string") { - const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]); - if (!dotTravAllowed) { - const aps = addPatternStart; - const needNoTrav = ( - // dots are allowed, and the pattern starts with [ or . - dot && aps.has(src.charAt(0)) || // the pattern starts with \., and then [ or . - src.startsWith("\\.") && aps.has(src.charAt(2)) || // the pattern starts with \.\., and then [ or . - src.startsWith("\\.\\.") && aps.has(src.charAt(4)) - ); - const needNoDot = !dot && !allowDot && aps.has(src.charAt(0)); - start2 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : ""; - } - } - } - let end = ""; - if (this.isEnd() && this.#root.#filledNegs && this.#parent?.type === "!") { - end = "(?:$|\\/)"; - } - const final2 = start2 + src + end; - return [ - final2, - unescape(src), - this.#hasMagic = !!this.#hasMagic, - this.#uflag - ]; - } - const repeated = this.type === "*" || this.type === "+"; - const start = this.type === "!" ? "(?:(?!(?:" : "(?:"; - let body = this.#partsToRegExp(dot); - if (this.isStart() && this.isEnd() && !body && this.type !== "!") { - const s = this.toString(); - const me = this; - me.#parts = [s]; - me.type = null; - me.#hasMagic = void 0; - return [s, unescape(this.toString()), false, false]; - } - let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ? "" : this.#partsToRegExp(true); - if (bodyDotAllowed === body) { - bodyDotAllowed = ""; - } - if (bodyDotAllowed) { - body = `(?:${body})(?:${bodyDotAllowed})*?`; - } - let final = ""; - if (this.type === "!" && this.#emptyExt) { - final = (this.isStart() && !dot ? startNoDot : "") + starNoEmpty; - } else { - const close = this.type === "!" ? ( - // !() must match something,but !(x) can match '' - "))" + (this.isStart() && !dot && !allowDot ? startNoDot : "") + star + ")" - ) : this.type === "@" ? ")" : this.type === "?" ? ")?" : this.type === "+" && bodyDotAllowed ? ")" : this.type === "*" && bodyDotAllowed ? `)?` : `)${this.type}`; - final = start + body + close; - } - return [ - final, - unescape(body), - this.#hasMagic = !!this.#hasMagic, - this.#uflag - ]; - } - #flatten() { - if (!isExtglobAST(this)) { - for (const p of this.#parts) { - if (typeof p === "object") { - p.#flatten(); - } - } - } else { - let iterations = 0; - let done = false; - do { - done = true; - for (let i = 0; i < this.#parts.length; i++) { - const c = this.#parts[i]; - if (typeof c === "object") { - c.#flatten(); - if (this.#canAdopt(c)) { - done = false; - this.#adopt(c, i); - } else if (this.#canAdoptWithSpace(c)) { - done = false; - this.#adoptWithSpace(c, i); - } else if (this.#canUsurp(c)) { - done = false; - this.#usurp(c); - } - } - } - } while (!done && ++iterations < 10); - } - this.#toString = void 0; - } - #partsToRegExp(dot) { - return this.#parts.map((p) => { - if (typeof p === "string") { - throw new Error("string type in extglob ast??"); - } - const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot); - this.#uflag = this.#uflag || uflag; - return re; - }).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|"); - } - static #parseGlob(glob, hasMagic, noEmpty = false) { - let escaping = false; - let re = ""; - let uflag = false; - let inStar = false; - for (let i = 0; i < glob.length; i++) { - const c = glob.charAt(i); - if (escaping) { - escaping = false; - re += (reSpecials.has(c) ? "\\" : "") + c; - continue; - } - if (c === "*") { - if (inStar) - continue; - inStar = true; - re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star; - hasMagic = true; - continue; - } else { - inStar = false; - } - if (c === "\\") { - if (i === glob.length - 1) { - re += "\\\\"; - } else { - escaping = true; - } - continue; - } - if (c === "[") { - const [src, needUflag, consumed, magic] = parseClass(glob, i); - if (consumed) { - re += src; - uflag = uflag || needUflag; - i += consumed - 1; - hasMagic = hasMagic || magic; - continue; - } - } - if (c === "?") { - re += qmark; - hasMagic = true; - continue; - } - re += regExpEscape(c); - } - return [re, unescape(glob), !!hasMagic, uflag]; - } -}; -_a = AST; - -// node_modules/minimatch/dist/esm/escape.js -var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => { - if (magicalBraces) { - return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&"); - } - return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&"); -}; - -// node_modules/minimatch/dist/esm/index.js -var minimatch = (p, pattern, options = {}) => { - assertValidPattern(pattern); - if (!options.nocomment && pattern.charAt(0) === "#") { - return false; - } - return new Minimatch(pattern, options).match(p); -}; -var starDotExtRE = /^\*+([^+@!?*[(]*)$/; -var starDotExtTest = (ext2) => (f) => !f.startsWith(".") && f.endsWith(ext2); -var starDotExtTestDot = (ext2) => (f) => f.endsWith(ext2); -var starDotExtTestNocase = (ext2) => { - ext2 = ext2.toLowerCase(); - return (f) => !f.startsWith(".") && f.toLowerCase().endsWith(ext2); -}; -var starDotExtTestNocaseDot = (ext2) => { - ext2 = ext2.toLowerCase(); - return (f) => f.toLowerCase().endsWith(ext2); -}; -var starDotStarRE = /^\*+\.\*+$/; -var starDotStarTest = (f) => !f.startsWith(".") && f.includes("."); -var starDotStarTestDot = (f) => f !== "." && f !== ".." && f.includes("."); -var dotStarRE = /^\.\*+$/; -var dotStarTest = (f) => f !== "." && f !== ".." && f.startsWith("."); -var starRE = /^\*+$/; -var starTest = (f) => f.length !== 0 && !f.startsWith("."); -var starTestDot = (f) => f.length !== 0 && f !== "." && f !== ".."; -var qmarksRE = /^\?+([^+@!?*[(]*)?$/; -var qmarksTestNocase = ([$0, ext2 = ""]) => { - const noext = qmarksTestNoExt([$0]); - if (!ext2) - return noext; - ext2 = ext2.toLowerCase(); - return (f) => noext(f) && f.toLowerCase().endsWith(ext2); -}; -var qmarksTestNocaseDot = ([$0, ext2 = ""]) => { - const noext = qmarksTestNoExtDot([$0]); - if (!ext2) - return noext; - ext2 = ext2.toLowerCase(); - return (f) => noext(f) && f.toLowerCase().endsWith(ext2); -}; -var qmarksTestDot = ([$0, ext2 = ""]) => { - const noext = qmarksTestNoExtDot([$0]); - return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2); -}; -var qmarksTest = ([$0, ext2 = ""]) => { - const noext = qmarksTestNoExt([$0]); - return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2); -}; -var qmarksTestNoExt = ([$0]) => { - const len = $0.length; - return (f) => f.length === len && !f.startsWith("."); -}; -var qmarksTestNoExtDot = ([$0]) => { - const len = $0.length; - return (f) => f.length === len && f !== "." && f !== ".."; -}; -var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix"; -var path = { - win32: { sep: "\\" }, - posix: { sep: "/" } -}; -var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep; -minimatch.sep = sep; -var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **"); -minimatch.GLOBSTAR = GLOBSTAR; -var qmark2 = "[^/]"; -var star2 = qmark2 + "*?"; -var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?"; -var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?"; -var filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options); -minimatch.filter = filter; -var ext = (a, b = {}) => Object.assign({}, a, b); -var defaults = (def) => { - if (!def || typeof def !== "object" || !Object.keys(def).length) { - return minimatch; - } - const orig = minimatch; - const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options)); - return Object.assign(m, { - Minimatch: class Minimatch extends orig.Minimatch { - constructor(pattern, options = {}) { - super(pattern, ext(def, options)); - } - static defaults(options) { - return orig.defaults(ext(def, options)).Minimatch; - } - }, - AST: class AST extends orig.AST { - /* c8 ignore start */ - constructor(type, parent, options = {}) { - super(type, parent, ext(def, options)); - } - /* c8 ignore stop */ - static fromGlob(pattern, options = {}) { - return orig.AST.fromGlob(pattern, ext(def, options)); - } - }, - unescape: (s, options = {}) => orig.unescape(s, ext(def, options)), - escape: (s, options = {}) => orig.escape(s, ext(def, options)), - filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)), - defaults: (options) => orig.defaults(ext(def, options)), - makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)), - braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)), - match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)), - sep: orig.sep, - GLOBSTAR - }); -}; -minimatch.defaults = defaults; -var braceExpand = (pattern, options = {}) => { - assertValidPattern(pattern); - if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { - return [pattern]; - } - return expand(pattern, { max: options.braceExpandMax }); -}; -minimatch.braceExpand = braceExpand; -var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(); -minimatch.makeRe = makeRe; -var match = (list, pattern, options = {}) => { - const mm = new Minimatch(pattern, options); - list = list.filter((f) => mm.match(f)); - if (mm.options.nonull && !list.length) { - list.push(pattern); - } - return list; -}; -minimatch.match = match; -var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/; -var regExpEscape2 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); -var Minimatch = class { - options; - set; - pattern; - windowsPathsNoEscape; - nonegate; - negate; - comment; - empty; - preserveMultipleSlashes; - partial; - globSet; - globParts; - nocase; - isWindows; - platform; - windowsNoMagicRoot; - maxGlobstarRecursion; - regexp; - constructor(pattern, options = {}) { - assertValidPattern(pattern); - options = options || {}; - this.options = options; - this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200; - this.pattern = pattern; - this.platform = options.platform || defaultPlatform; - this.isWindows = this.platform === "win32"; - const awe = "allowWindowsEscape"; - this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || options[awe] === false; - if (this.windowsPathsNoEscape) { - this.pattern = this.pattern.replace(/\\/g, "/"); - } - this.preserveMultipleSlashes = !!options.preserveMultipleSlashes; - this.regexp = null; - this.negate = false; - this.nonegate = !!options.nonegate; - this.comment = false; - this.empty = false; - this.partial = !!options.partial; - this.nocase = !!this.options.nocase; - this.windowsNoMagicRoot = options.windowsNoMagicRoot !== void 0 ? options.windowsNoMagicRoot : !!(this.isWindows && this.nocase); - this.globSet = []; - this.globParts = []; - this.set = []; - this.make(); - } - hasMagic() { - if (this.options.magicalBraces && this.set.length > 1) { - return true; - } - for (const pattern of this.set) { - for (const part of pattern) { - if (typeof part !== "string") - return true; - } - } - return false; - } - debug(..._) { - } - make() { - const pattern = this.pattern; - const options = this.options; - if (!options.nocomment && pattern.charAt(0) === "#") { - this.comment = true; - return; - } - if (!pattern) { - this.empty = true; - return; - } - this.parseNegate(); - this.globSet = [...new Set(this.braceExpand())]; - if (options.debug) { - this.debug = (...args) => console.error(...args); - } - this.debug(this.pattern, this.globSet); - const rawGlobParts = this.globSet.map((s) => this.slashSplit(s)); - this.globParts = this.preprocess(rawGlobParts); - this.debug(this.pattern, this.globParts); - let set = this.globParts.map((s, _, __) => { - if (this.isWindows && this.windowsNoMagicRoot) { - const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]); - const isDrive = /^[a-z]:/i.test(s[0]); - if (isUNC) { - return [ - ...s.slice(0, 4), - ...s.slice(4).map((ss) => this.parse(ss)) - ]; - } else if (isDrive) { - return [s[0], ...s.slice(1).map((ss) => this.parse(ss))]; - } - } - return s.map((ss) => this.parse(ss)); - }); - this.debug(this.pattern, set); - this.set = set.filter((s) => s.indexOf(false) === -1); - if (this.isWindows) { - for (let i = 0; i < this.set.length; i++) { - const p = this.set[i]; - if (p[0] === "" && p[1] === "" && this.globParts[i][2] === "?" && typeof p[3] === "string" && /^[a-z]:$/i.test(p[3])) { - p[2] = "?"; - } - } - } - this.debug(this.pattern, this.set); - } - // various transforms to equivalent pattern sets that are - // faster to process in a filesystem walk. The goal is to - // eliminate what we can, and push all ** patterns as far - // to the right as possible, even if it increases the number - // of patterns that we have to process. - preprocess(globParts) { - if (this.options.noglobstar) { - for (const partset of globParts) { - for (let j = 0; j < partset.length; j++) { - if (partset[j] === "**") { - partset[j] = "*"; - } - } - } - } - const { optimizationLevel = 1 } = this.options; - if (optimizationLevel >= 2) { - globParts = this.firstPhasePreProcess(globParts); - globParts = this.secondPhasePreProcess(globParts); - } else if (optimizationLevel >= 1) { - globParts = this.levelOneOptimize(globParts); - } else { - globParts = this.adjascentGlobstarOptimize(globParts); - } - return globParts; - } - // just get rid of adjascent ** portions - adjascentGlobstarOptimize(globParts) { - return globParts.map((parts) => { - let gs = -1; - while (-1 !== (gs = parts.indexOf("**", gs + 1))) { - let i = gs; - while (parts[i + 1] === "**") { - i++; - } - if (i !== gs) { - parts.splice(gs, i - gs); - } - } - return parts; - }); - } - // get rid of adjascent ** and resolve .. portions - levelOneOptimize(globParts) { - return globParts.map((parts) => { - parts = parts.reduce((set, part) => { - const prev = set[set.length - 1]; - if (part === "**" && prev === "**") { - return set; - } - if (part === "..") { - if (prev && prev !== ".." && prev !== "." && prev !== "**") { - set.pop(); - return set; - } - } - set.push(part); - return set; - }, []); - return parts.length === 0 ? [""] : parts; - }); - } - levelTwoFileOptimize(parts) { - if (!Array.isArray(parts)) { - parts = this.slashSplit(parts); - } - let didSomething = false; - do { - didSomething = false; - if (!this.preserveMultipleSlashes) { - for (let i = 1; i < parts.length - 1; i++) { - const p = parts[i]; - if (i === 1 && p === "" && parts[0] === "") - continue; - if (p === "." || p === "") { - didSomething = true; - parts.splice(i, 1); - i--; - } - } - if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) { - didSomething = true; - parts.pop(); - } - } - let dd = 0; - while (-1 !== (dd = parts.indexOf("..", dd + 1))) { - const p = parts[dd - 1]; - if (p && p !== "." && p !== ".." && p !== "**" && !(this.isWindows && /^[a-z]:$/i.test(p))) { - didSomething = true; - parts.splice(dd - 1, 2); - dd -= 2; - } - } - } while (didSomething); - return parts.length === 0 ? [""] : parts; - } - // First phase: single-pattern processing - //
is 1 or more portions - //is 1 or more portions - // is any portion other than ., .., '', or ** - //
is . or '' - // - // **/.. is *brutal* for filesystem walking performance, because - // it effectively resets the recursive walk each time it occurs, - // and ** cannot be reduced out by a .. pattern part like a regexp - // or most strings (other than .., ., and '') can be. - // - // /**/..//
/
-> { /..//
/
, /**//
/
} - // // -> /- // //../
-> /- // **/**/ -> **/ - // - // **/*/ -> */**/ <== not valid because ** doesn't follow - // this WOULD be allowed if ** did follow symlinks, or * didn't - firstPhasePreProcess(globParts) { - let didSomething = false; - do { - didSomething = false; - for (let parts of globParts) { - let gs = -1; - while (-1 !== (gs = parts.indexOf("**", gs + 1))) { - let gss = gs; - while (parts[gss + 1] === "**") { - gss++; - } - if (gss > gs) { - parts.splice(gs + 1, gss - gs); - } - let next = parts[gs + 1]; - const p = parts[gs + 2]; - const p2 = parts[gs + 3]; - if (next !== "..") - continue; - if (!p || p === "." || p === ".." || !p2 || p2 === "." || p2 === "..") { - continue; - } - didSomething = true; - parts.splice(gs, 1); - const other = parts.slice(0); - other[gs] = "**"; - globParts.push(other); - gs--; - } - if (!this.preserveMultipleSlashes) { - for (let i = 1; i < parts.length - 1; i++) { - const p = parts[i]; - if (i === 1 && p === "" && parts[0] === "") - continue; - if (p === "." || p === "") { - didSomething = true; - parts.splice(i, 1); - i--; - } - } - if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) { - didSomething = true; - parts.pop(); - } - } - let dd = 0; - while (-1 !== (dd = parts.indexOf("..", dd + 1))) { - const p = parts[dd - 1]; - if (p && p !== "." && p !== ".." && p !== "**") { - didSomething = true; - const needDot = dd === 1 && parts[dd + 1] === "**"; - const splin = needDot ? ["."] : []; - parts.splice(dd - 1, 2, ...splin); - if (parts.length === 0) - parts.push(""); - dd -= 2; - } - } - } - } while (didSomething); - return globParts; - } - // second phase: multi-pattern dedupes - // { /*/, //
} -> /*/- // { /, /} -> /- // { /**/, /} -> /**/- // - // { /**/, /**//
} -> /**/- // ^-- not valid because ** doens't follow symlinks - secondPhasePreProcess(globParts) { - for (let i = 0; i < globParts.length - 1; i++) { - for (let j = i + 1; j < globParts.length; j++) { - const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes); - if (matched) { - globParts[i] = []; - globParts[j] = matched; - break; - } - } - } - return globParts.filter((gs) => gs.length); - } - partsMatch(a, b, emptyGSMatch = false) { - let ai = 0; - let bi = 0; - let result = []; - let which = ""; - while (ai < a.length && bi < b.length) { - if (a[ai] === b[bi]) { - result.push(which === "b" ? b[bi] : a[ai]); - ai++; - bi++; - } else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) { - result.push(a[ai]); - ai++; - } else if (emptyGSMatch && b[bi] === "**" && a[ai] === b[bi + 1]) { - result.push(b[bi]); - bi++; - } else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") { - if (which === "b") - return false; - which = "a"; - result.push(a[ai]); - ai++; - bi++; - } else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") { - if (which === "a") - return false; - which = "b"; - result.push(b[bi]); - ai++; - bi++; - } else { - return false; - } - } - return a.length === b.length && result; - } - parseNegate() { - if (this.nonegate) - return; - const pattern = this.pattern; - let negate = false; - let negateOffset = 0; - for (let i = 0; i < pattern.length && pattern.charAt(i) === "!"; i++) { - negate = !negate; - negateOffset++; - } - if (negateOffset) - this.pattern = pattern.slice(negateOffset); - this.negate = negate; - } - // set partial to true to test if, for example, - // "/a/b" matches the start of "/*/b/*/d" - // Partial means, if you run out of file before you run - // out of pattern, then that's fine, as long as all - // the parts match. - matchOne(file, pattern, partial = false) { - let fileStartIndex = 0; - let patternStartIndex = 0; - if (this.isWindows) { - const fileDrive = typeof file[0] === "string" && /^[a-z]:$/i.test(file[0]); - const fileUNC = !fileDrive && file[0] === "" && file[1] === "" && file[2] === "?" && /^[a-z]:$/i.test(file[3]); - const patternDrive = typeof pattern[0] === "string" && /^[a-z]:$/i.test(pattern[0]); - const patternUNC = !patternDrive && pattern[0] === "" && pattern[1] === "" && pattern[2] === "?" && typeof pattern[3] === "string" && /^[a-z]:$/i.test(pattern[3]); - const fdi = fileUNC ? 3 : fileDrive ? 0 : void 0; - const pdi = patternUNC ? 3 : patternDrive ? 0 : void 0; - if (typeof fdi === "number" && typeof pdi === "number") { - const [fd, pd] = [ - file[fdi], - pattern[pdi] - ]; - if (fd.toLowerCase() === pd.toLowerCase()) { - pattern[pdi] = fd; - patternStartIndex = pdi; - fileStartIndex = fdi; - } - } - } - const { optimizationLevel = 1 } = this.options; - if (optimizationLevel >= 2) { - file = this.levelTwoFileOptimize(file); - } - if (pattern.includes(GLOBSTAR)) { - return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex); - } - return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex); - } - #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) { - const firstgs = pattern.indexOf(GLOBSTAR, patternIndex); - const lastgs = pattern.lastIndexOf(GLOBSTAR); - const [head, body, tail] = partial ? [ - pattern.slice(patternIndex, firstgs), - pattern.slice(firstgs + 1), - [] - ] : [ - pattern.slice(patternIndex, firstgs), - pattern.slice(firstgs + 1, lastgs), - pattern.slice(lastgs + 1) - ]; - if (head.length) { - const fileHead = file.slice(fileIndex, fileIndex + head.length); - if (!this.#matchOne(fileHead, head, partial, 0, 0)) { - return false; - } - fileIndex += head.length; - patternIndex += head.length; - } - let fileTailMatch = 0; - if (tail.length) { - if (tail.length + fileIndex > file.length) - return false; - let tailStart = file.length - tail.length; - if (this.#matchOne(file, tail, partial, tailStart, 0)) { - fileTailMatch = tail.length; - } else { - if (file[file.length - 1] !== "" || fileIndex + tail.length === file.length) { - return false; - } - tailStart--; - if (!this.#matchOne(file, tail, partial, tailStart, 0)) { - return false; - } - fileTailMatch = tail.length + 1; - } - } - if (!body.length) { - let sawSome = !!fileTailMatch; - for (let i2 = fileIndex; i2 < file.length - fileTailMatch; i2++) { - const f = String(file[i2]); - sawSome = true; - if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) { - return false; - } - } - return partial || sawSome; - } - const bodySegments = [[[], 0]]; - let currentBody = bodySegments[0]; - let nonGsParts = 0; - const nonGsPartsSums = [0]; - for (const b of body) { - if (b === GLOBSTAR) { - nonGsPartsSums.push(nonGsParts); - currentBody = [[], 0]; - bodySegments.push(currentBody); - } else { - currentBody[0].push(b); - nonGsParts++; - } - } - let i = bodySegments.length - 1; - const fileLength = file.length - fileTailMatch; - for (const b of bodySegments) { - b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length); - } - return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch); - } - // return false for "nope, not matching" - // return null for "not matching, cannot keep trying" - #matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) { - const bs = bodySegments[bodyIndex]; - if (!bs) { - for (let i = fileIndex; i < file.length; i++) { - sawTail = true; - const f = file[i]; - if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) { - return false; - } - } - return sawTail; - } - const [body, after] = bs; - while (fileIndex <= after) { - const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0); - if (m && globStarDepth < this.maxGlobstarRecursion) { - const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail); - if (sub !== false) { - return sub; - } - } - const f = file[fileIndex]; - if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) { - return false; - } - fileIndex++; - } - return partial || null; - } - #matchOne(file, pattern, partial, fileIndex, patternIndex) { - let fi; - let pi; - let pl; - let fl; - for (fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) { - this.debug("matchOne loop"); - let p = pattern[pi]; - let f = file[fi]; - this.debug(pattern, p, f); - if (p === false || p === GLOBSTAR) { - return false; - } - let hit; - if (typeof p === "string") { - hit = f === p; - this.debug("string match", p, f, hit); - } else { - hit = p.test(f); - this.debug("pattern match", p, f, hit); - } - if (!hit) - return false; - } - if (fi === fl && pi === pl) { - return true; - } else if (fi === fl) { - return partial; - } else if (pi === pl) { - return fi === fl - 1 && file[fi] === ""; - } else { - throw new Error("wtf?"); - } - } - braceExpand() { - return braceExpand(this.pattern, this.options); - } - parse(pattern) { - assertValidPattern(pattern); - const options = this.options; - if (pattern === "**") - return GLOBSTAR; - if (pattern === "") - return ""; - let m; - let fastTest = null; - if (m = pattern.match(starRE)) { - fastTest = options.dot ? starTestDot : starTest; - } else if (m = pattern.match(starDotExtRE)) { - fastTest = (options.nocase ? options.dot ? starDotExtTestNocaseDot : starDotExtTestNocase : options.dot ? starDotExtTestDot : starDotExtTest)(m[1]); - } else if (m = pattern.match(qmarksRE)) { - fastTest = (options.nocase ? options.dot ? qmarksTestNocaseDot : qmarksTestNocase : options.dot ? qmarksTestDot : qmarksTest)(m); - } else if (m = pattern.match(starDotStarRE)) { - fastTest = options.dot ? starDotStarTestDot : starDotStarTest; - } else if (m = pattern.match(dotStarRE)) { - fastTest = dotStarTest; - } - const re = AST.fromGlob(pattern, this.options).toMMPattern(); - if (fastTest && typeof re === "object") { - Reflect.defineProperty(re, "test", { value: fastTest }); - } - return re; - } - makeRe() { - if (this.regexp || this.regexp === false) - return this.regexp; - const set = this.set; - if (!set.length) { - this.regexp = false; - return this.regexp; - } - const options = this.options; - const twoStar = options.noglobstar ? star2 : options.dot ? twoStarDot : twoStarNoDot; - const flags = new Set(options.nocase ? ["i"] : []); - let re = set.map((pattern) => { - const pp = pattern.map((p) => { - if (p instanceof RegExp) { - for (const f of p.flags.split("")) - flags.add(f); - } - return typeof p === "string" ? regExpEscape2(p) : p === GLOBSTAR ? GLOBSTAR : p._src; - }); - pp.forEach((p, i) => { - const next = pp[i + 1]; - const prev = pp[i - 1]; - if (p !== GLOBSTAR || prev === GLOBSTAR) { - return; - } - if (prev === void 0) { - if (next !== void 0 && next !== GLOBSTAR) { - pp[i + 1] = "(?:\\/|" + twoStar + "\\/)?" + next; - } else { - pp[i] = twoStar; - } - } else if (next === void 0) { - pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + ")?"; - } else if (next !== GLOBSTAR) { - pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next; - pp[i + 1] = GLOBSTAR; - } - }); - const filtered = pp.filter((p) => p !== GLOBSTAR); - if (this.partial && filtered.length >= 1) { - const prefixes = []; - for (let i = 1; i <= filtered.length; i++) { - prefixes.push(filtered.slice(0, i).join("/")); - } - return "(?:" + prefixes.join("|") + ")"; - } - return filtered.join("/"); - }).join("|"); - const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""]; - re = "^" + open + re + close + "$"; - if (this.partial) { - re = "^(?:\\/|" + open + re.slice(1, -1) + close + ")$"; - } - if (this.negate) - re = "^(?!" + re + ").+$"; - try { - this.regexp = new RegExp(re, [...flags].join("")); - } catch { - this.regexp = false; - } - return this.regexp; - } - slashSplit(p) { - if (this.preserveMultipleSlashes) { - return p.split("/"); - } else if (this.isWindows && /^\/\/[^/]+/.test(p)) { - return ["", ...p.split(/\/+/)]; - } else { - return p.split(/\/+/); - } - } - match(f, partial = this.partial) { - this.debug("match", f, this.pattern); - if (this.comment) { - return false; - } - if (this.empty) { - return f === ""; - } - if (f === "/" && partial) { - return true; - } - const options = this.options; - if (this.isWindows) { - f = f.split("\\").join("/"); - } - const ff = this.slashSplit(f); - this.debug(this.pattern, "split", ff); - const set = this.set; - this.debug(this.pattern, "set", set); - let filename = ff[ff.length - 1]; - if (!filename) { - for (let i = ff.length - 2; !filename && i >= 0; i--) { - filename = ff[i]; - } - } - for (const pattern of set) { - let file = ff; - if (options.matchBase && pattern.length === 1) { - file = [filename]; - } - const hit = this.matchOne(file, pattern, partial); - if (hit) { - if (options.flipNegate) { - return true; - } - return !this.negate; - } - } - if (options.flipNegate) { - return false; - } - return this.negate; - } - static defaults(def) { - return minimatch.defaults(def).Minimatch; - } -}; -minimatch.AST = AST; -minimatch.Minimatch = Minimatch; -minimatch.escape = escape; -minimatch.unescape = unescape; - -// src/core/matcher.ts -var knownFileTypes = { - archive: "*.{zip,tar.gz,tgz}", - package: "*.{deb,pkg,rpm}", - linux: "*.{deb,rpm}", - macos: "*.pkg", - targz: "*.{tgz,tar.gz}" -}; -function filterByRegex(assets, pattern) { - const regex = new RegExp(pattern, "i"); - return assets.filter((asset) => regex.test(asset.name)); -} -function replacePlatformPlaceholders(pattern, platform2) { - return pattern.replace(/{{SYSTEM}}/g, platform2.systemPattern).replace(/{{ARCH}}/g, platform2.archPattern); -} -function getMatchingAsset(assets, platform2, fileName, fileType) { - if (fileName && !fileName.startsWith("~")) { - const exactMatches = assets.filter((asset) => asset.name === fileName); - if (exactMatches.length !== 1) { - throw new Error(`Expected exactly one asset to match the provided filename, matched: ${exactMatches.length}`); - } - return exactMatches[0]; - } - let fileTypeFilteredAssets = assets; - if (fileType) { - if (Object.hasOwn(knownFileTypes, fileType)) { - const fileTypeGlob = knownFileTypes[fileType]; - fileTypeFilteredAssets = assets.filter((asset) => minimatch(asset.name, fileTypeGlob, { nocase: true })); - } else if (fileType.startsWith("~")) { - const fileTypeRegex = `${fileType.substring(1)}$`; - fileTypeFilteredAssets = filterByRegex(assets, fileTypeRegex); - } else { - const extension = fileType.replace(/^\./, ""); - const fileTypeGlob = `*.${extension}`; - fileTypeFilteredAssets = assets.filter((asset) => minimatch(asset.name, fileTypeGlob, { nocase: true })); - } - } - if (fileName && fileName.startsWith("~")) { - const fileNamePattern = replacePlatformPlaceholders(fileName.substring(1), platform2); - const fileNameFilteredAssets = filterByRegex(fileTypeFilteredAssets, fileNamePattern); - if (fileNameFilteredAssets.length !== 1) { - throw new Error(`Expected exactly one asset to match the filename regex, matched: ${fileNameFilteredAssets.length}`); - } - return fileNameFilteredAssets[0]; - } - const defaultPattern = replacePlatformPlaceholders("{{SYSTEM}}[_-]{{ARCH}}", platform2); - const defaultFilteredAssets = filterByRegex(fileTypeFilteredAssets, defaultPattern); - if (defaultFilteredAssets.length !== 1) { - const errorMessage = defaultFilteredAssets.length === 0 ? `No assets matched the default criteria: ${defaultPattern}` : `Multiple assets matched the default criteria: ${defaultFilteredAssets.map((asset) => asset.name).join(", ")}`; - throw new Error(errorMessage); - } - return defaultFilteredAssets[0]; -} - -// src/core/finder.ts -var fs = __toESM(require("fs")); -var path2 = __toESM(require("path")); -function findBinary(dir, pattern, debug, logger) { - const items = fs.readdirSync(dir); - if (debug) { - logger(`Searching for binary in ${dir}...`); - items.forEach((item) => logger(` - ${item}`)); - } - for (const item of items) { - const fullPath = path2.join(dir, item); - const stat = fs.statSync(fullPath); - if (stat.isDirectory()) { - const found = findBinary(fullPath, pattern, debug, logger); - if (found) return found; - } else { - let isMatch = false; - if (pattern instanceof RegExp) { - isMatch = pattern.test(item); - } else { - isMatch = item === pattern; - if (!isMatch && process.platform === "win32" && !pattern.toLowerCase().endsWith(".exe")) { - isMatch = item.toLowerCase() === `${pattern.toLowerCase()}.exe`; - } - } - if (isMatch) return fullPath; - } - } - return void 0; -} - -// src/core/downloader.ts -function getGithubApiHeaders(token) { - const headers = { - "Accept": "application/vnd.github.v3+json", - "User-Agent": "setup-github-release-action" - }; - if (token) { - headers["Authorization"] = `token ${token}`; - } - return headers; -} -async function fetchLatestRelease(repository, token) { - const url = `https://api.github.com/repos/${repository}/releases/latest`; - const headers = getGithubApiHeaders(token); - const response = await fetch(url, { headers }); - if (!response.ok) { - const errorBody = await response.text(); - throw new Error(`Failed to fetch latest release for ${repository}: ${response.statusText}. ${errorBody}`); - } - return await response.json(); -} -async function fetchLatestReleaseRaw(repository, token) { - const url = `https://api.github.com/repos/${repository}/releases/latest`; - const headers = getGithubApiHeaders(token); - const response = await fetch(url, { headers }); - const body = await response.text(); - if (!response.ok) { - throw new Error(`Failed to fetch latest release for ${repository}: ${response.statusText}. ${body}`); - } - return body; -} -async function downloadAsset(url, destPath, token) { - const headers = { - "User-Agent": "setup-github-release-action" - }; - if (token) { - headers["Authorization"] = `token ${token}`; - } - const response = await fetch(url, { headers }); - if (!response.ok) { - throw new Error(`Failed to download asset: ${response.statusText}`); - } - const fs4 = await import("fs"); - const { Readable } = await import("stream"); - const { finished } = await import("stream/promises"); - const fileStream = fs4.createWriteStream(destPath); - await finished(Readable.fromWeb(response.body).pipe(fileStream)); -} - -// src/core/extractor.ts -var import_child_process = require("child_process"); -var path3 = __toESM(require("path")); -var fs2 = __toESM(require("fs")); -async function extractAsset(filePath, destDir) { - const ext2 = path3.extname(filePath).toLowerCase(); - const name = path3.basename(filePath).toLowerCase(); - if (!fs2.existsSync(destDir)) { - fs2.mkdirSync(destDir, { recursive: true }); - } - if (name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".tar")) { - const args = ["-xf", filePath, "-C", destDir]; - const result = (0, import_child_process.spawnSync)("tar", args); - if (result.status !== 0) { - throw new Error(`tar failed with status ${result.status}: ${result.stderr.toString()}`); - } - } else if (name.endsWith(".zip")) { - if (process.platform === "win32") { - const tarResult = (0, import_child_process.spawnSync)("tar", ["-xf", filePath, "-C", destDir]); - if (tarResult.status === 0) return; - const escapedFilePath = filePath.replace(/'/g, "''"); - const escapedDestDir = destDir.replace(/'/g, "''"); - const dotNetCommand = `Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFilePath}', '${escapedDestDir}')`; - for (const shell of ["pwsh", "powershell"]) { - const result = (0, import_child_process.spawnSync)(shell, ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", dotNetCommand]); - if (result.status === 0) return; - } - throw new Error(`Extraction failed: Both tar and PowerShell fallback failed. Make sure your system can extract ZIP files.`); - } else { - const result = (0, import_child_process.spawnSync)("unzip", ["-q", filePath, "-d", destDir]); - if (result.status !== 0) { - throw new Error(`unzip failed with status ${result.status}: ${result.stderr.toString()}`); - } - } - } else if (name.endsWith(".7z")) { - const result = (0, import_child_process.spawnSync)("7z", ["x", filePath, `-o${destDir}`, "-y"]); - if (result.status !== 0) { - throw new Error(`7z failed with status ${result.status}. Make sure 7z is installed.`); - } - } else { - const destPath = path3.join(destDir, path3.basename(filePath)); - fs2.copyFileSync(filePath, destPath); - } -} - -// src/cli.ts -function usage() { - return ` -Usage: install-github-release [options] - -Arguments: - repository The GitHub repository (owner/repo) - -Options: - --dry-run [level] Run in test mode (default level: 1) - -l, --list [repository] List available assets from latest release and exit - -a, --app-name Application name (optional, for output messages) - -f, --file-name Asset file name or regex pattern (prefixed with ~) - -b, --binary-name Binary name (supports source:destination form) - -t, --file-type Known: archive|package|linux|macos|targz - Or custom: ~ (end-of-string match) or extension (e.g. zip, .tar.gz) - -p, --install-path Custom installation directory - -o, --output-directory - Only download selected asset to the specified directory - -j, --releases-json Download latest release JSON only - --system Override detected system for asset matching - --arch Override detected architecture for asset matching - -k, --token GitHub token - -d, --debug Enable debug logging - -h, --help Show this help message - `; -} -function ensureOptionValue(argv, index, option) { - const value = argv[index + 1]; - if (!value || value.startsWith("-")) { - throw new Error(`Missing value for ${option}.`); - } - return value; -} -function parseCliArgs(argv) { - const envDryRun = process.env.TEST_MODE; - const dryRunLevelFromEnv = envDryRun && /^\d+$/.test(envDryRun) ? parseInt(envDryRun, 10) : 0; - const opts = { - releasesJsonOnly: false, - listOnly: false, - debug: false, - help: false, - dryRunLevel: dryRunLevelFromEnv, - positionals: [] - }; - for (let i = 0; i < argv.length; i++) { - const arg = argv[i]; - switch (arg) { - case "-h": - case "--help": - opts.help = true; - break; - case "--dry-run": { - const next = argv[i + 1]; - if (next && /^\d+$/.test(next)) { - opts.dryRunLevel = parseInt(next, 10); - i++; - } else { - opts.dryRunLevel = 1; - } - break; - } - case "-l": - case "--list": { - opts.listOnly = true; - const next = argv[i + 1]; - if (next && !next.startsWith("-")) { - opts.listRepo = next; - i++; - } - break; - } - case "-a": - case "--app-name": - opts.appName = ensureOptionValue(argv, i, arg); - i++; - break; - case "-f": - case "--file-name": - opts.fileName = ensureOptionValue(argv, i, arg); - i++; - break; - case "-b": - case "--binary-name": - opts.binaryName = ensureOptionValue(argv, i, arg); - i++; - break; - case "-t": - case "--file-type": { - const fileType = ensureOptionValue(argv, i, arg); - if (!fileType.trim()) { - throw new Error(`Unknown asset type: ${fileType}`); - } - opts.fileType = fileType; - i++; - break; - } - case "-p": - case "--install-path": - opts.installPath = ensureOptionValue(argv, i, arg); - i++; - break; - case "-o": - case "--output-directory": - opts.outputDirectory = ensureOptionValue(argv, i, arg); - i++; - break; - case "-j": - case "--releases-json": - opts.releasesJsonOnly = true; - break; - case "--system": - opts.systemOverride = ensureOptionValue(argv, i, arg); - i++; - break; - case "--arch": - opts.archOverride = ensureOptionValue(argv, i, arg); - i++; - break; - case "-k": - case "--token": - opts.token = ensureOptionValue(argv, i, arg); - i++; - break; - case "-d": - case "--debug": - opts.debug = true; - break; - default: - if (arg.startsWith("-")) { - throw new Error(`Unknown option: ${arg}`); - } - opts.positionals.push(arg); - break; - } - } - return opts; -} -function validateOutputDirectory(outputDirectory) { - const resolvedPath = path4.resolve(outputDirectory); - if (!fs3.existsSync(resolvedPath) || !fs3.statSync(resolvedPath).isDirectory()) { - throw new Error(`Output directory "${resolvedPath}" does not exist.`); - } - return resolvedPath; -} -function getInstallDir(installPath) { - if (installPath) { - return path4.resolve(installPath); - } - if (process.platform === "win32") { - const localAppData = process.env.LOCALAPPDATA || path4.join(os2.homedir(), "AppData", "Local"); - return path4.join(localAppData, "bin"); - } - const isRoot = process.getuid && process.getuid() === 0; - if (isRoot) { - return "/usr/local/bin"; - } - const homeBin = path4.join(os2.homedir(), "bin"); - if (fs3.existsSync(homeBin)) { - return homeBin; - } - return "/usr/local/bin"; -} -function installSystemPackage(downloadPath) { - const fileName = path4.basename(downloadPath).toLowerCase(); - const command = fileName.endsWith(".deb") ? { binary: "dpkg", args: ["-i", downloadPath] } : fileName.endsWith(".pkg") ? { binary: "installer", args: ["-pkg", downloadPath, "-target", "/"] } : fileName.endsWith(".rpm") ? { binary: "rpm", args: ["-i", downloadPath] } : void 0; - if (!command) { - throw new Error(`Unsupported package type: ${fileName}`); - } - const isRoot = process.getuid && process.getuid() === 0; - const commandToRun = isRoot ? command.binary : "sudo"; - const argsToRun = isRoot ? command.args : [command.binary, ...command.args]; - const result = (0, import_child_process2.spawnSync)(commandToRun, argsToRun, { stdio: "inherit" }); - if (result.status !== 0) { - throw new Error(`Failed to install package using ${commandToRun} ${argsToRun.join(" ")}.`); - } -} -async function run() { - let tempDir; - try { - const options = parseCliArgs(process.argv.slice(2)); - const repository = options.listRepo || options.positionals[0]; - if (options.help || !repository) { - console.log(usage()); - process.exit(options.help ? 0 : 1); - } - const token = options.token || process.env.GITHUB_TOKEN; - if (options.listOnly) { - const release2 = await fetchLatestRelease(repository, token); - release2.assets.forEach((asset2) => console.log(`- ${asset2.browser_download_url}`)); - process.exit(0); - } - const toolName = repository.split("/").pop() || repository; - const appName = options.appName || toolName.charAt(0).toUpperCase() + toolName.slice(1); - const binaryOption = options.binaryName || toolName; - const [binarySource, binaryDestination] = binaryOption.includes(":") ? [binaryOption.split(":")[0], binaryOption.split(":")[1]] : [binaryOption, binaryOption]; - if (options.releasesJsonOnly) { - const rawRelease = await fetchLatestReleaseRaw(repository, token); - const outputBase = binaryDestination || toolName; - const outputName = `${outputBase}.releases.json`; - const outputPath = options.outputDirectory ? path4.join(validateOutputDirectory(options.outputDirectory), outputName) : outputName; - fs3.writeFileSync(outputPath, rawRelease, "utf8"); - console.log(`Downloaded GitHub releases to ${outputPath}.`); - process.exit(0); - } - const platformInfo = getPlatformInfo({ - system: options.systemOverride, - arch: options.archOverride - }); - console.log(`Fetching latest release for ${repository}...`); - const release = await fetchLatestRelease(repository, token); - const asset = getMatchingAsset(release.assets, platformInfo, options.fileName, options.fileType); - const version = release.tag_name.replace(/^v/i, ""); - const downloadUrl = asset.browser_download_url; - console.log(`Will download '${appName}' version: ${version}`); - console.log(`Download URL: "${downloadUrl}".`); - if (options.dryRunLevel > 0) { - process.exit(0); - } - if (options.outputDirectory) { - const outputDir = validateOutputDirectory(options.outputDirectory); - const outputPath = path4.join(outputDir, path4.basename(downloadUrl)); - console.log(`Downloading '${appName}' version ${version} to '${outputPath}'...`); - await downloadAsset(downloadUrl, outputPath, token); - process.exit(0); - } - tempDir = fs3.mkdtempSync(path4.join(os2.tmpdir(), "setup-gh-release-")); - const downloadPath = path4.join(tempDir, asset.name); - await downloadAsset(downloadUrl, downloadPath, token); - if (/\.(deb|pkg|rpm)$/i.test(asset.name)) { - installSystemPackage(downloadPath); - console.log("Installation successful!"); - process.exit(0); - } - const extractDir = path4.join(tempDir, "extract"); - console.log(`Extracting ${asset.name}...`); - await extractAsset(downloadPath, extractDir); - let binaryPattern; - if (binarySource.startsWith("~")) { - binaryPattern = new RegExp(binarySource.substring(1), "i"); - } else { - binaryPattern = binarySource; - } - const binaryPath = findBinary(extractDir, binaryPattern, options.debug, console.log); - if (!binaryPath) { - throw new Error(`Could not find binary "${binarySource}" in the extracted asset.`); - } - const installDir = getInstallDir(options.installPath); - if (!fs3.existsSync(installDir)) { - fs3.mkdirSync(installDir, { recursive: true }); - } - const finalName = binaryDestination || path4.basename(binaryPath); - const destPath = path4.join(installDir, finalName); - console.log(`Installing ${finalName} to ${destPath}...`); - try { - fs3.copyFileSync(binaryPath, destPath); - } catch (err) { - if (err.code === "EBUSY") { - throw new Error(`The file ${destPath} is currently in use. Please close any running instances and try again.`); - } - if (err.code === "EACCES" || err.code === "EPERM") { - throw new Error(`Permission denied while installing to ${destPath}. Try running with sudo or as administrator, or use -p to specify a custom path.`); - } - throw err; - } - if (process.platform !== "win32") { - fs3.chmodSync(destPath, "755"); - } - console.log("Installation successful!"); - process.exit(0); - } catch (error) { - if (error?.message) { - console.error(`Error: ${error.message}`); - } else { - console.error("Error: Unknown failure."); - } - process.exit(1); - } finally { - if (tempDir && fs3.existsSync(tempDir)) { - fs3.rmSync(tempDir, { recursive: true, force: true }); - } - } -} -run();