From 964ebe8d0a0d57bf702b1e77a5a32dbc48bbf366 Mon Sep 17 00:00:00 2001 From: Asher Date: Mon, 15 Mar 2021 16:15:24 -0500 Subject: [PATCH] Replace fs-extra with fs.promises Remove the Mac directory copy instead of refactoring it since we've had this for a long time now and I think it's safe to assume that users running code-server on Mac don't have the old directory anymore. --- package.json | 2 -- src/node/cli.ts | 35 ++++++++++++++--------------------- src/node/settings.ts | 2 +- src/node/socket.ts | 4 ++-- src/node/util.ts | 12 ++++++++---- test/unit/cli.test.ts | 8 ++++---- test/unit/socket.test.ts | 10 +++++----- test/unit/update.test.ts | 6 +++--- yarn.lock | 36 ------------------------------------ 9 files changed, 37 insertions(+), 78 deletions(-) diff --git a/package.json b/package.json index 84a4c247..82871da7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "@types/compression": "^1.7.0", "@types/cookie-parser": "^1.4.2", "@types/express": "^4.17.8", - "@types/fs-extra": "^8.0.1", "@types/http-proxy": "^1.17.4", "@types/js-yaml": "^3.12.3", "@types/node": "^12.12.7", @@ -83,7 +82,6 @@ "cookie-parser": "^1.4.5", "env-paths": "^2.2.0", "express": "^5.0.0-alpha.8", - "fs-extra": "^9.0.1", "http-proxy": "^1.18.0", "httpolyglot": "^0.1.2", "js-yaml": "^3.13.1", diff --git a/src/node/cli.ts b/src/node/cli.ts index 0990797d..139391ab 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -1,5 +1,5 @@ import { field, Level, logger } from "@coder/logger" -import * as fs from "fs-extra" +import { promises as fs } from "fs" import yaml from "js-yaml" import * as os from "os" import * as path from "path" @@ -385,7 +385,6 @@ export async function setDefaults(cliArgs: Args, configArgs?: ConfigArgs): Promi const args = Object.assign({}, configArgs || {}, cliArgs) if (!args["user-data-dir"]) { - await copyOldMacOSDataDir() args["user-data-dir"] = paths.data } @@ -510,13 +509,22 @@ export async function readConfigFile(configPath?: string): Promise { } } - if (!(await fs.pathExists(configPath))) { - await fs.outputFile(configPath, await defaultConfigFile()) + await fs.mkdir(path.dirname(configPath), { recursive: true }) + + try { + await fs.writeFile(configPath, await defaultConfigFile(), { + flag: "wx", // wx means to fail if the path exists. + }) logger.info(`Wrote default config file to ${humanPath(configPath)}`) + } catch (error) { + // EEXIST is fine; we don't want to overwrite existing configurations. + if (error.code !== "EEXIST") { + throw error + } } - const configFile = await fs.readFile(configPath) - return parseConfigFile(configFile.toString(), configPath) + const configFile = await fs.readFile(configPath, "utf8") + return parseConfigFile(configFile, configPath) } /** @@ -599,21 +607,6 @@ function bindAddrFromAllSources(...argsConfig: Args[]): Addr { return addr } -async function copyOldMacOSDataDir(): Promise { - 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) - } -} - export const shouldRunVsCodeCli = (args: Args): boolean => { return !!args["list-extensions"] || !!args["install-extension"] || !!args["uninstall-extension"] } diff --git a/src/node/settings.ts b/src/node/settings.ts index 5f9427aa..ee955aad 100644 --- a/src/node/settings.ts +++ b/src/node/settings.ts @@ -1,6 +1,6 @@ import { logger } from "@coder/logger" import { Query } from "express-serve-static-core" -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as path from "path" import { paths } from "./util" diff --git a/src/node/socket.ts b/src/node/socket.ts index ada02483..5885f7fd 100644 --- a/src/node/socket.ts +++ b/src/node/socket.ts @@ -1,4 +1,4 @@ -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as net from "net" import * as path from "path" import * as tls from "tls" @@ -75,7 +75,7 @@ export class SocketProxyProvider { this._proxyServer = this.findFreeSocketPath(this.proxyPipe) .then((pipe) => { this.proxyPipe = pipe - return Promise.all([fs.mkdirp(tmpdir), fs.remove(this.proxyPipe)]) + return Promise.all([fs.mkdir(tmpdir, { recursive: true }), fs.rmdir(this.proxyPipe, { recursive: true })]) }) .then(() => { return new Promise((resolve) => { diff --git a/src/node/util.ts b/src/node/util.ts index 7c460958..e8ec311e 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -1,7 +1,7 @@ import * as cp from "child_process" import * as crypto from "crypto" import envPaths from "env-paths" -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as net from "net" import * as os from "os" import * as path from "path" @@ -58,8 +58,11 @@ export const generateCertificate = async (hostname: string): Promise<{ cert: str const certPath = path.join(paths.data, `${hostname.replace(/\./g, "_")}.crt`) const certKeyPath = path.join(paths.data, `${hostname.replace(/\./g, "_")}.key`) - const checks = await Promise.all([fs.pathExists(certPath), fs.pathExists(certKeyPath)]) - if (!checks[0] || !checks[1]) { + // Try generating the certificates if we can't access them (which probably + // means they don't exist). + try { + await Promise.all([fs.access(certPath), fs.access(certKeyPath)]) + } catch (error) { // Require on demand so openssl isn't required if you aren't going to // generate certificates. const pem = require("pem") as typeof import("pem") @@ -86,9 +89,10 @@ DNS.1 = ${hostname} }, ) }) - await fs.mkdirp(paths.data) + await fs.mkdir(paths.data, { recursive: true }) await Promise.all([fs.writeFile(certPath, certs.certificate), fs.writeFile(certKeyPath, certs.serviceKey)]) } + return { cert: certPath, certKey: certKeyPath, diff --git a/test/unit/cli.test.ts b/test/unit/cli.test.ts index 531dd434..a8374bd7 100644 --- a/test/unit/cli.test.ts +++ b/test/unit/cli.test.ts @@ -1,5 +1,5 @@ import { Level, logger } from "@coder/logger" -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as net from "net" import * as os from "os" import * as path from "path" @@ -339,14 +339,14 @@ describe("cli", () => { const vscodeIpcPath = path.join(os.tmpdir(), "vscode-ipc") beforeAll(async () => { - await fs.remove(testDir) - await fs.mkdirp(testDir) + await fs.rmdir(testDir, { recursive: true }) + await fs.mkdir(testDir, { recursive: true }) }) beforeEach(async () => { delete process.env.VSCODE_IPC_HOOK_CLI args = { _: [] } - await fs.remove(vscodeIpcPath) + await fs.rmdir(vscodeIpcPath, { recursive: true }) }) it("should use existing if inside code-server", async () => { diff --git a/test/unit/socket.test.ts b/test/unit/socket.test.ts index 01177127..4fedf5a8 100644 --- a/test/unit/socket.test.ts +++ b/test/unit/socket.test.ts @@ -1,5 +1,5 @@ import { field, logger } from "@coder/logger" -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as net from "net" import * as path from "path" import * as tls from "tls" @@ -45,14 +45,14 @@ describe("SocketProxyProvider", () => { beforeAll(async () => { const cert = await generateCertificate("localhost") const options = { - cert: fs.readFileSync(cert.cert), - key: fs.readFileSync(cert.certKey), + cert: await fs.readFile(cert.cert), + key: await fs.readFile(cert.certKey), rejectUnauthorized: false, } - await fs.mkdirp(path.join(tmpdir, "tests")) + await fs.mkdir(path.join(tmpdir, "tests"), { recursive: true }) const socketPath = await provider.findFreeSocketPath(path.join(tmpdir, "tests/tls-socket-proxy")) - await fs.remove(socketPath) + await fs.rmdir(socketPath, { recursive: true }) return new Promise((_resolve) => { const resolved: { [key: string]: boolean } = { client: false, server: false } diff --git a/test/unit/update.test.ts b/test/unit/update.test.ts index 0f5d55a6..2f73f80d 100644 --- a/test/unit/update.test.ts +++ b/test/unit/update.test.ts @@ -1,4 +1,4 @@ -import * as fs from "fs-extra" +import { promises as fs } from "fs" import * as http from "http" import * as path from "path" import { SettingsProvider, UpdateSettings } from "../../src/node/settings" @@ -53,8 +53,8 @@ describe.skip("update", () => { host: "localhost", }) }) - await fs.remove(path.join(tmpdir, "tests/updates")) - await fs.mkdirp(path.join(tmpdir, "tests/updates")) + await fs.rmdir(path.join(tmpdir, "tests/updates"), { recursive: true }) + await fs.mkdir(path.join(tmpdir, "tests/updates"), { recursive: true }) }) afterAll(() => { diff --git a/yarn.lock b/yarn.lock index 3b6246e3..f6de23be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1197,13 +1197,6 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/fs-extra@^8.0.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.1.tgz#1e49f22d09aa46e19b51c0b013cb63d0d923a068" - integrity sha512-TcUlBem321DFQzBNuz8p0CLLKp0VvF/XH9E4KHNmgwyp4E3AfgI5cjiIVZWlbfThBop2qxFIh4+LeY6hVWWZ2w== - dependencies: - "@types/node" "*" - "@types/http-proxy@^1.17.4": version "1.17.5" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.5.tgz#c203c5e6e9dc6820d27a40eb1e511c70a220423d" @@ -1721,11 +1714,6 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -at-least-node@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" - integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== - atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -3726,16 +3714,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" - integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== - dependencies: - at-least-node "^1.0.0" - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^1.0.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -4730,15 +4708,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" - integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== - dependencies: - universalify "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -7966,11 +7935,6 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" - integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== - unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"