From adc4463507860b7090c12105695e94f5aa7e0bfc Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 6 May 2021 16:27:04 -0700 Subject: [PATCH 1/5] docs: update pr template to say default branch --- .github/PULL_REQUEST_TEMPLATE/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index ee5819a5..cc6d2aa5 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -2,7 +2,7 @@ Please link to the issue this PR solves. If there is no existing issue, please first create one unless the fix is minor. -Please make sure the base of your PR is the master branch! +Please make sure the base of your PR is the default branch! --> ## Checklist From a57ee6982233b7e451a963d1ce3530f40bd7173a Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Mon, 10 May 2021 16:17:30 -0700 Subject: [PATCH 2/5] feat: add runtime to getEnvPaths --- src/node/util.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/node/util.ts b/src/node/util.ts index 380e32b9..2633d3d5 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -7,10 +7,12 @@ import * as os from "os" import * as path from "path" import * as util from "util" import xdgBasedir from "xdg-basedir" +import { tmpdir } from "./constants" interface Paths { data: string config: string + runtime: string } export const paths = getEnvPaths() @@ -20,12 +22,15 @@ export const paths = getEnvPaths() * On MacOS this function gets the standard XDG directories instead of using the native macOS * ones. Most CLIs do this as in practice only GUI apps use the standard macOS directories. */ -function getEnvPaths(): Paths { +export function getEnvPaths(): Paths { let paths: Paths if (process.platform === "win32") { - paths = envPaths("code-server", { - suffix: "", - }) + paths = { + ...envPaths("code-server", { + suffix: "", + }), + runtime: tmpdir, + } } else { if (xdgBasedir.data === undefined || xdgBasedir.config === undefined) { throw new Error("No home folder?") @@ -33,6 +38,7 @@ function getEnvPaths(): Paths { paths = { data: path.join(xdgBasedir.data, "code-server"), config: path.join(xdgBasedir.config, "code-server"), + runtime: xdgBasedir.runtime ? path.join(xdgBasedir.runtime, "code-server") : tmpdir, } } From 2a657ab9301abbe01e3f567ce184a7ad44b260b7 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Mon, 10 May 2021 16:17:43 -0700 Subject: [PATCH 3/5] feat: add tests for getEnvPaths --- test/unit/node/util.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/unit/node/util.test.ts diff --git a/test/unit/node/util.test.ts b/test/unit/node/util.test.ts new file mode 100644 index 00000000..e26add80 --- /dev/null +++ b/test/unit/node/util.test.ts @@ -0,0 +1,10 @@ +import { getEnvPaths } from "../../../src/node/util" + +describe("getEnvPaths", () => { + it("should return an object with the data, config and runtime path", () => { + const actualPaths = getEnvPaths() + expect(actualPaths.hasOwnProperty("data")).toBe(true) + expect(actualPaths.hasOwnProperty("config")).toBe(true) + expect(actualPaths.hasOwnProperty("runtime")).toBe(true) + }) +}) From d7f141529019b6a26127f73a8f4068663c629390 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Mon, 10 May 2021 16:18:03 -0700 Subject: [PATCH 4/5] refactor: use paths.runtime in socket proxyPipe --- src/node/socket.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/node/socket.ts b/src/node/socket.ts index 9c937bbb..39f23dfb 100644 --- a/src/node/socket.ts +++ b/src/node/socket.ts @@ -4,8 +4,7 @@ import * as path from "path" import * as tls from "tls" import { Emitter } from "../common/emitter" import { generateUuid } from "../common/util" -import { tmpdir } from "./constants" -import { canConnect } from "./util" +import { canConnect, paths } from "./util" /** * Provides a way to proxy a TLS socket. Can be used when you need to pass a @@ -13,7 +12,7 @@ import { canConnect } from "./util" */ export class SocketProxyProvider { private readonly onProxyConnect = new Emitter() - private proxyPipe = path.join(tmpdir, "tls-proxy") + private proxyPipe = path.join(paths.runtime, "tls-proxy") private _proxyServer?: Promise private readonly proxyTimeout = 5000 @@ -76,7 +75,10 @@ export class SocketProxyProvider { this._proxyServer = this.findFreeSocketPath(this.proxyPipe) .then((pipe) => { this.proxyPipe = pipe - return Promise.all([fs.mkdir(tmpdir, { recursive: true }), fs.rmdir(this.proxyPipe, { recursive: true })]) + return Promise.all([ + fs.mkdir(paths.runtime, { recursive: true }), + fs.rmdir(this.proxyPipe, { recursive: true }), + ]) }) .then(() => { return new Promise((resolve) => { From 46fe77d46400513ca3ee971a6e001f5cd275c7e8 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Mon, 10 May 2021 16:27:47 -0700 Subject: [PATCH 5/5] chore: update CHANGELOG --- CHANGELOG.md | 1 + src/node/socket.ts | 2 +- src/node/util.ts | 48 +++++++----- test/unit/node/util.test.ts | 151 ++++++++++++++++++++++++++++++++++-- 4 files changed, 173 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f723fc7b..12e3d507 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ VS Code v1.56 ### Development - chore: ignore updates to microsoft/playwright-github-action +- fix(socket): use xdgBasedir.runtime instead of tmp #3304 @jsjoeio ## 3.10.0 diff --git a/src/node/socket.ts b/src/node/socket.ts index 39f23dfb..1651046d 100644 --- a/src/node/socket.ts +++ b/src/node/socket.ts @@ -76,7 +76,7 @@ export class SocketProxyProvider { .then((pipe) => { this.proxyPipe = pipe return Promise.all([ - fs.mkdir(paths.runtime, { recursive: true }), + fs.mkdir(path.dirname(this.proxyPipe), { recursive: true }), fs.rmdir(this.proxyPipe, { recursive: true }), ]) }) diff --git a/src/node/util.ts b/src/node/util.ts index 2633d3d5..f1882471 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -7,9 +7,8 @@ import * as os from "os" import * as path from "path" import * as util from "util" import xdgBasedir from "xdg-basedir" -import { tmpdir } from "./constants" -interface Paths { +export interface Paths { data: string config: string runtime: string @@ -23,26 +22,33 @@ export const paths = getEnvPaths() * ones. Most CLIs do this as in practice only GUI apps use the standard macOS directories. */ export function getEnvPaths(): Paths { - let paths: Paths - if (process.platform === "win32") { - paths = { - ...envPaths("code-server", { - suffix: "", - }), - runtime: tmpdir, - } - } else { - if (xdgBasedir.data === undefined || xdgBasedir.config === undefined) { - throw new Error("No home folder?") - } - paths = { - data: path.join(xdgBasedir.data, "code-server"), - config: path.join(xdgBasedir.config, "code-server"), - runtime: xdgBasedir.runtime ? path.join(xdgBasedir.runtime, "code-server") : tmpdir, - } + const paths = envPaths("code-server", { suffix: "" }) + const append = (p: string): string => path.join(p, "code-server") + switch (process.platform) { + case "darwin": + return { + // envPaths uses native directories so force Darwin to use the XDG spec + // to align with other CLI tools. + data: xdgBasedir.data ? append(xdgBasedir.data) : paths.data, + config: xdgBasedir.config ? append(xdgBasedir.config) : paths.config, + // Fall back to temp if there is no runtime dir. + runtime: xdgBasedir.runtime ? append(xdgBasedir.runtime) : paths.temp, + } + case "win32": + return { + data: paths.data, + config: paths.config, + // Windows doesn't have a runtime dir. + runtime: paths.temp, + } + default: + return { + data: paths.data, + config: paths.config, + // Fall back to temp if there is no runtime dir. + runtime: xdgBasedir.runtime ? append(xdgBasedir.runtime) : paths.temp, + } } - - return paths } /** diff --git a/test/unit/node/util.test.ts b/test/unit/node/util.test.ts index e26add80..bb1884b9 100644 --- a/test/unit/node/util.test.ts +++ b/test/unit/node/util.test.ts @@ -1,10 +1,147 @@ -import { getEnvPaths } from "../../../src/node/util" - describe("getEnvPaths", () => { - it("should return an object with the data, config and runtime path", () => { - const actualPaths = getEnvPaths() - expect(actualPaths.hasOwnProperty("data")).toBe(true) - expect(actualPaths.hasOwnProperty("config")).toBe(true) - expect(actualPaths.hasOwnProperty("runtime")).toBe(true) + describe("on darwin", () => { + let ORIGINAL_PLATFORM = "" + + beforeAll(() => { + ORIGINAL_PLATFORM = process.platform + + Object.defineProperty(process, "platform", { + value: "darwin", + }) + }) + + beforeEach(() => { + jest.resetModules() + jest.mock("env-paths", () => { + return () => ({ + data: "/home/envPath/.local/share", + config: "/home/envPath/.config", + temp: "/tmp/envPath/runtime", + }) + }) + }) + + afterAll(() => { + // Restore old platform + + Object.defineProperty(process, "platform", { + value: ORIGINAL_PLATFORM, + }) + }) + + it("should return the env paths using xdgBasedir", () => { + jest.mock("xdg-basedir", () => ({ + data: "/home/usr/.local/share", + config: "/home/usr/.config", + runtime: "/tmp/runtime", + })) + const getEnvPaths = require("../../../src/node/util").getEnvPaths + const envPaths = getEnvPaths() + + expect(envPaths.data).toEqual("/home/usr/.local/share/code-server") + expect(envPaths.config).toEqual("/home/usr/.config/code-server") + expect(envPaths.runtime).toEqual("/tmp/runtime/code-server") + }) + + it("should return the env paths using envPaths when xdgBasedir is undefined", () => { + jest.mock("xdg-basedir", () => ({})) + const getEnvPaths = require("../../../src/node/util").getEnvPaths + const envPaths = getEnvPaths() + + expect(envPaths.data).toEqual("/home/envPath/.local/share") + expect(envPaths.config).toEqual("/home/envPath/.config") + expect(envPaths.runtime).toEqual("/tmp/envPath/runtime") + }) + }) + describe("on win32", () => { + let ORIGINAL_PLATFORM = "" + + beforeAll(() => { + ORIGINAL_PLATFORM = process.platform + + Object.defineProperty(process, "platform", { + value: "win32", + }) + }) + + beforeEach(() => { + jest.resetModules() + jest.mock("env-paths", () => { + return () => ({ + data: "/windows/envPath/.local/share", + config: "/windows/envPath/.config", + temp: "/tmp/envPath/runtime", + }) + }) + }) + + afterAll(() => { + // Restore old platform + + Object.defineProperty(process, "platform", { + value: ORIGINAL_PLATFORM, + }) + }) + + it("should return the env paths using envPaths", () => { + const getEnvPaths = require("../../../src/node/util").getEnvPaths + const envPaths = getEnvPaths() + + expect(envPaths.data).toEqual("/windows/envPath/.local/share") + expect(envPaths.config).toEqual("/windows/envPath/.config") + expect(envPaths.runtime).toEqual("/tmp/envPath/runtime") + }) + }) + describe("on other platforms", () => { + let ORIGINAL_PLATFORM = "" + + beforeAll(() => { + ORIGINAL_PLATFORM = process.platform + + Object.defineProperty(process, "platform", { + value: "linux", + }) + }) + + beforeEach(() => { + jest.resetModules() + jest.mock("env-paths", () => { + return () => ({ + data: "/linux/envPath/.local/share", + config: "/linux/envPath/.config", + temp: "/tmp/envPath/runtime", + }) + }) + }) + + afterAll(() => { + // Restore old platform + + Object.defineProperty(process, "platform", { + value: ORIGINAL_PLATFORM, + }) + }) + + it("should return the runtime using xdgBasedir if it exists", () => { + jest.mock("xdg-basedir", () => ({ + runtime: "/tmp/runtime", + })) + const getEnvPaths = require("../../../src/node/util").getEnvPaths + const envPaths = getEnvPaths() + + expect(envPaths.data).toEqual("/linux/envPath/.local/share") + expect(envPaths.config).toEqual("/linux/envPath/.config") + expect(envPaths.runtime).toEqual("/tmp/runtime/code-server") + }) + + it("should return the env paths using envPaths when xdgBasedir is undefined", () => { + jest.mock("xdg-basedir", () => ({})) + const getEnvPaths = require("../../../src/node/util").getEnvPaths + const envPaths = getEnvPaths() + + expect(envPaths.data).toEqual("/linux/envPath/.local/share") + expect(envPaths.config).toEqual("/linux/envPath/.config") + expect(envPaths.runtime).toEqual("/tmp/envPath/runtime") + }) }) })