Files
backrest/cmd/backrestmon/backrestmon.go

144 lines
3.2 KiB
Go

//go:build windows
// +build windows
package main
import (
"context"
"flag"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"runtime"
"syscall"
"github.com/garethgeorge/backrest/internal/env"
"github.com/getlantern/systray"
"github.com/ncruces/zenity"
_ "embed"
)
//go:embed icon.ico
var icon []byte
func main() {
flag.Parse()
backrest, err := findBackrest()
if err != nil {
reportError(err)
return
}
ctx, cancel := context.WithCancel(context.Background())
cmd := exec.CommandContext(ctx, backrest, os.Args[1:]...)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "ENV=production")
if err := cmd.Start(); err != nil {
reportError(err)
cancel()
return
}
systray.Run(func() {
systray.SetTitle("Backrest Tray")
systray.SetTooltip("Manage backrest")
systray.SetIcon(icon)
// First item: open the WebUI in the default browser.
mOpenUI := systray.AddMenuItem("Open WebUI", "Open the Backrest WebUI in your default browser")
mOpenUI.ClickedCh = make(chan struct{})
go func() {
for range mOpenUI.ClickedCh {
bindaddr := env.BindAddress()
if bindaddr == "" {
bindaddr = ":9898"
}
_, port, err := net.SplitHostPort(bindaddr)
if err != nil {
port = "9898" // try the default
}
if err := openBrowser(fmt.Sprintf("http://localhost:%v", port)); err != nil {
reportError(err)
}
}
}()
// Second item: open the log file in the file explorer
mOpenLog := systray.AddMenuItem("Open Log Dir", "Open the Backrest log directory")
mOpenLog.ClickedCh = make(chan struct{})
go func() {
for range mOpenLog.ClickedCh {
cmd := exec.Command(`explorer`, `/select,`, env.LogsPath())
cmd.Start()
go cmd.Wait()
}
}()
// Last item: quit button to stop the backrest process.
mQuit := systray.AddMenuItem("Quit", "Kills the backrest process and exits the tray app")
mQuit.ClickedCh = make(chan struct{})
go func() {
<-mQuit.ClickedCh
cancel()
systray.Quit()
}()
}, func() {
cancel()
})
if err := cmd.Wait(); err != nil {
systray.Quit()
if ctx.Err() != context.Canceled {
reportError(fmt.Errorf("backrest process exited unexpectedly with error: %w", err))
}
return
}
}
func findBackrest() (string, error) {
// Backrest binary must be installed in the same directory as the backresttray binary.
ex, err := os.Executable()
if err != nil {
return "", err
}
dir := filepath.Dir(ex)
wantPath := filepath.Join(dir, backrestBinName())
if stat, err := os.Stat(wantPath); err == nil && !stat.IsDir() {
return wantPath, nil
}
return "", fmt.Errorf("backrest binary not found at %s", wantPath)
}
func backrestBinName() string {
if runtime.GOOS == "windows" {
return "backrest.exe"
} else {
return "backrest"
}
}
func openBrowser(url string) error {
switch runtime.GOOS {
case "linux":
return exec.Command("xdg-open", url).Start()
case "windows":
return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
return exec.Command("open", url).Start()
default:
return fmt.Errorf("unsupported platform")
}
}
func reportError(err error) {
zenity.Error(err.Error(), zenity.Title("Backrest Error"))
}