Move start path logic out of patch and fix it
This commit is contained in:
27
src/node/cli.ts
Normal file
27
src/node/cli.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { AuthType } from "./http"
|
||||
import { Args as VsArgs } from "../../lib/vscode/src/vs/server/ipc"
|
||||
|
||||
export interface Args extends VsArgs {
|
||||
auth?: AuthType
|
||||
"base-path"?: string
|
||||
cert?: string
|
||||
"cert-key"?: string
|
||||
format?: string
|
||||
host?: string
|
||||
json?: boolean
|
||||
open?: boolean
|
||||
port?: string
|
||||
socket?: string
|
||||
version?: boolean
|
||||
_: string[]
|
||||
}
|
||||
|
||||
// TODO: Implement proper CLI parser.
|
||||
export const parse = (): Args => {
|
||||
const last = process.argv[process.argv.length - 1]
|
||||
return {
|
||||
version: process.argv.includes("--version"),
|
||||
json: process.argv.includes("--json"),
|
||||
_: last && !last.startsWith("-") ? [last] : [],
|
||||
}
|
||||
}
|
@ -1,25 +1,13 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import { ApiHttpProvider } from "./api/server"
|
||||
import { MainHttpProvider } from "./app/server"
|
||||
import { Args, parse } from "./cli"
|
||||
import { AuthType, HttpServer } from "./http"
|
||||
import { generateCertificate, generatePassword, hash, open } from "./util"
|
||||
import { VscodeHttpProvider } from "./vscode/server"
|
||||
import { ipcMain, wrap } from "./wrapper"
|
||||
|
||||
export interface Args {
|
||||
auth?: AuthType
|
||||
"base-path"?: string
|
||||
cert?: string
|
||||
"cert-key"?: string
|
||||
format?: string
|
||||
host?: string
|
||||
open?: boolean
|
||||
port?: string
|
||||
socket?: string
|
||||
_?: string[]
|
||||
}
|
||||
|
||||
const main = async (args: Args = {}): Promise<void> => {
|
||||
const main = async (args: Args): Promise<void> => {
|
||||
const auth = args.auth || AuthType.Password
|
||||
const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword()))
|
||||
|
||||
@ -51,7 +39,7 @@ const main = async (args: Args = {}): Promise<void> => {
|
||||
const httpServer = new HttpServer(options)
|
||||
httpServer.registerHttpProvider("/", MainHttpProvider)
|
||||
httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer)
|
||||
httpServer.registerHttpProvider("/vscode-embed", VscodeHttpProvider, [])
|
||||
httpServer.registerHttpProvider("/vscode-embed", VscodeHttpProvider, args)
|
||||
|
||||
ipcMain().onDispose(() => httpServer.dispose())
|
||||
|
||||
@ -88,10 +76,10 @@ const main = async (args: Args = {}): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement CLI parser.
|
||||
if (process.argv.includes("--version")) {
|
||||
const args = parse()
|
||||
if (args.version) {
|
||||
const version = require("../../package.json").version
|
||||
if (process.argv.includes("--json")) {
|
||||
if (args.json) {
|
||||
console.log({
|
||||
codeServer: version,
|
||||
vscode: require("../../lib/vscode/package.json").version,
|
||||
@ -101,5 +89,5 @@ if (process.argv.includes("--version")) {
|
||||
}
|
||||
process.exit(0)
|
||||
} else {
|
||||
wrap(main)
|
||||
wrap(() => main(args))
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
<meta http-equiv="Content-Security-Policy" content="font-src 'self' fonts.gstatic.com; connect-src 'self'; default-src ws: wss: 'self'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; script-src 'self' 'unsafe-inline'; manifest-src 'self'; img-src 'self' data:;">
|
||||
<title>code-server</title>
|
||||
</head>
|
||||
<body>
|
||||
<body style="background-color:#272727;">
|
||||
<div id="root" style="color:#f4f4f4;padding:20px;max-width:700px;">
|
||||
{{ERROR}}
|
||||
</div>
|
||||
|
@ -1,22 +1,29 @@
|
||||
import { field, logger } from "@coder/logger"
|
||||
import * as cp from "child_process"
|
||||
import * as crypto from "crypto"
|
||||
import * as fs from "fs-extra"
|
||||
import * as http from "http"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
import * as url from "url"
|
||||
import {
|
||||
CodeServerMessage,
|
||||
Settings,
|
||||
StartPath,
|
||||
VscodeMessage,
|
||||
VscodeOptions,
|
||||
WorkbenchOptions,
|
||||
} from "../../../lib/vscode/src/vs/server/ipc"
|
||||
import { HttpCode, HttpError } from "../../common/http"
|
||||
import { generateUuid } from "../../common/util"
|
||||
import { Args } from "../cli"
|
||||
import { HttpProvider, HttpProviderOptions, HttpResponse, Route } from "../http"
|
||||
import { SettingsProvider } from "../settings"
|
||||
import { xdgLocalDir } from "../util"
|
||||
|
||||
export interface Settings {
|
||||
lastVisited: StartPath
|
||||
}
|
||||
|
||||
export class VscodeHttpProvider extends HttpProvider {
|
||||
private readonly serverRootPath: string
|
||||
private readonly vsRootPath: string
|
||||
@ -24,7 +31,7 @@ export class VscodeHttpProvider extends HttpProvider {
|
||||
private _vscode?: Promise<cp.ChildProcess>
|
||||
private workbenchOptions?: WorkbenchOptions
|
||||
|
||||
public constructor(options: HttpProviderOptions, private readonly args: string[]) {
|
||||
public constructor(options: HttpProviderOptions, private readonly args: Args) {
|
||||
super(options)
|
||||
this.vsRootPath = path.resolve(this.rootPath, "lib/vscode")
|
||||
this.serverRootPath = path.join(this.vsRootPath, "out/vs/server")
|
||||
@ -161,24 +168,26 @@ export class VscodeHttpProvider extends HttpProvider {
|
||||
|
||||
private async getRoot(request: http.IncomingMessage, route: Route): Promise<HttpResponse> {
|
||||
const settings = await this.settings.read()
|
||||
const startPath = await this.getFirstValidPath([
|
||||
{ url: route.query.workspace, workspace: true },
|
||||
{ url: route.query.folder, workspace: false },
|
||||
settings.lastVisited,
|
||||
this.args._ && this.args._.length > 0 ? { url: this.urlify(this.args._[0]) } : undefined,
|
||||
])
|
||||
const [response, options] = await Promise.all([
|
||||
await this.getUtf8Resource(this.rootPath, `src/node/vscode/workbench${!this.isDev ? "-build" : ""}.html`),
|
||||
this.initialize({
|
||||
args: this.args,
|
||||
query: route.query,
|
||||
remoteAuthority: request.headers.host as string,
|
||||
settings,
|
||||
startPath,
|
||||
}),
|
||||
])
|
||||
|
||||
this.workbenchOptions = options
|
||||
|
||||
if (options.startPath) {
|
||||
if (startPath) {
|
||||
this.settings.write({
|
||||
lastVisited: {
|
||||
path: options.startPath.path,
|
||||
workspace: options.startPath.workspace,
|
||||
},
|
||||
lastVisited: startPath,
|
||||
})
|
||||
}
|
||||
|
||||
@ -201,4 +210,40 @@ export class VscodeHttpProvider extends HttpProvider {
|
||||
response.content = response.content.replace(/{{COMMIT}}/g, this.options.commit).replace(/{{ERROR}}/g, message)
|
||||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the first valid path. If `workspace` is undefined then either a
|
||||
* workspace or a directory are acceptable. Otherwise it must be a file if a
|
||||
* workspace or a directory otherwise.
|
||||
*/
|
||||
private async getFirstValidPath(
|
||||
startPaths: Array<{ url?: string | string[]; workspace?: boolean } | undefined>
|
||||
): Promise<StartPath | undefined> {
|
||||
for (let i = 0; i < startPaths.length; ++i) {
|
||||
const startPath = startPaths[i]
|
||||
if (!startPath) {
|
||||
continue
|
||||
}
|
||||
const paths = typeof startPath.url === "string" ? [startPath.url] : startPath.url || []
|
||||
for (let j = 0; j < paths.length; ++j) {
|
||||
const u = url.parse(paths[j])
|
||||
try {
|
||||
if (!u.pathname) {
|
||||
throw new Error(`${paths[j]} is not a valid URL`)
|
||||
}
|
||||
const stat = await fs.stat(u.pathname)
|
||||
if (typeof startPath.workspace === "undefined" || startPath.workspace !== stat.isDirectory()) {
|
||||
return { url: u.href, workspace: !stat.isDirectory() }
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
private urlify(p: string): string {
|
||||
return "vscode-remote://host" + path.resolve(p)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user