1#!/usr/bin/env node 2"use strict"; 3Object.defineProperty(exports, "__esModule", { value: true }); 4const foreground_child_1 = require("foreground-child"); 5const fs_1 = require("fs"); 6const jackspeak_1 = require("jackspeak"); 7const index_js_1 = require("./index.js"); 8const package_json_1 = require("../package.json"); 9const j = (0, jackspeak_1.jack)({ 10 usage: 'glob [options] [<pattern> [<pattern> ...]]' 11}) 12 .description(` 13 Glob v${package_json_1.version} 14 15 Expand the positional glob expression arguments into any matching file 16 system paths found. 17 `) 18 .opt({ 19 cmd: { 20 short: 'c', 21 hint: 'command', 22 description: `Run the command provided, passing the glob expression 23 matches as arguments.`, 24 }, 25}) 26 .flag({ 27 all: { 28 short: 'A', 29 description: `By default, the glob cli command will not expand any 30 arguments that are an exact match to a file on disk. 31 32 This prevents double-expanding, in case the shell expands 33 an argument whose filename is a glob expression. 34 35 For example, if 'app/*.ts' would match 'app/[id].ts', then 36 on Windows powershell or cmd.exe, 'glob app/*.ts' will 37 expand to 'app/[id].ts', as expected. However, in posix 38 shells such as bash or zsh, the shell will first expand 39 'app/*.ts' to a list of filenames. Then glob will look 40 for a file matching 'app/[id].ts' (ie, 'app/i.ts' or 41 'app/d.ts'), which is unexpected. 42 43 Setting '--all' prevents this behavior, causing glob 44 to treat ALL patterns as glob expressions to be expanded, 45 even if they are an exact match to a file on disk. 46 47 When setting this option, be sure to enquote arguments 48 so that the shell will not expand them prior to passing 49 them to the glob command process. 50 `, 51 }, 52 absolute: { 53 short: 'a', 54 description: 'Expand to absolute paths', 55 }, 56 'dot-relative': { 57 short: 'd', 58 description: `Prepend './' on relative matches`, 59 }, 60 mark: { 61 short: 'm', 62 description: `Append a / on any directories matched`, 63 }, 64 posix: { 65 short: 'x', 66 description: `Always resolve to posix style paths, using '/' as the 67 directory separator, even on Windows. Drive letter 68 absolute matches on Windows will be expanded to their 69 full resolved UNC maths, eg instead of 'C:\\foo\\bar', 70 it will expand to '//?/C:/foo/bar'. 71 `, 72 }, 73 follow: { 74 short: 'f', 75 description: `Follow symlinked directories when expanding '**'`, 76 }, 77 realpath: { 78 short: 'R', 79 description: `Call 'fs.realpath' on all of the results. In the case 80 of an entry that cannot be resolved, the entry is 81 omitted. This incurs a slight performance penalty, of 82 course, because of the added system calls.`, 83 }, 84 stat: { 85 short: 's', 86 description: `Call 'fs.lstat' on all entries, whether required or not 87 to determine if it's a valid match.`, 88 }, 89 'match-base': { 90 short: 'b', 91 description: `Perform a basename-only match if the pattern does not 92 contain any slash characters. That is, '*.js' would be 93 treated as equivalent to '**/*.js', matching js files 94 in all directories. 95 `, 96 }, 97 dot: { 98 description: `Allow patterns to match files/directories that start 99 with '.', even if the pattern does not start with '.' 100 `, 101 }, 102 nobrace: { 103 description: 'Do not expand {...} patterns', 104 }, 105 nocase: { 106 description: `Perform a case-insensitive match. This defaults to 107 'true' on macOS and Windows platforms, and false on 108 all others. 109 110 Note: 'nocase' should only be explicitly set when it is 111 known that the filesystem's case sensitivity differs 112 from the platform default. If set 'true' on 113 case-insensitive file systems, then the walk may return 114 more or less results than expected. 115 `, 116 }, 117 nodir: { 118 description: `Do not match directories, only files. 119 120 Note: to *only* match directories, append a '/' at the 121 end of the pattern. 122 `, 123 }, 124 noext: { 125 description: `Do not expand extglob patterns, such as '+(a|b)'`, 126 }, 127 noglobstar: { 128 description: `Do not expand '**' against multiple path portions. 129 Ie, treat it as a normal '*' instead.`, 130 }, 131 'windows-path-no-escape': { 132 description: `Use '\\' as a path separator *only*, and *never* as an 133 escape character. If set, all '\\' characters are 134 replaced with '/' in the pattern.`, 135 }, 136}) 137 .num({ 138 'max-depth': { 139 short: 'D', 140 description: `Maximum depth to traverse from the current 141 working directory`, 142 }, 143}) 144 .opt({ 145 cwd: { 146 short: 'C', 147 description: 'Current working directory to execute/match in', 148 default: process.cwd(), 149 }, 150 root: { 151 short: 'r', 152 description: `A string path resolved against the 'cwd', which is 153 used as the starting point for absolute patterns that 154 start with '/' (but not drive letters or UNC paths 155 on Windows). 156 157 Note that this *doesn't* necessarily limit the walk to 158 the 'root' directory, and doesn't affect the cwd 159 starting point for non-absolute patterns. A pattern 160 containing '..' will still be able to traverse out of 161 the root directory, if it is not an actual root directory 162 on the filesystem, and any non-absolute patterns will 163 still be matched in the 'cwd'. 164 165 To start absolute and non-absolute patterns in the same 166 path, you can use '--root=' to set it to the empty 167 string. However, be aware that on Windows systems, a 168 pattern like 'x:/*' or '//host/share/*' will *always* 169 start in the 'x:/' or '//host/share/' directory, 170 regardless of the --root setting. 171 `, 172 }, 173 platform: { 174 description: `Defaults to the value of 'process.platform' if 175 available, or 'linux' if not. Setting --platform=win32 176 on non-Windows systems may cause strange behavior!`, 177 validate: v => new Set([ 178 'aix', 179 'android', 180 'darwin', 181 'freebsd', 182 'haiku', 183 'linux', 184 'openbsd', 185 'sunos', 186 'win32', 187 'cygwin', 188 'netbsd', 189 ]).has(v), 190 }, 191}) 192 .optList({ 193 ignore: { 194 short: 'i', 195 description: `Glob patterns to ignore`, 196 }, 197}) 198 .flag({ 199 debug: { 200 short: 'v', 201 description: `Output a huge amount of noisy debug information about 202 patterns as they are parsed and used to match files.`, 203 }, 204}) 205 .flag({ 206 help: { 207 short: 'h', 208 description: 'Show this usage information', 209 }, 210}); 211try { 212 const { positionals, values } = j.parse(); 213 if (values.help) { 214 console.log(j.usage()); 215 process.exit(0); 216 } 217 if (positionals.length === 0) 218 throw 'No patterns provided'; 219 const patterns = values.all 220 ? positionals 221 : positionals.filter(p => !(0, fs_1.existsSync)(p)); 222 const matches = values.all ? [] : positionals.filter(p => (0, fs_1.existsSync)(p)); 223 const stream = (0, index_js_1.globStream)(patterns, { 224 absolute: values.absolute, 225 cwd: values.cwd, 226 dot: values.dot, 227 dotRelative: values['dot-relative'], 228 follow: values.follow, 229 ignore: values.ignore, 230 mark: values.mark, 231 matchBase: values['match-base'], 232 maxDepth: values['max-depth'], 233 nobrace: values.nobrace, 234 nocase: values.nocase, 235 nodir: values.nodir, 236 noext: values.noext, 237 noglobstar: values.noglobstar, 238 platform: values.platform, 239 realpath: values.realpath, 240 root: values.root, 241 stat: values.stat, 242 debug: values.debug, 243 posix: values.posix, 244 }); 245 const cmd = values.cmd; 246 if (!cmd) { 247 matches.forEach(m => console.log(m)); 248 stream.on('data', f => console.log(f)); 249 } 250 else { 251 stream.on('data', f => matches.push(f)); 252 stream.on('end', () => (0, foreground_child_1.foregroundChild)(cmd, matches, { shell: true })); 253 } 254} 255catch (e) { 256 console.error(j.usage()); 257 console.error(e instanceof Error ? e.message : String(e)); 258 process.exit(1); 259} 260//# sourceMappingURL=bin.js.map