diff --git a/Taskfile.yml b/Taskfile.yml index 29a37bd42..829704db3 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -184,8 +184,8 @@ tasks: generate: desc: Generate Typescript bindings for the Go backend. cmds: - - go run cmd/generatets/main-generatets.go - - go run cmd/generatego/main-generatego.go + - NO_PANIC=1 go run cmd/generatets/main-generatets.go + - NO_PANIC=1 go run cmd/generatego/main-generatego.go sources: - "cmd/generatego/*.go" - "cmd/generatets/*.go" diff --git a/cmd/server/main-server.go b/cmd/server/main-server.go index 5ab88bd59..b560b2766 100644 --- a/cmd/server/main-server.go +++ b/cmd/server/main-server.go @@ -182,7 +182,7 @@ func main() { log.Printf("error validating service map: %v\n", err) return } - err = wavebase.EnsureWaveHomeDir() + err = wavebase.EnsureWaveDataDir() if err != nil { log.Printf("error ensuring wave home dir: %v\n", err) return @@ -192,14 +192,14 @@ func main() { log.Printf("error ensuring wave db dir: %v\n", err) return } - err = wconfig.EnsureWaveConfigDir() + err = wavebase.EnsureWaveConfigDir() if err != nil { log.Printf("error ensuring wave config dir: %v\n", err) return } // TODO: rather than ensure this dir exists, we should let the editor recursively create parent dirs on save - err = wconfig.EnsureWavePresetsDir() + err = wavebase.EnsureWavePresetsDir() if err != nil { log.Printf("error ensuring wave presets dir: %v\n", err) return @@ -216,7 +216,8 @@ func main() { } }() log.Printf("wave version: %s (%s)\n", WaveVersion, BuildTime) - log.Printf("wave home dir: %s\n", wavebase.GetWaveHomeDir()) + log.Printf("wave data dir: %s\n", wavebase.GetWaveDataDir()) + log.Printf("wave config dir: %s\n", wavebase.GetWaveConfigDir()) err = filestore.InitFilestore() if err != nil { log.Printf("error initializing filestore: %v\n", err) diff --git a/emain/docsite.ts b/emain/docsite.ts index ddf9d21b8..37818b954 100644 --- a/emain/docsite.ts +++ b/emain/docsite.ts @@ -1,6 +1,6 @@ -import { getWebServerEndpoint } from "@/util/endpoints"; -import { fetch } from "@/util/fetchutil"; import { ipcMain } from "electron"; +import { getWebServerEndpoint } from "../frontend/util/endpoints"; +import { fetch } from "../frontend/util/fetchutil"; const docsiteWebUrl = "https://docs.waveterm.dev/"; let docsiteUrl: string; diff --git a/emain/emain-viewmgr.ts b/emain/emain-viewmgr.ts index 0afe7a0f1..7818e69ac 100644 --- a/emain/emain-viewmgr.ts +++ b/emain/emain-viewmgr.ts @@ -1,8 +1,13 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { ClientService, FileService, ObjectService, WindowService } from "@/app/store/services"; import * as electron from "electron"; +import * as path from "path"; +import { debounce } from "throttle-debounce"; +import { ClientService, FileService, ObjectService, WindowService } from "../frontend/app/store/services"; +import * as keyutil from "../frontend/util/keyutil"; +import { configureAuthKeyRequestInjection } from "./authkey"; +import { getGlobalIsQuitting, getGlobalIsStarting, setWasActive, setWasInFg } from "./emain-activity"; import { delay, ensureBoundsAreVisible, @@ -10,12 +15,7 @@ import { handleCtrlShiftState, shFrameNavHandler, shNavHandler, -} from "emain/emain-util"; -import * as keyutil from "frontend/util/keyutil"; -import * as path from "path"; -import { debounce } from "throttle-debounce"; -import { configureAuthKeyRequestInjection } from "./authkey"; -import { getGlobalIsQuitting, getGlobalIsStarting, setWasActive, setWasInFg } from "./emain-activity"; +} from "./emain-util"; import { getElectronAppBasePath, isDevVite } from "./platform"; import { updater } from "./updater"; diff --git a/emain/emain-wavesrv.ts b/emain/emain-wavesrv.ts index 597e2f032..e8ade2475 100644 --- a/emain/emain-wavesrv.ts +++ b/emain/emain-wavesrv.ts @@ -1,15 +1,23 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { WebServerEndpointVarName, WSServerEndpointVarName } from "@/util/endpoints"; import * as electron from "electron"; -import { AuthKey, AuthKeyEnv } from "emain/authkey"; -import { setForceQuit } from "emain/emain-activity"; -import { WaveAppPathVarName } from "emain/emain-util"; -import { getElectronAppUnpackedBasePath, getWaveSrvCwd, getWaveSrvPath } from "emain/platform"; -import { updater } from "emain/updater"; import * as child_process from "node:child_process"; import * as readline from "readline"; +import { WebServerEndpointVarName, WSServerEndpointVarName } from "../frontend/util/endpoints"; +import { AuthKey, AuthKeyEnv } from "./authkey"; +import { setForceQuit } from "./emain-activity"; +import { WaveAppPathVarName } from "./emain-util"; +import { + getElectronAppUnpackedBasePath, + getWaveConfigDir, + getWaveDataDir, + getWaveSrvCwd, + getWaveSrvPath, + WaveConfigHomeVarName, + WaveDataHomeVarName, +} from "./platform"; +import { updater } from "./updater"; export const WaveSrvReadySignalPidVarName = "WAVETERM_READY_SIGNAL_PID"; @@ -50,6 +58,8 @@ export function runWaveSrv(handleWSEvent: (evtMsg: WSEventType) => void): Promis envCopy[WaveAppPathVarName] = getElectronAppUnpackedBasePath(); envCopy[WaveSrvReadySignalPidVarName] = process.pid.toString(); envCopy[AuthKeyEnv] = AuthKey; + envCopy[WaveDataHomeVarName] = getWaveDataDir(); + envCopy[WaveConfigHomeVarName] = getWaveConfigDir(); const waveSrvCmd = getWaveSrvPath(); console.log("trying to run local server", waveSrvCmd); const proc = child_process.spawn(getWaveSrvPath(), { diff --git a/emain/emain-wsh.ts b/emain/emain-wsh.ts index fcdeb253a..a354f2676 100644 --- a/emain/emain-wsh.ts +++ b/emain/emain-wsh.ts @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import { Notification } from "electron"; -import { getWaveWindowById } from "emain/emain-viewmgr"; import { RpcResponseHelper, WshClient } from "../frontend/app/store/wshclient"; +import { getWaveWindowById } from "./emain-viewmgr"; import { getWebContentsByBlockId, webGetSelector } from "./emain-web"; export class ElectronWshClientType extends WshClient { diff --git a/emain/emain.ts b/emain/emain.ts index 86b0009a8..40f8a11e0 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -2,31 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import * as electron from "electron"; -import { - getActivityState, - getForceQuit, - getGlobalIsRelaunching, - setForceQuit, - setGlobalIsQuitting, - setGlobalIsRelaunching, - setGlobalIsStarting, - setWasActive, - setWasInFg, -} from "emain/emain-activity"; -import { handleCtrlShiftState } from "emain/emain-util"; -import { - createBrowserWindow, - ensureHotSpareTab, - getAllWaveWindows, - getFocusedWaveWindow, - getLastFocusedWaveWindow, - getWaveTabViewByWebContentsId, - getWaveWindowById, - getWaveWindowByWebContentsId, - setActiveTab, - setMaxTabCacheSize, -} from "emain/emain-viewmgr"; -import { getIsWaveSrvDead, getWaveSrvProc, getWaveSrvReady, getWaveVersion, runWaveSrv } from "emain/emain-wavesrv"; import { FastAverageColor } from "fast-average-color"; import fs from "fs"; import * as child_process from "node:child_process"; @@ -44,13 +19,39 @@ import * as keyutil from "../frontend/util/keyutil"; import { fireAndForget } from "../frontend/util/util"; import { AuthKey, configureAuthKeyRequestInjection } from "./authkey"; import { initDocsite } from "./docsite"; +import { + getActivityState, + getForceQuit, + getGlobalIsRelaunching, + setForceQuit, + setGlobalIsQuitting, + setGlobalIsRelaunching, + setGlobalIsStarting, + setWasActive, + setWasInFg, +} from "./emain-activity"; +import { handleCtrlShiftState } from "./emain-util"; +import { + createBrowserWindow, + ensureHotSpareTab, + getAllWaveWindows, + getFocusedWaveWindow, + getLastFocusedWaveWindow, + getWaveTabViewByWebContentsId, + getWaveWindowById, + getWaveWindowByWebContentsId, + setActiveTab, + setMaxTabCacheSize, +} from "./emain-viewmgr"; +import { getIsWaveSrvDead, getWaveSrvProc, getWaveSrvReady, getWaveVersion, runWaveSrv } from "./emain-wavesrv"; import { ElectronWshClient, initElectronWshClient } from "./emain-wsh"; import { getLaunchSettings } from "./launchsettings"; import { getAppMenu } from "./menu"; import { getElectronAppBasePath, getElectronAppUnpackedBasePath, - getWaveHomeDir, + getWaveConfigDir, + getWaveDataDir, isDev, unameArch, unamePlatform, @@ -59,15 +60,17 @@ import { configureAutoUpdater, updater } from "./updater"; const electronApp = electron.app; +const waveDataDir = getWaveDataDir(); +const waveConfigDir = getWaveConfigDir(); + electron.nativeTheme.themeSource = "dark"; let webviewFocusId: number = null; // set to the getWebContentsId of the webview that has focus (null if not focused) let webviewKeys: string[] = []; // the keys to trap when webview has focus -const waveHome = getWaveHomeDir(); const oldConsoleLog = console.log; const loggerTransports: winston.transport[] = [ - new winston.transports.File({ filename: path.join(getWaveHomeDir(), "waveapp.log"), level: "info" }), + new winston.transports.File({ filename: path.join(waveDataDir, "waveapp.log"), level: "info" }), ]; if (isDev) { loggerTransports.push(new winston.transports.Console()); @@ -91,8 +94,9 @@ function log(...msg: any[]) { console.log = log; console.log( sprintf( - "waveterm-app starting, WAVETERM_HOME=%s, electronpath=%s gopath=%s arch=%s/%s", - waveHome, + "waveterm-app starting, data_dir=%s, config_dir=%s electronpath=%s gopath=%s arch=%s/%s", + waveDataDir, + waveConfigDir, getElectronAppBasePath(), getElectronAppUnpackedBasePath(), unamePlatform, @@ -676,10 +680,6 @@ async function appMain() { electronApp.quit(); return; } - const waveHomeDir = getWaveHomeDir(); - if (!fs.existsSync(waveHomeDir)) { - fs.mkdirSync(waveHomeDir); - } makeAppMenu(); try { await runWaveSrv(handleWSEvent); diff --git a/emain/launchsettings.ts b/emain/launchsettings.ts index 92339c915..cb0c253ad 100644 --- a/emain/launchsettings.ts +++ b/emain/launchsettings.ts @@ -1,6 +1,6 @@ import fs from "fs"; import path from "path"; -import { getWaveHomeDir } from "./platform"; +import { getWaveConfigDir } from "./platform"; /** * Get settings directly from the Wave Home directory on launch. @@ -8,7 +8,7 @@ import { getWaveHomeDir } from "./platform"; * @returns The initial launch settings for the application. */ export function getLaunchSettings(): SettingsType { - const settingsPath = path.join(getWaveHomeDir(), "config", "settings.json"); + const settingsPath = path.join(getWaveConfigDir(), "settings.json"); try { const settingsContents = fs.readFileSync(settingsPath, "utf8"); return JSON.parse(settingsContents); diff --git a/emain/menu.ts b/emain/menu.ts index b23094287..0a38e7752 100644 --- a/emain/menu.ts +++ b/emain/menu.ts @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 import * as electron from "electron"; -import { clearTabCache, getFocusedWaveWindow } from "emain/emain-viewmgr"; import { fireAndForget } from "../frontend/util/util"; +import { clearTabCache, getFocusedWaveWindow } from "./emain-viewmgr"; import { unamePlatform } from "./platform"; import { updater } from "./updater"; diff --git a/emain/platform.ts b/emain/platform.ts index 36089982e..712c82ad2 100644 --- a/emain/platform.ts +++ b/emain/platform.ts @@ -2,12 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 import { app, ipcMain } from "electron"; +import envPaths from "env-paths"; +import { existsSync, mkdirSync } from "fs"; import os from "os"; import path from "path"; import { WaveDevVarName, WaveDevViteVarName } from "../frontend/util/isdev"; import * as keyutil from "../frontend/util/keyutil"; -const WaveHomeVarName = "WAVETERM_HOME"; +// This is a little trick to ensure that Electron puts all its runtime data into a subdirectory to avoid conflicts with our own data. +// On macOS, it will store to ~/Library/Application \Support/waveterm/electron +// On Linux, it will store to ~/.config/waveterm/electron +// On Windows, it will store to %LOCALAPPDATA%/waveterm/electron +app.setName("waveterm/electron"); const isDev = !app.isPackaged; const isDevVite = isDev && process.env.ELECTRON_RENDERER_URL; @@ -18,18 +24,100 @@ if (isDevVite) { process.env[WaveDevViteVarName] = "1"; } +const waveDirNamePrefix = "waveterm"; +const waveDirNameSuffix = isDev ? "dev" : ""; +const waveDirName = `${waveDirNamePrefix}${waveDirNameSuffix ? `-${waveDirNameSuffix}` : ""}`; + +const paths = envPaths("waveterm", { suffix: waveDirNameSuffix }); + app.setName(isDev ? "Wave (Dev)" : "Wave"); const unamePlatform = process.platform; const unameArch: string = process.arch; keyutil.setKeyUtilPlatform(unamePlatform); -// must match golang -function getWaveHomeDir() { - const override = process.env[WaveHomeVarName]; - if (override) { - return override; +const WaveConfigHomeVarName = "WAVETERM_CONFIG_HOME"; +const WaveDataHomeVarName = "WAVETERM_DATA_HOME"; +const WaveHomeVarName = "WAVETERM_HOME"; + +/** + * Gets the path to the old Wave home directory (defaults to `~/.waveterm`). + * @returns The path to the directory if it exists and contains valid data for the current app, otherwise null. + */ +function getWaveHomeDir(): string { + let home = process.env[WaveHomeVarName]; + if (!home) { + const homeDir = process.env.HOME; + if (homeDir) { + home = path.join(homeDir, `.${waveDirName}`); + } } - return path.join(os.homedir(), isDev ? ".waveterm-dev" : ".waveterm"); + // If home exists and it has `wave.lock` in it, we know it has valid data from Wave >=v0.8. Otherwise, it could be for WaveLegacy ( { @@ -71,18 +159,24 @@ ipcMain.on("get-host-name", (event) => { ipcMain.on("get-webview-preload", (event) => { event.returnValue = path.join(getElectronAppBasePath(), "preload", "preload-webview.cjs"); }); +ipcMain.on("get-data-dir", (event) => { + event.returnValue = getWaveDataDir(); +}); ipcMain.on("get-config-dir", (event) => { - event.returnValue = path.join(getWaveHomeDir(), "config"); + event.returnValue = getWaveConfigDir(); }); export { getElectronAppBasePath, getElectronAppUnpackedBasePath, - getWaveHomeDir, + getWaveConfigDir, + getWaveDataDir, getWaveSrvCwd, getWaveSrvPath, isDev, isDevVite, unameArch, unamePlatform, + WaveConfigHomeVarName, + WaveDataHomeVarName, }; diff --git a/emain/preload.ts b/emain/preload.ts index ba7027c7e..d0e0acfa9 100644 --- a/emain/preload.ts +++ b/emain/preload.ts @@ -10,6 +10,7 @@ contextBridge.exposeInMainWorld("api", { getCursorPoint: () => ipcRenderer.sendSync("get-cursor-point"), getUserName: () => ipcRenderer.sendSync("get-user-name"), getHostName: () => ipcRenderer.sendSync("get-host-name"), + getDataDir: () => ipcRenderer.sendSync("get-data-dir"), getConfigDir: () => ipcRenderer.sendSync("get-config-dir"), getAboutModalDetails: () => ipcRenderer.sendSync("get-about-modal-details"), getDocsiteUrl: () => ipcRenderer.sendSync("get-docsite-url"), diff --git a/emain/updater.ts b/emain/updater.ts index 4c8e440d0..f3849d144 100644 --- a/emain/updater.ts +++ b/emain/updater.ts @@ -1,16 +1,16 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { RpcApi } from "@/app/store/wshclientapi"; import { dialog, ipcMain, Notification } from "electron"; import { autoUpdater } from "electron-updater"; -import { getAllWaveWindows, getFocusedWaveWindow } from "emain/emain-viewmgr"; import { readFileSync } from "fs"; import path from "path"; import YAML from "yaml"; import { FileService } from "../frontend/app/store/services"; +import { RpcApi } from "../frontend/app/store/wshclientapi"; import { isDev } from "../frontend/util/isdev"; import { fireAndForget } from "../frontend/util/util"; +import { getAllWaveWindows, getFocusedWaveWindow } from "./emain-viewmgr"; import { ElectronWshClient } from "./emain-wsh"; export let updater: Updater; diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 32d770b99..209405d49 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -64,6 +64,7 @@ declare global { getEnv: (varName: string) => string; getUserName: () => string; getHostName: () => string; + getDataDir: () => string; getConfigDir: () => string; getWebviewPreload: () => string; getAboutModalDetails: () => AboutModalDetails; diff --git a/package.json b/package.json index f77e05cea..8c52ad3db 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "dayjs": "^1.11.13", "debug": "^4.3.7", "electron-updater": "6.3.9", + "env-paths": "^3.0.0", "fast-average-color": "^9.4.0", "htl": "^0.3.1", "html-to-image": "^1.11.11", diff --git a/pkg/filestore/blockstore_dbsetup.go b/pkg/filestore/blockstore_dbsetup.go index d828c4173..8ceb5b366 100644 --- a/pkg/filestore/blockstore_dbsetup.go +++ b/pkg/filestore/blockstore_dbsetup.go @@ -50,7 +50,7 @@ func InitFilestore() error { } func GetDBName() string { - waveHome := wavebase.GetWaveHomeDir() + waveHome := wavebase.GetWaveDataDir() return filepath.Join(waveHome, wavebase.WaveDBDir, FilestoreDBName) } diff --git a/pkg/shellexec/shellexec.go b/pkg/shellexec/shellexec.go index a58433ded..c11faf619 100644 --- a/pkg/shellexec/shellexec.go +++ b/pkg/shellexec/shellexec.go @@ -289,7 +289,7 @@ func StartShellProc(termSize waveobj.TermSize, cmdStr string, cmdOpts CommandOpt // cant set -l or -i with --rcfile shellOpts = append(shellOpts, "--rcfile", shellutil.GetBashRcFileOverride()) } else if isFishShell(shellPath) { - wshBinDir := filepath.Join(wavebase.GetWaveHomeDir(), shellutil.WaveHomeBinDir) + wshBinDir := filepath.Join(wavebase.GetWaveDataDir(), shellutil.WaveHomeBinDir) quotedWshBinDir := utilfn.ShellQuote(wshBinDir, false, 300) shellOpts = append(shellOpts, "-C", fmt.Sprintf("set -x PATH %s $PATH", quotedWshBinDir)) } else if remote.IsPowershell(shellPath) { diff --git a/pkg/util/panic/panic.go b/pkg/util/panic/panic.go new file mode 100644 index 000000000..a7dde8bf5 --- /dev/null +++ b/pkg/util/panic/panic.go @@ -0,0 +1,15 @@ +package panic + +import ( + "log" + "os" +) + +var shouldPanic = len(os.Getenv("NO_PANIC")) == 0 + +// Wraps log.Panic, ignored if NO_PANIC is set +func Panic(message string) { + if shouldPanic { + log.Panic(message) + } +} diff --git a/pkg/util/shellutil/shellutil.go b/pkg/util/shellutil/shellutil.go index 1e6e6a3ab..91ac6d76b 100644 --- a/pkg/util/shellutil/shellutil.go +++ b/pkg/util/shellutil/shellutil.go @@ -149,7 +149,7 @@ func WaveshellLocalEnvVars(termType string) map[string]string { rtn["TERM_PROGRAM"] = "waveterm" rtn["WAVETERM"], _ = os.Executable() rtn["WAVETERM_VERSION"] = wavebase.WaveVersion - rtn["WAVETERM_WSHBINDIR"] = filepath.Join(wavebase.GetWaveHomeDir(), WaveHomeBinDir) + rtn["WAVETERM_WSHBINDIR"] = filepath.Join(wavebase.GetWaveDataDir(), WaveHomeBinDir) return rtn } @@ -202,15 +202,15 @@ func InitCustomShellStartupFiles() error { } func GetBashRcFileOverride() string { - return filepath.Join(wavebase.GetWaveHomeDir(), BashIntegrationDir, ".bashrc") + return filepath.Join(wavebase.GetWaveDataDir(), BashIntegrationDir, ".bashrc") } func GetWavePowershellEnv() string { - return filepath.Join(wavebase.GetWaveHomeDir(), PwshIntegrationDir, "wavepwsh.ps1") + return filepath.Join(wavebase.GetWaveDataDir(), PwshIntegrationDir, "wavepwsh.ps1") } func GetZshZDotDir() string { - return filepath.Join(wavebase.GetWaveHomeDir(), ZshIntegrationDir) + return filepath.Join(wavebase.GetWaveDataDir(), ZshIntegrationDir) } func GetWshBaseName(version string, goos string, goarch string) string { @@ -289,9 +289,9 @@ func InitRcFiles(waveHome string, wshBinDir string) error { func initCustomShellStartupFilesInternal() error { log.Printf("initializing wsh and shell startup files\n") - waveHome := wavebase.GetWaveHomeDir() - binDir := filepath.Join(waveHome, WaveHomeBinDir) - err := InitRcFiles(waveHome, `$WAVETERM_WSHBINDIR`) + waveDataHome := wavebase.GetWaveDataDir() + binDir := filepath.Join(waveDataHome, WaveHomeBinDir) + err := InitRcFiles(waveDataHome, `$WAVETERM_WSHBINDIR`) if err != nil { return err } diff --git a/pkg/wavebase/wavebase-posix.go b/pkg/wavebase/wavebase-posix.go index 352302221..12d2e7f75 100644 --- a/pkg/wavebase/wavebase-posix.go +++ b/pkg/wavebase/wavebase-posix.go @@ -14,8 +14,8 @@ import ( ) func AcquireWaveLock() (FDLock, error) { - homeDir := GetWaveHomeDir() - lockFileName := filepath.Join(homeDir, WaveLockFile) + dataHomeDir := GetWaveDataDir() + lockFileName := filepath.Join(dataHomeDir, WaveLockFile) log.Printf("[base] acquiring lock on %s\n", lockFileName) fd, err := os.OpenFile(lockFileName, os.O_RDWR|os.O_CREATE, 0600) if err != nil { diff --git a/pkg/wavebase/wavebase-win.go b/pkg/wavebase/wavebase-win.go index a22ac2f85..31bdab821 100644 --- a/pkg/wavebase/wavebase-win.go +++ b/pkg/wavebase/wavebase-win.go @@ -14,8 +14,8 @@ import ( ) func AcquireWaveLock() (FDLock, error) { - homeDir := GetWaveHomeDir() - lockFileName := filepath.Join(homeDir, WaveLockFile) + dataHomeDir := GetWaveDataDir() + lockFileName := filepath.Join(dataHomeDir, WaveLockFile) log.Printf("[base] acquiring lock on %s\n", lockFileName) m, err := filemutex.New(lockFileName) if err != nil { diff --git a/pkg/wavebase/wavebase.go b/pkg/wavebase/wavebase.go index da61e4a6f..44f80b7a7 100644 --- a/pkg/wavebase/wavebase.go +++ b/pkg/wavebase/wavebase.go @@ -17,15 +17,16 @@ import ( "strings" "sync" "time" + + "github.com/wavetermdev/waveterm/pkg/util/panic" ) // set by main-server.go var WaveVersion = "0.0.0" var BuildTime = "0" -const DefaultWaveHome = "~/.waveterm" -const DevWaveHome = "~/.waveterm-dev" -const WaveHomeVarName = "WAVETERM_HOME" +const WaveConfigHomeEnvVar = "WAVETERM_CONFIG_HOME" +const WaveDataHomeEnvVar = "WAVETERM_DATA_HOME" const WaveDevVarName = "WAVETERM_DEV" const WaveLockFile = "wave.lock" const DomainSocketBaseName = "wave.sock" @@ -97,26 +98,39 @@ func ReplaceHomeDir(pathStr string) string { } func GetDomainSocketName() string { - return filepath.Join(GetWaveHomeDir(), DomainSocketBaseName) + return filepath.Join(GetWaveDataDir(), DomainSocketBaseName) } -func GetWaveHomeDir() string { - homeVar := os.Getenv(WaveHomeVarName) - if homeVar != "" { - return ExpandHomeDirSafe(homeVar) +func GetWaveDataDir() string { + retVal, found := os.LookupEnv(WaveDataHomeEnvVar) + if !found { + panic.Panic(WaveDataHomeEnvVar + " not set") } - if IsDevMode() { - return ExpandHomeDirSafe(DevWaveHome) - } - return ExpandHomeDirSafe(DefaultWaveHome) + return retVal } -func EnsureWaveHomeDir() error { - return CacheEnsureDir(GetWaveHomeDir(), "wavehome", 0700, "wave home directory") +func GetWaveConfigDir() string { + retVal, found := os.LookupEnv(WaveConfigHomeEnvVar) + if !found { + panic.Panic(WaveConfigHomeEnvVar + " not set") + } + return retVal +} + +func EnsureWaveDataDir() error { + return CacheEnsureDir(GetWaveDataDir(), "wavehome", 0700, "wave home directory") } func EnsureWaveDBDir() error { - return CacheEnsureDir(filepath.Join(GetWaveHomeDir(), WaveDBDir), "wavedb", 0700, "wave db directory") + return CacheEnsureDir(filepath.Join(GetWaveDataDir(), WaveDBDir), "wavedb", 0700, "wave db directory") +} + +func EnsureWaveConfigDir() error { + return CacheEnsureDir(GetWaveConfigDir(), "waveconfig", 0700, "wave config directory") +} + +func EnsureWavePresetsDir() error { + return CacheEnsureDir(filepath.Join(GetWaveConfigDir(), "presets"), "wavepresets", 0700, "wave presets directory") } func CacheEnsureDir(dirName string, cacheKey string, perm os.FileMode, dirDesc string) error { diff --git a/pkg/wconfig/filewatcher.go b/pkg/wconfig/filewatcher.go index c8d344d62..7286c3c32 100644 --- a/pkg/wconfig/filewatcher.go +++ b/pkg/wconfig/filewatcher.go @@ -14,7 +14,7 @@ import ( "github.com/wavetermdev/waveterm/pkg/wps" ) -var configDirAbsPath = filepath.Join(wavebase.GetWaveHomeDir(), wavebase.ConfigDir) +var configDirAbsPath = wavebase.GetWaveConfigDir() var instance *Watcher var once sync.Once diff --git a/pkg/wconfig/settingsconfig.go b/pkg/wconfig/settingsconfig.go index abcb22383..21386675e 100644 --- a/pkg/wconfig/settingsconfig.go +++ b/pkg/wconfig/settingsconfig.go @@ -16,7 +16,6 @@ import ( "strings" "github.com/wavetermdev/waveterm/pkg/util/utilfn" - "github.com/wavetermdev/waveterm/pkg/wavebase" "github.com/wavetermdev/waveterm/pkg/waveobj" "github.com/wavetermdev/waveterm/pkg/wconfig/defaultconfig" ) @@ -498,14 +497,6 @@ func SetBaseConfigValue(toMerge waveobj.MetaMapType) error { return WriteWaveHomeConfigFile(SettingsFile, m) } -func EnsureWaveConfigDir() error { - return wavebase.CacheEnsureDir(configDirAbsPath, "waveconfig", 0700, "wave config directory") -} - -func EnsureWavePresetsDir() error { - return wavebase.CacheEnsureDir(filepath.Join(configDirAbsPath, "presets"), "wavepresets", 0700, "wave presets directory") -} - type WidgetConfigType struct { DisplayOrder float64 `json:"display:order,omitempty"` Icon string `json:"icon,omitempty"` diff --git a/pkg/web/web.go b/pkg/web/web.go index 0e470490b..92d99ed77 100644 --- a/pkg/web/web.go +++ b/pkg/web/web.go @@ -431,7 +431,7 @@ func MakeTCPListener(serviceName string) (net.Listener, error) { } func MakeUnixListener() (net.Listener, error) { - serverAddr := wavebase.GetWaveHomeDir() + "/wave.sock" + serverAddr := wavebase.GetWaveDataDir() + "/wave.sock" os.Remove(serverAddr) // ignore error rtn, err := net.Listen("unix", serverAddr) if err != nil { diff --git a/pkg/wstore/wstore_dbsetup.go b/pkg/wstore/wstore_dbsetup.go index 7df15a021..3a4f83585 100644 --- a/pkg/wstore/wstore_dbsetup.go +++ b/pkg/wstore/wstore_dbsetup.go @@ -42,7 +42,7 @@ func InitWStore() error { } func GetDBName() string { - waveHome := wavebase.GetWaveHomeDir() + waveHome := wavebase.GetWaveDataDir() return filepath.Join(waveHome, wavebase.WaveDBDir, WStoreDBName) } diff --git a/yarn.lock b/yarn.lock index f63fa4aa4..9740c1282 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5297,6 +5297,13 @@ __metadata: languageName: node linkType: hard +"env-paths@npm:^3.0.0": + version: 3.0.0 + resolution: "env-paths@npm:3.0.0" + checksum: 10c0/76dec878cee47f841103bacd7fae03283af16f0702dad65102ef0a556f310b98a377885e0f32943831eb08b5ab37842a323d02529f3dfd5d0a40ca71b01b435f + languageName: node + linkType: hard + "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -11685,6 +11692,7 @@ __metadata: electron-builder: "npm:^25.1.7" electron-updater: "npm:6.3.9" electron-vite: "npm:^2.3.0" + env-paths: "npm:^3.0.0" eslint: "npm:^9.12.0" eslint-config-prettier: "npm:^9.1.0" fast-average-color: "npm:^9.4.0"