diff --git a/packages/cli/src/cli/cmd/config/get.ts b/packages/cli/src/cli/cmd/config/get.ts index e6430820c..190b39a8e 100644 --- a/packages/cli/src/cli/cmd/config/get.ts +++ b/packages/cli/src/cli/cmd/config/get.ts @@ -1,12 +1,16 @@ import { Command } from "interactive-commander"; import chalk from "chalk"; import _ from "lodash"; -import { SETTINGS_KEYS, loadSystemSettings } from "../../utils/settings"; +import { + SETTINGS_KEYS, + loadSystemSettings, + getSettingsDisplayPath, +} from "../../utils/settings"; import dedent from "dedent"; export default new Command() .name("get") - .description("Display the value of a CLI setting from ~/.lingodotdevrc") + .description(`Display the value of a CLI setting from ${getSettingsDisplayPath()}`) .addHelpText("afterAll", `\nAvailable keys:\n ${SETTINGS_KEYS.join("\n ")}`) .argument( "", diff --git a/packages/cli/src/cli/cmd/config/index.ts b/packages/cli/src/cli/cmd/config/index.ts index c055b3e41..6a323f830 100644 --- a/packages/cli/src/cli/cmd/config/index.ts +++ b/packages/cli/src/cli/cmd/config/index.ts @@ -1,4 +1,5 @@ import { Command } from "interactive-commander"; +import { getSettingsDisplayPath } from "../../utils/settings"; import setCmd from "./set"; import unsetCmd from "./unset"; @@ -7,7 +8,7 @@ import getCmd from "./get"; export default new Command() .command("config") .description( - "Manage CLI settings (authentication, API keys) stored in ~/.lingodotdevrc", + `Manage CLI settings (authentication, API keys) stored in ${getSettingsDisplayPath()}`, ) .helpOption("-h, --help", "Show help") .addCommand(setCmd) diff --git a/packages/cli/src/cli/cmd/config/set.ts b/packages/cli/src/cli/cmd/config/set.ts index 6ca879d2f..80fa43194 100644 --- a/packages/cli/src/cli/cmd/config/set.ts +++ b/packages/cli/src/cli/cmd/config/set.ts @@ -6,11 +6,12 @@ import { SETTINGS_KEYS, loadSystemSettings, saveSettings, + getSettingsDisplayPath, } from "../../utils/settings"; export default new Command() .name("set") - .description("Set or update a CLI setting in ~/.lingodotdevrc") + .description(`Set or update a CLI setting in ${getSettingsDisplayPath()}`) .addHelpText("afterAll", `\nAvailable keys:\n ${SETTINGS_KEYS.join("\n ")}`) .argument( "", diff --git a/packages/cli/src/cli/cmd/config/unset.ts b/packages/cli/src/cli/cmd/config/unset.ts index 14e4377e7..a4ef55c6f 100644 --- a/packages/cli/src/cli/cmd/config/unset.ts +++ b/packages/cli/src/cli/cmd/config/unset.ts @@ -6,11 +6,12 @@ import { SETTINGS_KEYS, loadSystemSettings, saveSettings, + getSettingsDisplayPath, } from "../../utils/settings"; export default new Command() .name("unset") - .description("Remove a CLI setting from ~/.lingodotdevrc") + .description(`Remove a CLI setting from ${getSettingsDisplayPath()}`) .addHelpText("afterAll", `\nAvailable keys:\n ${SETTINGS_KEYS.join("\n ")}`) .argument( "", diff --git a/packages/cli/src/cli/utils/settings.spec.ts b/packages/cli/src/cli/utils/settings.spec.ts new file mode 100644 index 000000000..f66cca0a2 --- /dev/null +++ b/packages/cli/src/cli/utils/settings.spec.ts @@ -0,0 +1,27 @@ +import os from "os"; +import path from "path"; +import { describe, it, expect, vi, afterEach } from "vitest"; + +import { getSettingsDisplayPath } from "./settings"; + +describe("getSettingsDisplayPath", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("returns a tilde path on non-Windows platforms", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("linux"); + + expect(getSettingsDisplayPath()).toBe("~/.lingodotdevrc"); + }); + + it("returns the resolved settings path on Windows", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + vi.spyOn(os, "homedir").mockReturnValue("C:\\Users\\alice"); + + const expectedPath = path.join("C:\\Users\\alice", ".lingodotdevrc"); + + expect(getSettingsDisplayPath()).toBe(expectedPath); + }); +}); + diff --git a/packages/cli/src/cli/utils/settings.ts b/packages/cli/src/cli/utils/settings.ts index 8d3db2928..44b15e26f 100644 --- a/packages/cli/src/cli/utils/settings.ts +++ b/packages/cli/src/cli/utils/settings.ts @@ -52,6 +52,20 @@ export function loadSystemSettings() { return _loadSystemFile(); } +export function getSettingsFilePath(): string { + const settingsFile = ".lingodotdevrc"; + const homedir = os.homedir(); + const settingsFilePath = path.join(homedir, settingsFile); + return settingsFilePath; +} + +export function getSettingsDisplayPath(): string { + if (process.platform === "win32") { + return getSettingsFilePath(); + } + return "~/.lingodotdevrc"; +} + const flattenZodObject = (schema: Z.ZodObject, prefix = ""): string[] => { return Object.entries(schema.shape).flatMap(([key, value]) => { const newPrefix = prefix ? `${prefix}.${key}` : key; @@ -112,7 +126,7 @@ function _loadEnv() { } function _loadSystemFile() { - const settingsFilePath = _getSettingsFilePath(); + const settingsFilePath = getSettingsFilePath(); const content = fs.existsSync(settingsFilePath) ? fs.readFileSync(settingsFilePath, "utf-8") : ""; @@ -138,18 +152,11 @@ function _loadSystemFile() { } function _saveSystemFile(settings: CliSettings) { - const settingsFilePath = _getSettingsFilePath(); + const settingsFilePath = getSettingsFilePath(); const content = Ini.stringify(settings); fs.writeFileSync(settingsFilePath, content); } -function _getSettingsFilePath(): string { - const settingsFile = ".lingodotdevrc"; - const homedir = os.homedir(); - const settingsFilePath = path.join(homedir, settingsFile); - return settingsFilePath; -} - function _legacyEnvVarWarning() { const env = _loadEnv(); diff --git a/packages/cli/src/cli/utils/update-gitignore.ts b/packages/cli/src/cli/utils/update-gitignore.ts index 3d30e4e7e..b97fdafbf 100644 --- a/packages/cli/src/cli/utils/update-gitignore.ts +++ b/packages/cli/src/cli/utils/update-gitignore.ts @@ -12,19 +12,22 @@ export default function updateGitignore() { return; } - const gitignore = fs.readFileSync(gitignorePath, "utf8").split("\n"); - const cacheIsIgnored = gitignore.includes(cacheFile); + const gitignoreContent = fs.readFileSync(gitignorePath, "utf8"); + const gitignoreEntries = gitignoreContent + .split(/\r?\n/) + .map((entry) => entry.replace(/\r$/, "")); + const cacheIsIgnored = gitignoreEntries.includes(cacheFile); if (!cacheIsIgnored) { - let content = ""; + let content = gitignoreContent; + const newline = gitignoreContent.includes("\r\n") ? "\r\n" : "\n"; // Ensure there's a trailing newline - content = fs.readFileSync(gitignorePath, "utf8"); if (content !== "" && !content.endsWith("\n")) { - content += "\n"; + content += newline; } - content += `${cacheFile}\n`; + content += `${cacheFile}${newline}`; fs.writeFileSync(gitignorePath, content); } }