diff --git a/CHANGELOG.md b/CHANGELOG.md index f723fc7bd..12e3d5073 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 39f23dfbe..1651046d0 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 2633d3d5c..f1882471d 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 e26add808..bb1884b9c 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") + }) }) })