From d0c4f5c46fb40d963ded7530884225355c8e9465 Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Sat, 15 Jun 2024 14:59:14 -0700 Subject: [PATCH] Support Windows Builds (#54) This adds support for windows builds. With it, the app can successfully run on windows and unix systems. Note that the terminal still only works on unix systems at this time. --- Taskfile.yml | 4 ++-- cmd/server/main-server.go | 11 +++++++-- emain/emain.ts | 35 +++++++++++++++++++++-------- go.mod | 3 ++- go.sum | 5 +++++ pkg/filestore/blockstore_dbsetup.go | 4 ++-- pkg/wavebase/wavebase.go | 24 +++++++++----------- pkg/wstore/wstore_dbsetup.go | 4 ++-- 8 files changed, 58 insertions(+), 32 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index e3dc52fd..8b767b8d 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -32,12 +32,12 @@ tasks: build:server: cmds: - - go build -o dist/bin/wavesrv cmd/server/main-server.go + - go build -o dist/bin/wavesrv{{exeExt}} cmd/server/main-server.go sources: - "cmd/server/*.go" - "pkg/**/*.go" generates: - - dist/bin/wavesrv + - dist/bin/wavesrv{{exeExt}} deps: - go:mod:tidy diff --git a/cmd/server/main-server.go b/cmd/server/main-server.go index 5b994469..34d777b3 100644 --- a/cmd/server/main-server.go +++ b/cmd/server/main-server.go @@ -9,6 +9,7 @@ import ( "log" "os" "os/signal" + "runtime" "strconv" "sync" @@ -80,6 +81,12 @@ func main() { log.Printf("error acquiring wave lock (another instance of Wave is likely running): %v\n", err) return } + defer func() { + err = waveLock.Unlock() + if err != nil { + log.Printf("error releasing wave lock: %v\n", err) + } + }() log.Printf("wave home dir: %s\n", wavebase.GetWaveHomeDir()) err = filestore.InitFilestore() @@ -105,9 +112,9 @@ func main() { time.Sleep(30 * time.Millisecond) pidStr := os.Getenv(ReadySignalPidVarName) if pidStr != "" { - pid, err := strconv.Atoi(pidStr) + _, err := strconv.Atoi(pidStr) if err == nil { - syscall.Kill(pid, syscall.SIGUSR1) + log.Printf("WAVESRV-ESTART\n") } } }() diff --git a/emain/emain.ts b/emain/emain.ts index 2152c81b..b2f83426 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -7,6 +7,8 @@ import * as path from "path"; import * as readline from "readline"; import { debounce } from "throttle-debounce"; import * as services from "../frontend/app/store/services"; +import os from "os"; +import fs from "fs"; const electronApp = electron.app; const isDev = process.env.WAVETERM_DEV; @@ -23,6 +25,7 @@ let waveSrvReadyResolve = (value: boolean) => {}; let waveSrvReady: Promise = new Promise((resolve, _) => { waveSrvReadyResolve = resolve; }); + let waveSrvProc: child_process.ChildProcessWithoutNullStreams | null = null; electronApp.setName(isDev ? "NextWave (Dev)" : "NextWave"); const unamePlatform = process.platform; @@ -40,7 +43,7 @@ function getBaseHostPort(): string { // must match golang function getWaveHomeDir() { - return path.join(process.env.HOME, ".w2"); + return path.join(os.homedir(), ".w2"); } function getElectronAppBasePath(): string { @@ -60,6 +63,11 @@ function getWaveSrvPath(): string { return path.join(getGoAppBasePath(), "bin", "wavesrv"); } +function getWaveSrvPathWin(): string { + const appPath = path.join(getGoAppBasePath(), "bin", "wavesrv.exe"); + return `& "${appPath}"` +} + function getWaveSrvCwd(): string { return getWaveHomeDir(); } @@ -77,7 +85,12 @@ function runWaveSrv(): Promise { envCopy[WaveDevVarName] = "1"; } envCopy[WaveSrvReadySignalPidVarName] = process.pid.toString(); - const waveSrvCmd = getWaveSrvPath(); + let waveSrvCmd: string; + if (process.platform === "win32") { + waveSrvCmd = getWaveSrvPathWin(); + } else { + waveSrvCmd = getWaveSrvPath(); + } console.log("trying to run local server", waveSrvCmd); const proc = child_process.spawn(getWaveSrvPath(), { cwd: getWaveSrvCwd(), @@ -108,6 +121,10 @@ function runWaveSrv(): Promise { terminal: false, }); rlStderr.on("line", (line) => { + if (line.includes("WAVESRV-ESTART")) { + waveSrvReadyResolve(true); + return; + } console.log(line); }); return rtnPromise; @@ -232,11 +249,6 @@ electron.ipcMain.on("isDevServer", () => { return isDevServer; }); -process.on("SIGUSR1", function () { - ``; - waveSrvReadyResolve(true); -}); - (async () => { const startTs = Date.now(); const instanceLock = electronApp.requestSingleInstanceLock(); @@ -245,16 +257,21 @@ process.on("SIGUSR1", function () { electronApp.quit(); return; } + const waveHomeDir = getWaveHomeDir(); + if (!fs.existsSync(waveHomeDir)) { + fs.mkdirSync(waveHomeDir); + } try { await runWaveSrv(); } catch (e) { console.log(e.toString()); } - console.log("waiting for wavesrv ready signal (SIGUSR1)"); const ready = await waveSrvReady; console.log("wavesrv ready signal received", ready, Date.now() - startTs, "ms"); - let clientData = await services.ClientService.GetClientData(); + console.log("get client data"); + let clientData = await services.ClientService.GetClientData().catch(e => console.log(e)) as Client; + console.log("client data ready"); let windowData: WaveWindow = (await services.ObjectService.GetObject( "window:" + clientData.mainwindowid )) as WaveWindow; diff --git a/go.mod b/go.mod index 990843d4..0f985907 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22 toolchain go1.22.1 require ( + github.com/alexflint/go-filemutex v1.3.0 github.com/creack/pty v1.1.18 github.com/golang-migrate/migrate/v4 v4.17.1 github.com/google/uuid v1.4.0 @@ -17,7 +18,6 @@ require ( github.com/sawka/txwrap v0.2.0 github.com/spf13/cobra v1.8.0 github.com/wavetermdev/waveterm/wavesrv v0.0.0-20240508181017-d07068c09d94 - golang.org/x/sys v0.20.0 golang.org/x/term v0.17.0 ) @@ -29,4 +29,5 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 // indirect go.uber.org/atomic v1.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect ) diff --git a/go.sum b/go.sum index 7f1f1f43..f496a489 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/alexflint/go-filemutex v1.3.0 h1:LgE+nTUWnQCyRKbpoceKZsPQbs84LivvgwUymZXdOcM= +github.com/alexflint/go-filemutex v1.3.0/go.mod h1:U0+VA/i30mGBlLCrFPGtTe9y6wGQfNAWPBTekHQ+c8A= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -46,16 +48,19 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/wavetermdev/waveterm/wavesrv v0.0.0-20240508181017-d07068c09d94 h1:/SPCxd4KHlS4eRTreYEXWFRr8WfRFBcChlV5cgkaO58= github.com/wavetermdev/waveterm/wavesrv v0.0.0-20240508181017-d07068c09d94/go.mod h1:ywoo7DXdYueQ0tTPhVoB+wzRTgERSE19EA3mR6KGRaI= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/filestore/blockstore_dbsetup.go b/pkg/filestore/blockstore_dbsetup.go index 63bcf88d..3580ebd6 100644 --- a/pkg/filestore/blockstore_dbsetup.go +++ b/pkg/filestore/blockstore_dbsetup.go @@ -10,7 +10,7 @@ import ( "context" "fmt" "log" - "path" + "path/filepath" "time" "github.com/wavetermdev/thenextwave/pkg/util/migrateutil" @@ -51,7 +51,7 @@ func InitFilestore() error { func GetDBName() string { waveHome := wavebase.GetWaveHomeDir() - return path.Join(waveHome, FilestoreDBName) + return filepath.Join(waveHome, FilestoreDBName) } func MakeDB(ctx context.Context) (*sqlx.DB, error) { diff --git a/pkg/wavebase/wavebase.go b/pkg/wavebase/wavebase.go index 5e5bcac2..423ead07 100644 --- a/pkg/wavebase/wavebase.go +++ b/pkg/wavebase/wavebase.go @@ -11,21 +11,19 @@ import ( "log" "os" "os/exec" - "path" "path/filepath" "runtime" "strings" "sync" "time" - "golang.org/x/sys/unix" + "github.com/alexflint/go-filemutex" ) const WaveVersion = "v0.1.0" const DefaultWaveHome = "~/.w2" const WaveHomeVarName = "WAVETERM_HOME" const WaveDevVarName = "WAVETERM_DEV" -const HomeVarName = "HOME" const WaveLockFile = "waveterm.lock" var baseLock = &sync.Mutex{} @@ -37,8 +35,8 @@ func IsDevMode() bool { } func GetHomeDir() string { - homeVar := os.Getenv(HomeVarName) - if homeVar == "" { + homeVar, err := os.UserHomeDir() + if err != nil { return "/" } return homeVar @@ -52,7 +50,7 @@ func ExpandHomeDir(pathStr string) string { if pathStr == "~" { return homeDir } - return path.Join(homeDir, pathStr[2:]) + return filepath.Join(homeDir, pathStr[2:]) } func ReplaceHomeDir(pathStr string) string { @@ -142,18 +140,16 @@ func DetermineLang() string { return osLang } -func AcquireWaveLock() (*os.File, error) { +func AcquireWaveLock() (*filemutex.FileMutex, error) { homeDir := GetWaveHomeDir() lockFileName := filepath.Join(homeDir, WaveLockFile) log.Printf("[base] acquiring lock on %s\n", lockFileName) - fd, err := os.OpenFile(lockFileName, os.O_RDWR|os.O_CREATE, 0600) + m, err := filemutex.New(lockFileName) if err != nil { return nil, err } - err = unix.Flock(int(fd.Fd()), unix.LOCK_EX|unix.LOCK_NB) - if err != nil { - fd.Close() - return nil, err - } - return fd, nil + + err = m.TryLock() + return m, err + } diff --git a/pkg/wstore/wstore_dbsetup.go b/pkg/wstore/wstore_dbsetup.go index f79e2cea..fafdade3 100644 --- a/pkg/wstore/wstore_dbsetup.go +++ b/pkg/wstore/wstore_dbsetup.go @@ -7,7 +7,7 @@ import ( "context" "fmt" "log" - "path" + "path/filepath" "time" "github.com/jmoiron/sqlx" @@ -42,7 +42,7 @@ func InitWStore() error { func GetDBName() string { waveHome := wavebase.GetWaveHomeDir() - return path.Join(waveHome, WStoreDBName) + return filepath.Join(waveHome, WStoreDBName) } func MakeDB(ctx context.Context) (*sqlx.DB, error) {