Copy old macOS data directory if applicable
This commit is contained in:
parent
f475767c2b
commit
5651201643
@ -1,6 +1,7 @@
|
||||
import { field, Level, logger } from "@coder/logger"
|
||||
import * as fs from "fs-extra"
|
||||
import yaml from "js-yaml"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc"
|
||||
import { AuthType } from "./http"
|
||||
@ -151,12 +152,12 @@ export const optionDescriptions = (): string[] => {
|
||||
)
|
||||
}
|
||||
|
||||
export const parse = (
|
||||
export const parse = async (
|
||||
argv: string[],
|
||||
opts?: {
|
||||
configFile: string
|
||||
},
|
||||
): Args => {
|
||||
): Promise<Args> => {
|
||||
const error = (msg: string): Error => {
|
||||
if (opts?.configFile) {
|
||||
msg = `error reading ${opts.configFile}: ${msg}`
|
||||
@ -300,6 +301,7 @@ export const parse = (
|
||||
}
|
||||
|
||||
if (!args["user-data-dir"]) {
|
||||
await copyOldMacOSDataDir()
|
||||
args["user-data-dir"] = paths.data
|
||||
}
|
||||
|
||||
@ -351,7 +353,7 @@ export async function readConfigFile(configPath?: string): Promise<Args> {
|
||||
}
|
||||
return `--${optName}=${opt}`
|
||||
})
|
||||
const args = parse(configFileArgv, {
|
||||
const args = await parse(configFileArgv, {
|
||||
configFile: configPath,
|
||||
})
|
||||
return {
|
||||
@ -400,3 +402,18 @@ export function bindAddrFromAllSources(cliArgs: Args, configArgs: Args): [string
|
||||
|
||||
return [addr.host, addr.port]
|
||||
}
|
||||
|
||||
async function copyOldMacOSDataDir(): Promise<void> {
|
||||
if (os.platform() !== "darwin") {
|
||||
return
|
||||
}
|
||||
if (await fs.pathExists(paths.data)) {
|
||||
return
|
||||
}
|
||||
|
||||
// If the old data directory exists, we copy it in.
|
||||
const oldDataDir = path.join(os.homedir(), "Library/Application Support", "code-server")
|
||||
if (await fs.pathExists(oldDataDir)) {
|
||||
await fs.copy(oldDataDir, paths.data)
|
||||
}
|
||||
}
|
||||
|
@ -125,58 +125,62 @@ const main = async (cliArgs: Args): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
const tryParse = (): Args => {
|
||||
try {
|
||||
return parse(process.argv.slice(2))
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
process.exit(1)
|
||||
async function entry(): Promise<void> {
|
||||
const tryParse = async (): Promise<Args> => {
|
||||
try {
|
||||
return await parse(process.argv.slice(2))
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const args = await tryParse()
|
||||
if (args.help) {
|
||||
console.log("code-server", version, commit)
|
||||
console.log("")
|
||||
console.log(`Usage: code-server [options] [path]`)
|
||||
console.log("")
|
||||
console.log("Options")
|
||||
optionDescriptions().forEach((description) => {
|
||||
console.log("", description)
|
||||
})
|
||||
} else if (args.version) {
|
||||
if (args.json) {
|
||||
console.log({
|
||||
codeServer: version,
|
||||
commit,
|
||||
vscode: require("../../lib/vscode/package.json").version,
|
||||
})
|
||||
} else {
|
||||
console.log(version, commit)
|
||||
}
|
||||
process.exit(0)
|
||||
} else if (args["list-extensions"] || args["install-extension"] || args["uninstall-extension"]) {
|
||||
logger.debug("forking vs code cli...")
|
||||
const vscode = cp.fork(path.resolve(__dirname, "../../lib/vscode/out/vs/server/fork"), [], {
|
||||
env: {
|
||||
...process.env,
|
||||
CODE_SERVER_PARENT_PID: process.pid.toString(),
|
||||
},
|
||||
})
|
||||
vscode.once("message", (message) => {
|
||||
logger.debug("Got message from VS Code", field("message", message))
|
||||
if (message.type !== "ready") {
|
||||
logger.error("Unexpected response waiting for ready response")
|
||||
process.exit(1)
|
||||
}
|
||||
const send: CliMessage = { type: "cli", args }
|
||||
vscode.send(send)
|
||||
})
|
||||
vscode.once("error", (error) => {
|
||||
logger.error(error.message)
|
||||
process.exit(1)
|
||||
})
|
||||
vscode.on("exit", (code) => process.exit(code || 0))
|
||||
} else {
|
||||
wrap(() => main(args))
|
||||
}
|
||||
}
|
||||
|
||||
const args = tryParse()
|
||||
if (args.help) {
|
||||
console.log("code-server", version, commit)
|
||||
console.log("")
|
||||
console.log(`Usage: code-server [options] [path]`)
|
||||
console.log("")
|
||||
console.log("Options")
|
||||
optionDescriptions().forEach((description) => {
|
||||
console.log("", description)
|
||||
})
|
||||
} else if (args.version) {
|
||||
if (args.json) {
|
||||
console.log({
|
||||
codeServer: version,
|
||||
commit,
|
||||
vscode: require("../../lib/vscode/package.json").version,
|
||||
})
|
||||
} else {
|
||||
console.log(version, commit)
|
||||
}
|
||||
process.exit(0)
|
||||
} else if (args["list-extensions"] || args["install-extension"] || args["uninstall-extension"]) {
|
||||
logger.debug("forking vs code cli...")
|
||||
const vscode = cp.fork(path.resolve(__dirname, "../../lib/vscode/out/vs/server/fork"), [], {
|
||||
env: {
|
||||
...process.env,
|
||||
CODE_SERVER_PARENT_PID: process.pid.toString(),
|
||||
},
|
||||
})
|
||||
vscode.once("message", (message) => {
|
||||
logger.debug("Got message from VS Code", field("message", message))
|
||||
if (message.type !== "ready") {
|
||||
logger.error("Unexpected response waiting for ready response")
|
||||
process.exit(1)
|
||||
}
|
||||
const send: CliMessage = { type: "cli", args }
|
||||
vscode.send(send)
|
||||
})
|
||||
vscode.once("error", (error) => {
|
||||
logger.error(error.message)
|
||||
process.exit(1)
|
||||
})
|
||||
vscode.on("exit", (code) => process.exit(code || 0))
|
||||
} else {
|
||||
wrap(() => main(args))
|
||||
}
|
||||
entry()
|
||||
|
@ -16,13 +16,13 @@ describe("cli", () => {
|
||||
"user-data-dir": paths.data,
|
||||
}
|
||||
|
||||
it("should set defaults", () => {
|
||||
assert.deepEqual(parse([]), defaults)
|
||||
it("should set defaults", async () => {
|
||||
assert.deepEqual(await await parse([]), defaults)
|
||||
})
|
||||
|
||||
it("should parse all available options", () => {
|
||||
it("should parse all available options", async () => {
|
||||
assert.deepEqual(
|
||||
parse([
|
||||
await await parse([
|
||||
"--bind-addr=192.169.0.1:8080",
|
||||
"--auth",
|
||||
"none",
|
||||
@ -84,8 +84,8 @@ describe("cli", () => {
|
||||
)
|
||||
})
|
||||
|
||||
it("should work with short options", () => {
|
||||
assert.deepEqual(parse(["-vvv", "-v"]), {
|
||||
it("should work with short options", async () => {
|
||||
assert.deepEqual(await parse(["-vvv", "-v"]), {
|
||||
...defaults,
|
||||
log: "trace",
|
||||
verbose: true,
|
||||
@ -95,9 +95,9 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Trace)
|
||||
})
|
||||
|
||||
it("should use log level env var", () => {
|
||||
it("should use log level env var", async () => {
|
||||
process.env.LOG_LEVEL = "debug"
|
||||
assert.deepEqual(parse([]), {
|
||||
assert.deepEqual(await parse([]), {
|
||||
...defaults,
|
||||
log: "debug",
|
||||
})
|
||||
@ -105,7 +105,7 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Debug)
|
||||
|
||||
process.env.LOG_LEVEL = "trace"
|
||||
assert.deepEqual(parse([]), {
|
||||
assert.deepEqual(await parse([]), {
|
||||
...defaults,
|
||||
log: "trace",
|
||||
verbose: true,
|
||||
@ -114,9 +114,9 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Trace)
|
||||
})
|
||||
|
||||
it("should prefer --log to env var and --verbose to --log", () => {
|
||||
it("should prefer --log to env var and --verbose to --log", async () => {
|
||||
process.env.LOG_LEVEL = "debug"
|
||||
assert.deepEqual(parse(["--log", "info"]), {
|
||||
assert.deepEqual(await parse(["--log", "info"]), {
|
||||
...defaults,
|
||||
log: "info",
|
||||
})
|
||||
@ -124,7 +124,7 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Info)
|
||||
|
||||
process.env.LOG_LEVEL = "trace"
|
||||
assert.deepEqual(parse(["--log", "info"]), {
|
||||
assert.deepEqual(await parse(["--log", "info"]), {
|
||||
...defaults,
|
||||
log: "info",
|
||||
})
|
||||
@ -132,7 +132,7 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Info)
|
||||
|
||||
process.env.LOG_LEVEL = "warn"
|
||||
assert.deepEqual(parse(["--log", "info", "--verbose"]), {
|
||||
assert.deepEqual(await parse(["--log", "info", "--verbose"]), {
|
||||
...defaults,
|
||||
log: "trace",
|
||||
verbose: true,
|
||||
@ -141,31 +141,34 @@ describe("cli", () => {
|
||||
assert.equal(logger.level, Level.Trace)
|
||||
})
|
||||
|
||||
it("should ignore invalid log level env var", () => {
|
||||
it("should ignore invalid log level env var", async () => {
|
||||
process.env.LOG_LEVEL = "bogus"
|
||||
assert.deepEqual(parse([]), defaults)
|
||||
assert.deepEqual(await parse([]), defaults)
|
||||
})
|
||||
|
||||
it("should error if value isn't provided", () => {
|
||||
assert.throws(() => parse(["--auth"]), /--auth requires a value/)
|
||||
assert.throws(() => parse(["--auth=", "--log=debug"]), /--auth requires a value/)
|
||||
assert.throws(() => parse(["--auth", "--log"]), /--auth requires a value/)
|
||||
assert.throws(() => parse(["--auth", "--invalid"]), /--auth requires a value/)
|
||||
assert.throws(() => parse(["--bind-addr"]), /--bind-addr requires a value/)
|
||||
it("should error if value isn't provided", async () => {
|
||||
await assert.rejects(async () => await parse(["--auth"]), /--auth requires a value/)
|
||||
await assert.rejects(async () => await parse(["--auth=", "--log=debug"]), /--auth requires a value/)
|
||||
await assert.rejects(async () => await parse(["--auth", "--log"]), /--auth requires a value/)
|
||||
await assert.rejects(async () => await parse(["--auth", "--invalid"]), /--auth requires a value/)
|
||||
await assert.rejects(async () => await parse(["--bind-addr"]), /--bind-addr requires a value/)
|
||||
})
|
||||
|
||||
it("should error if value is invalid", () => {
|
||||
assert.throws(() => parse(["--port", "foo"]), /--port must be a number/)
|
||||
assert.throws(() => parse(["--auth", "invalid"]), /--auth valid values: \[password, none\]/)
|
||||
assert.throws(() => parse(["--log", "invalid"]), /--log valid values: \[trace, debug, info, warn, error\]/)
|
||||
it("should error if value is invalid", async () => {
|
||||
await assert.rejects(async () => await parse(["--port", "foo"]), /--port must be a number/)
|
||||
await assert.rejects(async () => await parse(["--auth", "invalid"]), /--auth valid values: \[password, none\]/)
|
||||
await assert.rejects(
|
||||
async () => await parse(["--log", "invalid"]),
|
||||
/--log valid values: \[trace, debug, info, warn, error\]/,
|
||||
)
|
||||
})
|
||||
|
||||
it("should error if the option doesn't exist", () => {
|
||||
assert.throws(() => parse(["--foo"]), /Unknown option --foo/)
|
||||
it("should error if the option doesn't exist", async () => {
|
||||
await assert.rejects(async () => await parse(["--foo"]), /Unknown option --foo/)
|
||||
})
|
||||
|
||||
it("should not error if the value is optional", () => {
|
||||
assert.deepEqual(parse(["--cert"]), {
|
||||
it("should not error if the value is optional", async () => {
|
||||
assert.deepEqual(await parse(["--cert"]), {
|
||||
...defaults,
|
||||
cert: {
|
||||
value: undefined,
|
||||
@ -173,30 +176,33 @@ describe("cli", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("should not allow option-like values", () => {
|
||||
assert.throws(() => parse(["--socket", "--socket-path-value"]), /--socket requires a value/)
|
||||
it("should not allow option-like values", async () => {
|
||||
await assert.rejects(async () => await parse(["--socket", "--socket-path-value"]), /--socket requires a value/)
|
||||
// If you actually had a path like this you would do this instead:
|
||||
assert.deepEqual(parse(["--socket", "./--socket-path-value"]), {
|
||||
assert.deepEqual(await parse(["--socket", "./--socket-path-value"]), {
|
||||
...defaults,
|
||||
socket: path.resolve("--socket-path-value"),
|
||||
})
|
||||
assert.throws(() => parse(["--cert", "--socket-path-value"]), /Unknown option --socket-path-value/)
|
||||
await assert.rejects(
|
||||
async () => await parse(["--cert", "--socket-path-value"]),
|
||||
/Unknown option --socket-path-value/,
|
||||
)
|
||||
})
|
||||
|
||||
it("should allow positional arguments before options", () => {
|
||||
assert.deepEqual(parse(["foo", "test", "--auth", "none"]), {
|
||||
it("should allow positional arguments before options", async () => {
|
||||
assert.deepEqual(await parse(["foo", "test", "--auth", "none"]), {
|
||||
...defaults,
|
||||
_: ["foo", "test"],
|
||||
auth: "none",
|
||||
})
|
||||
})
|
||||
|
||||
it("should support repeatable flags", () => {
|
||||
assert.deepEqual(parse(["--proxy-domain", "*.coder.com"]), {
|
||||
it("should support repeatable flags", async () => {
|
||||
assert.deepEqual(await parse(["--proxy-domain", "*.coder.com"]), {
|
||||
...defaults,
|
||||
"proxy-domain": ["*.coder.com"],
|
||||
})
|
||||
assert.deepEqual(parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"]), {
|
||||
assert.deepEqual(await parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"]), {
|
||||
...defaults,
|
||||
"proxy-domain": ["*.coder.com", "test.com"],
|
||||
})
|
||||
|
Reference in New Issue
Block a user