|
| 1 | +import * as child_process from "child_process"; |
| 2 | +import * as path from "path"; |
| 3 | +import * as fs from "fs"; |
| 4 | + |
| 5 | +function commonDir(paths: string[]): string { |
| 6 | + if (paths.length === 0) return ""; |
| 7 | + const splitPaths = paths.map(p => p.split(path.sep)); |
| 8 | + let i; |
| 9 | + for (i = 0; i < splitPaths[0].length; i++) { |
| 10 | + if (!splitPaths.every(parts => parts[i] === splitPaths[0][i])) { |
| 11 | + break; |
| 12 | + } |
| 13 | + } |
| 14 | + const commonParts = splitPaths[0].slice(0, i); |
| 15 | + let ret = commonParts.join(path.sep); |
| 16 | + if (!fs.existsSync(ret)) { |
| 17 | + throw new Error(`Common directory does not exist: ${ret}`); |
| 18 | + } |
| 19 | + if (!fs.lstatSync(ret).isDirectory()) { |
| 20 | + ret = path.dirname(ret); |
| 21 | + } |
| 22 | + return ret; |
| 23 | +} |
| 24 | + |
| 25 | +function forwardCommand(args: string[]): number { |
| 26 | + // Avoid infinite recursion |
| 27 | + if (args.length == 0) { |
| 28 | + console.error("No command provided"); |
| 29 | + return 1; |
| 30 | + } |
| 31 | + const cmd = args[0]; |
| 32 | + const envVariable = `__JUST_FORWARD_${cmd}`; |
| 33 | + if (process.env[envVariable]) { |
| 34 | + console.error(`No common ${cmd} handler found`); |
| 35 | + return 1; |
| 36 | + } |
| 37 | + process.env[envVariable] = "true"; |
| 38 | + const cmdArgs = args.slice(1); |
| 39 | + const is_flag = /^(-.*|\++)$/; // + is used for testing level in some langauge tests |
| 40 | + const flags = cmdArgs.filter(arg => is_flag.test(arg)); |
| 41 | + const positionalArgs = cmdArgs.filter(arg => !is_flag.test(arg)); |
| 42 | + |
| 43 | + if (positionalArgs.length === 0) { |
| 44 | + console.error("No positional arguments provided"); |
| 45 | + return 1; |
| 46 | + } |
| 47 | + |
| 48 | + const commonPath = commonDir(positionalArgs); |
| 49 | + let relativeArgs = positionalArgs.map(arg => path.relative(commonPath, arg) || "."); |
| 50 | + if (relativeArgs.length === 1 && relativeArgs[0] === ".") { |
| 51 | + relativeArgs = []; |
| 52 | + } |
| 53 | + |
| 54 | + const invocation = [process.env["JUST_EXECUTABLE"] || "just", cmd, ...flags, ...relativeArgs]; |
| 55 | + console.log(`-> ${commonPath}: just ${invocation.slice(1).join(" ")}`); |
| 56 | + try { |
| 57 | + child_process.execFileSync(invocation[0], invocation.slice(1), { stdio: "inherit", cwd: commonPath }); |
| 58 | + } catch (error) { |
| 59 | + return 1; |
| 60 | + } |
| 61 | + return 0; |
| 62 | +} |
| 63 | + |
| 64 | +process.exit(forwardCommand(process.argv.slice(2))); |
0 commit comments