2020-04-30 13:52:54 +02:00
|
|
|
import * as cp from "child_process"
|
|
|
|
import * as path from "path"
|
2021-06-23 22:57:16 +02:00
|
|
|
import { onLine } from "../../src/node/util"
|
2020-04-30 13:52:54 +02:00
|
|
|
|
|
|
|
async function main(): Promise<void> {
|
|
|
|
try {
|
|
|
|
const watcher = new Watcher()
|
|
|
|
await watcher.watch()
|
2021-09-30 05:14:56 +02:00
|
|
|
} catch (error: any) {
|
2020-04-30 13:52:54 +02:00
|
|
|
console.error(error.message)
|
|
|
|
process.exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Watcher {
|
|
|
|
private readonly rootPath = path.resolve(__dirname, "../..")
|
2021-09-08 21:05:49 +02:00
|
|
|
private readonly vscodeSourcePath = path.join(this.rootPath, "vendor/modules/code-oss-dev")
|
2020-04-30 13:52:54 +02:00
|
|
|
|
|
|
|
private static log(message: string, skipNewline = false): void {
|
|
|
|
process.stdout.write(message)
|
|
|
|
if (!skipNewline) {
|
|
|
|
process.stdout.write("\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async watch(): Promise<void> {
|
|
|
|
let server: cp.ChildProcess | undefined
|
|
|
|
const restartServer = (): void => {
|
|
|
|
if (server) {
|
|
|
|
server.kill()
|
|
|
|
}
|
|
|
|
const s = cp.fork(path.join(this.rootPath, "out/node/entry.js"), process.argv.slice(2))
|
|
|
|
console.log(`[server] spawned process ${s.pid}`)
|
|
|
|
s.on("exit", () => console.log(`[server] process ${s.pid} exited`))
|
|
|
|
server = s
|
|
|
|
}
|
|
|
|
|
|
|
|
const vscode = cp.spawn("yarn", ["watch"], { cwd: this.vscodeSourcePath })
|
2021-09-30 05:14:56 +02:00
|
|
|
|
|
|
|
const vscodeWebExtensions = cp.spawn("yarn", ["watch-web"], { cwd: this.vscodeSourcePath })
|
|
|
|
|
2020-04-30 13:52:54 +02:00
|
|
|
const tsc = cp.spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath })
|
2020-08-18 19:03:49 +02:00
|
|
|
const plugin = process.env.PLUGIN_DIR
|
|
|
|
? cp.spawn("yarn", ["build", "--watch"], { cwd: process.env.PLUGIN_DIR })
|
|
|
|
: undefined
|
2020-04-30 13:52:54 +02:00
|
|
|
|
|
|
|
const cleanup = (code?: number | null): void => {
|
|
|
|
Watcher.log("killing vs code watcher")
|
|
|
|
vscode.removeAllListeners()
|
|
|
|
vscode.kill()
|
|
|
|
|
2021-09-30 05:14:56 +02:00
|
|
|
Watcher.log("killing vs code web extension watcher")
|
|
|
|
vscodeWebExtensions.removeAllListeners()
|
|
|
|
vscodeWebExtensions.kill()
|
|
|
|
|
2020-04-30 13:52:54 +02:00
|
|
|
Watcher.log("killing tsc")
|
|
|
|
tsc.removeAllListeners()
|
|
|
|
tsc.kill()
|
|
|
|
|
2020-08-18 19:03:49 +02:00
|
|
|
if (plugin) {
|
|
|
|
Watcher.log("killing plugin")
|
|
|
|
plugin.removeAllListeners()
|
|
|
|
plugin.kill()
|
|
|
|
}
|
2020-07-31 23:27:32 +02:00
|
|
|
|
2020-04-30 13:52:54 +02:00
|
|
|
if (server) {
|
|
|
|
Watcher.log("killing server")
|
|
|
|
server.removeAllListeners()
|
|
|
|
server.kill()
|
|
|
|
}
|
|
|
|
|
2021-06-23 19:19:50 +02:00
|
|
|
Watcher.log("killing watch")
|
2020-04-30 13:52:54 +02:00
|
|
|
process.exit(code || 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
process.on("SIGINT", () => cleanup())
|
|
|
|
process.on("SIGTERM", () => cleanup())
|
|
|
|
|
|
|
|
vscode.on("exit", (code) => {
|
|
|
|
Watcher.log("vs code watcher terminated unexpectedly")
|
|
|
|
cleanup(code)
|
|
|
|
})
|
2021-09-30 05:14:56 +02:00
|
|
|
|
|
|
|
vscodeWebExtensions.on("exit", (code) => {
|
|
|
|
Watcher.log("vs code extension watcher terminated unexpectedly")
|
|
|
|
cleanup(code)
|
|
|
|
})
|
|
|
|
|
2020-04-30 13:52:54 +02:00
|
|
|
tsc.on("exit", (code) => {
|
|
|
|
Watcher.log("tsc terminated unexpectedly")
|
|
|
|
cleanup(code)
|
|
|
|
})
|
2021-09-30 05:14:56 +02:00
|
|
|
|
2020-08-18 19:03:49 +02:00
|
|
|
if (plugin) {
|
|
|
|
plugin.on("exit", (code) => {
|
|
|
|
Watcher.log("plugin terminated unexpectedly")
|
|
|
|
cleanup(code)
|
|
|
|
})
|
|
|
|
}
|
2020-04-30 13:52:54 +02:00
|
|
|
|
2021-09-30 05:14:56 +02:00
|
|
|
vscodeWebExtensions.stderr.on("data", (d) => process.stderr.write(d))
|
2020-04-30 13:52:54 +02:00
|
|
|
vscode.stderr.on("data", (d) => process.stderr.write(d))
|
|
|
|
tsc.stderr.on("data", (d) => process.stderr.write(d))
|
2021-09-30 05:14:56 +02:00
|
|
|
|
2020-08-18 19:03:49 +02:00
|
|
|
if (plugin) {
|
|
|
|
plugin.stderr.on("data", (d) => process.stderr.write(d))
|
|
|
|
}
|
2020-04-30 13:52:54 +02:00
|
|
|
|
|
|
|
let startingVscode = false
|
|
|
|
let startedVscode = false
|
|
|
|
onLine(vscode, (line, original) => {
|
|
|
|
console.log("[vscode]", original)
|
|
|
|
// Wait for watch-client since "Finished compilation" will appear multiple
|
|
|
|
// times before the client starts building.
|
|
|
|
if (!startingVscode && line.includes("Starting watch-client")) {
|
|
|
|
startingVscode = true
|
|
|
|
} else if (startingVscode && line.includes("Finished compilation")) {
|
|
|
|
if (startedVscode) {
|
2021-06-23 19:19:50 +02:00
|
|
|
restartServer()
|
2020-04-30 13:52:54 +02:00
|
|
|
}
|
|
|
|
startedVscode = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
onLine(tsc, (line, original) => {
|
|
|
|
// tsc outputs blank lines; skip them.
|
|
|
|
if (line !== "") {
|
|
|
|
console.log("[tsc]", original)
|
|
|
|
}
|
|
|
|
if (line.includes("Watching for file changes")) {
|
2021-06-23 19:19:50 +02:00
|
|
|
restartServer()
|
2020-04-30 13:52:54 +02:00
|
|
|
}
|
|
|
|
})
|
2020-07-31 23:27:32 +02:00
|
|
|
|
2020-08-18 19:03:49 +02:00
|
|
|
if (plugin) {
|
|
|
|
onLine(plugin, (line, original) => {
|
|
|
|
// tsc outputs blank lines; skip them.
|
|
|
|
if (line !== "") {
|
|
|
|
console.log("[plugin]", original)
|
|
|
|
}
|
|
|
|
if (line.includes("Watching for file changes")) {
|
2021-06-23 19:19:50 +02:00
|
|
|
restartServer()
|
2020-08-18 19:03:49 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2020-04-30 13:52:54 +02:00
|
|
|
}
|
2021-06-23 19:19:50 +02:00
|
|
|
}
|
2020-04-30 13:52:54 +02:00
|
|
|
|
|
|
|
main()
|