Installer/installer_win.go
partisan 58e18083a3
All checks were successful
/ test-on-windows (push) Successful in 15s
/ test-on-alpine (push) Successful in 11s
is this too much voodoo?
2025-03-02 10:14:22 +01:00

130 lines
3.2 KiB
Go

//go:build windows
package main
import (
"fmt"
"runtime"
spm "weforge.xyz/Spitfire/SPM"
)
// Installer manages the download, decompression, and installation processes.
type Installer struct {
// Progress info from SPM
Progress int
Task string
// Internal states
IsDownloading bool
IsInstalling bool
DoneDownload bool
DoneInstall bool
LastError error
PendingInstall bool
}
// NewInstaller creates a new Installer with initial state.
func NewInstaller() *Installer {
return &Installer{}
}
// StartDownloadDecompress starts the download and decompression in a background goroutine.
func (inst *Installer) StartDownloadDecompress() {
inst.IsDownloading = true
go func() {
defer func() {
inst.IsDownloading = false
// Signal that download phase is complete.
inst.DoneDownload = (inst.LastError == nil)
// If a final install was requested, go ahead.
if inst.PendingInstall && inst.DoneDownload && !inst.IsInstalling && !inst.DoneInstall {
inst.doFinalInstall()
}
}()
spm.UpdateProgress(0, "Preparing to download...")
// Define the package specifications.
specs := []spm.AppIndexEntry{
{
Name: "spitfire-luncher",
Release: "nightly",
OS: "windows",
Arch: runtime.GOARCH,
Type: "luncher",
},
{
Name: "spitfire-browser",
Release: "nightly",
OS: "windows",
Arch: runtime.GOARCH,
Type: "browser",
},
}
spm.UpdateProgress(0, "Downloading specified packages...")
if err := spm.DownloadSpecified(specs); err != nil {
fmt.Println("DownloadSpecifiedPackages failed:", err)
inst.LastError = err
return
}
spm.UpdateProgress(0, "Download and decompression complete!")
// Here, update your installer state so FinalInstall() can proceed.
inst.DoneDownload = true
}()
}
// FinalInstall is called by the UI to request installation.
// If download is done, it runs immediately, otherwise sets PendingInstall=true.
func (inst *Installer) FinalInstall() {
// Already installed or installing => ignore repeated calls.
if inst.IsInstalling || inst.DoneInstall {
return
}
// If not done downloading, mark that we want to install once finished.
if !inst.DoneDownload {
fmt.Println("Cannot install now: download and decompression not complete -> pending install.")
inst.PendingInstall = true
return
}
// Otherwise, go ahead and install now.
inst.doFinalInstall()
}
// doFinalInstall does the actual installation by invoking InstallUpdates.
func (inst *Installer) doFinalInstall() {
inst.IsInstalling = true
inst.PendingInstall = false // we are fulfilling the install now
go func() {
defer func() {
inst.IsInstalling = false
inst.DoneInstall = (inst.LastError == nil)
}()
spm.UpdateProgress(0, "Installing updates...")
if err := spm.InstallUpdates(); err != nil {
inst.LastError = err
return
}
// Register the app in Windows (i.e. create registry entries)
spm.UpdateProgress(0, "Registering app...")
if err := spm.RegisterApp(); err != nil {
inst.LastError = err
return
}
spm.UpdateProgress(100, "Installation complete!")
}()
}
// PollProgress fetches the latest progress and task from SPM.
func (inst *Installer) PollProgress() {
p, t := spm.GetProgress()
inst.Progress, inst.Task = p, t
}