1"use strict";
2// this is just a very light wrapper around 2 arrays with an offset index
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.Pattern = void 0;
5const minimatch_1 = require("minimatch");
6const isPatternList = (pl) => pl.length >= 1;
7const isGlobList = (gl) => gl.length >= 1;
8/**
9 * An immutable-ish view on an array of glob parts and their parsed
10 * results
11 */
12class Pattern {
13    #patternList;
14    #globList;
15    #index;
16    length;
17    #platform;
18    #rest;
19    #globString;
20    #isDrive;
21    #isUNC;
22    #isAbsolute;
23    #followGlobstar = true;
24    constructor(patternList, globList, index, platform) {
25        if (!isPatternList(patternList)) {
26            throw new TypeError('empty pattern list');
27        }
28        if (!isGlobList(globList)) {
29            throw new TypeError('empty glob list');
30        }
31        if (globList.length !== patternList.length) {
32            throw new TypeError('mismatched pattern list and glob list lengths');
33        }
34        this.length = patternList.length;
35        if (index < 0 || index >= this.length) {
36            throw new TypeError('index out of range');
37        }
38        this.#patternList = patternList;
39        this.#globList = globList;
40        this.#index = index;
41        this.#platform = platform;
42        // normalize root entries of absolute patterns on initial creation.
43        if (this.#index === 0) {
44            // c: => ['c:/']
45            // C:/ => ['C:/']
46            // C:/x => ['C:/', 'x']
47            // //host/share => ['//host/share/']
48            // //host/share/ => ['//host/share/']
49            // //host/share/x => ['//host/share/', 'x']
50            // /etc => ['/', 'etc']
51            // / => ['/']
52            if (this.isUNC()) {
53                // '' / '' / 'host' / 'share'
54                const [p0, p1, p2, p3, ...prest] = this.#patternList;
55                const [g0, g1, g2, g3, ...grest] = this.#globList;
56                if (prest[0] === '') {
57                    // ends in /
58                    prest.shift();
59                    grest.shift();
60                }
61                const p = [p0, p1, p2, p3, ''].join('/');
62                const g = [g0, g1, g2, g3, ''].join('/');
63                this.#patternList = [p, ...prest];
64                this.#globList = [g, ...grest];
65                this.length = this.#patternList.length;
66            }
67            else if (this.isDrive() || this.isAbsolute()) {
68                const [p1, ...prest] = this.#patternList;
69                const [g1, ...grest] = this.#globList;
70                if (prest[0] === '') {
71                    // ends in /
72                    prest.shift();
73                    grest.shift();
74                }
75                const p = p1 + '/';
76                const g = g1 + '/';
77                this.#patternList = [p, ...prest];
78                this.#globList = [g, ...grest];
79                this.length = this.#patternList.length;
80            }
81        }
82    }
83    /**
84     * The first entry in the parsed list of patterns
85     */
86    pattern() {
87        return this.#patternList[this.#index];
88    }
89    /**
90     * true of if pattern() returns a string
91     */
92    isString() {
93        return typeof this.#patternList[this.#index] === 'string';
94    }
95    /**
96     * true of if pattern() returns GLOBSTAR
97     */
98    isGlobstar() {
99        return this.#patternList[this.#index] === minimatch_1.GLOBSTAR;
100    }
101    /**
102     * true if pattern() returns a regexp
103     */
104    isRegExp() {
105        return this.#patternList[this.#index] instanceof RegExp;
106    }
107    /**
108     * The /-joined set of glob parts that make up this pattern
109     */
110    globString() {
111        return (this.#globString =
112            this.#globString ||
113                (this.#index === 0
114                    ? this.isAbsolute()
115                        ? this.#globList[0] + this.#globList.slice(1).join('/')
116                        : this.#globList.join('/')
117                    : this.#globList.slice(this.#index).join('/')));
118    }
119    /**
120     * true if there are more pattern parts after this one
121     */
122    hasMore() {
123        return this.length > this.#index + 1;
124    }
125    /**
126     * The rest of the pattern after this part, or null if this is the end
127     */
128    rest() {
129        if (this.#rest !== undefined)
130            return this.#rest;
131        if (!this.hasMore())
132            return (this.#rest = null);
133        this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
134        this.#rest.#isAbsolute = this.#isAbsolute;
135        this.#rest.#isUNC = this.#isUNC;
136        this.#rest.#isDrive = this.#isDrive;
137        return this.#rest;
138    }
139    /**
140     * true if the pattern represents a //unc/path/ on windows
141     */
142    isUNC() {
143        const pl = this.#patternList;
144        return this.#isUNC !== undefined
145            ? this.#isUNC
146            : (this.#isUNC =
147                this.#platform === 'win32' &&
148                    this.#index === 0 &&
149                    pl[0] === '' &&
150                    pl[1] === '' &&
151                    typeof pl[2] === 'string' &&
152                    !!pl[2] &&
153                    typeof pl[3] === 'string' &&
154                    !!pl[3]);
155    }
156    // pattern like C:/...
157    // split = ['C:', ...]
158    // XXX: would be nice to handle patterns like `c:*` to test the cwd
159    // in c: for *, but I don't know of a way to even figure out what that
160    // cwd is without actually chdir'ing into it?
161    /**
162     * True if the pattern starts with a drive letter on Windows
163     */
164    isDrive() {
165        const pl = this.#patternList;
166        return this.#isDrive !== undefined
167            ? this.#isDrive
168            : (this.#isDrive =
169                this.#platform === 'win32' &&
170                    this.#index === 0 &&
171                    this.length > 1 &&
172                    typeof pl[0] === 'string' &&
173                    /^[a-z]:$/i.test(pl[0]));
174    }
175    // pattern = '/' or '/...' or '/x/...'
176    // split = ['', ''] or ['', ...] or ['', 'x', ...]
177    // Drive and UNC both considered absolute on windows
178    /**
179     * True if the pattern is rooted on an absolute path
180     */
181    isAbsolute() {
182        const pl = this.#patternList;
183        return this.#isAbsolute !== undefined
184            ? this.#isAbsolute
185            : (this.#isAbsolute =
186                (pl[0] === '' && pl.length > 1) ||
187                    this.isDrive() ||
188                    this.isUNC());
189    }
190    /**
191     * consume the root of the pattern, and return it
192     */
193    root() {
194        const p = this.#patternList[0];
195        return typeof p === 'string' && this.isAbsolute() && this.#index === 0
196            ? p
197            : '';
198    }
199    /**
200     * Check to see if the current globstar pattern is allowed to follow
201     * a symbolic link.
202     */
203    checkFollowGlobstar() {
204        return !(this.#index === 0 ||
205            !this.isGlobstar() ||
206            !this.#followGlobstar);
207    }
208    /**
209     * Mark that the current globstar pattern is following a symbolic link
210     */
211    markFollowGlobstar() {
212        if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
213            return false;
214        this.#followGlobstar = false;
215        return true;
216    }
217}
218exports.Pattern = Pattern;
219//# sourceMappingURL=pattern.js.map