Init
This commit is contained in:
commit
d9dae02ffc
17 changed files with 1742 additions and 0 deletions
263
main.go
Normal file
263
main.go
Normal file
|
@ -0,0 +1,263 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
// Import your SPM-based installer code
|
||||
"spitfire-luncher/spm"
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// GLOBALS
|
||||
// -------------------------------------------------------------------
|
||||
var (
|
||||
copyingInProgress int32
|
||||
updateStatusMsg string
|
||||
browserCmd *exec.Cmd
|
||||
browserMutex sync.Mutex // Protects the lock file map
|
||||
isBackgroundMode bool
|
||||
)
|
||||
|
||||
// StateFile holds the update state from INI
|
||||
type StateFile struct {
|
||||
IsUpdating bool
|
||||
Progress int32
|
||||
Stage string // "Idle","Downloading","Decompressing","ReadyToInstall","Installing","Complete","Failed"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// LOG INIT
|
||||
// -------------------------------------------------------------------
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("[UPDATER] ")
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// INI Helpers
|
||||
// -------------------------------------------------------------------
|
||||
func getSpmDir() string {
|
||||
installDir, err := spm.GetDefaultInstallDir()
|
||||
if err != nil {
|
||||
log.Println("Warning: Using '.' for spmDir =>", err)
|
||||
return "."
|
||||
}
|
||||
spmDir := filepath.Join(installDir, "spm")
|
||||
_ = os.MkdirAll(spmDir, 0755)
|
||||
return spmDir
|
||||
}
|
||||
|
||||
func getStateFilePath() string {
|
||||
return filepath.Join(getSpmDir(), "update_state.ini")
|
||||
}
|
||||
|
||||
func WriteState(isUpdating bool, progress int32, stage string) {
|
||||
content := "[UpdateState]\n" +
|
||||
fmt.Sprintf("IsUpdating=%v\n", isUpdating) +
|
||||
fmt.Sprintf("Progress=%d\n", progress) +
|
||||
fmt.Sprintf("Stage=%s\n", stage)
|
||||
_ = os.WriteFile(getStateFilePath(), []byte(content), 0644)
|
||||
}
|
||||
|
||||
func ReadState() StateFile {
|
||||
sf := StateFile{}
|
||||
data, err := os.ReadFile(getStateFilePath())
|
||||
if err != nil {
|
||||
return sf
|
||||
}
|
||||
|
||||
lines := strings.Split(string(data), "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" || strings.HasPrefix(line, "[") {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
val := strings.TrimSpace(parts[1])
|
||||
switch key {
|
||||
case "IsUpdating":
|
||||
sf.IsUpdating = (val == "true")
|
||||
case "Progress":
|
||||
if i, errAtoi := strconv.Atoi(val); errAtoi == nil {
|
||||
sf.Progress = int32(i)
|
||||
}
|
||||
case "Stage":
|
||||
sf.Stage = val
|
||||
}
|
||||
}
|
||||
return sf
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// BROWSER
|
||||
// -------------------------------------------------------------------
|
||||
// LaunchBrowser starts the browser and creates a unique lock file in the spmdir.
|
||||
func LaunchBrowser() {
|
||||
spmDir := getSpmDir()
|
||||
|
||||
// Generate a unique lock file name (based on timestamp)
|
||||
lockFileName := fmt.Sprintf("browser_lock_%d.lock", time.Now().UnixNano())
|
||||
lockFilePath := filepath.Join(spmDir, lockFileName)
|
||||
|
||||
// Create the lock file
|
||||
file, err := os.Create(lockFilePath)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to create lock file:", err)
|
||||
return
|
||||
}
|
||||
file.Close()
|
||||
|
||||
// Run the browser process and wait for it to finish
|
||||
fmt.Println("Starting browser...")
|
||||
err = spm.RunAndWait()
|
||||
if err != nil {
|
||||
fmt.Println("Browser process encountered an error:", err)
|
||||
}
|
||||
|
||||
// Remove the lock file after the browser finishes
|
||||
fmt.Printf("Removing lock file: %s\n", lockFilePath)
|
||||
err = os.Remove(lockFilePath)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to remove lock file:", err)
|
||||
} else {
|
||||
fmt.Println("Lock file removed successfully.")
|
||||
}
|
||||
}
|
||||
|
||||
// IsBrowserRunning checks if there are any browser lock files in the spmdir.
|
||||
func IsBrowserRunning() bool {
|
||||
spmDir := getSpmDir()
|
||||
|
||||
// Look for lock files in the spmdir
|
||||
lockFiles, err := filepath.Glob(filepath.Join(spmDir, "browser_lock_*.lock"))
|
||||
if err != nil {
|
||||
fmt.Println("Error checking for lock files:", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Return true if at least one lock file is found
|
||||
return len(lockFiles) > 0
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// BACKGROUND SERVICE
|
||||
// -------------------------------------------------------------------
|
||||
func runBackgroundUpdater() {
|
||||
// Delete the update_state.ini file on startup
|
||||
stateFilePath := getStateFilePath()
|
||||
if _, err := os.Stat(stateFilePath); err == nil {
|
||||
err = os.Remove(stateFilePath)
|
||||
if err != nil {
|
||||
log.Printf("Failed to delete state file %s: %v\n", stateFilePath, err)
|
||||
} else {
|
||||
log.Printf("Deleted state file: %s\n", stateFilePath)
|
||||
}
|
||||
} else {
|
||||
log.Printf("State file does not exist, no need to delete: %s\n", stateFilePath)
|
||||
}
|
||||
|
||||
// Remove all lock files in the spmdir
|
||||
spmDir := getSpmDir()
|
||||
lockFilePattern := filepath.Join(spmDir, "browser_lock_*.lock")
|
||||
lockFiles, err := filepath.Glob(lockFilePattern)
|
||||
if err != nil {
|
||||
log.Printf("Failed to scan for lock files in %s: %v\n", spmDir, err)
|
||||
} else {
|
||||
for _, lockFile := range lockFiles {
|
||||
err := os.Remove(lockFile)
|
||||
if err != nil {
|
||||
log.Printf("Failed to delete lock file %s: %v\n", lockFile, err)
|
||||
} else {
|
||||
log.Printf("Deleted lock file: %s\n", lockFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Background updater started (no GUI).")
|
||||
|
||||
// Start a separate goroutine to periodically update the progress in update_state.ini
|
||||
go func() {
|
||||
for {
|
||||
// Get current progress and task from spm
|
||||
progress, task := spm.GetProgress()
|
||||
|
||||
// Determine if the updater is in "Copying files to install directory" stage
|
||||
isUpdating := task == "Copying files to install directory"
|
||||
|
||||
// Write the state to the update_state.ini file
|
||||
WriteState(isUpdating, int32(progress), task)
|
||||
|
||||
// Sleep for 1 second before updating the progress again
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}()
|
||||
|
||||
// Main loop for periodic AutoDownloadUpdates and AutoInstallUpdates
|
||||
for {
|
||||
// Run AutoDownloadUpdates every 10 seconds
|
||||
err := spm.AutoDownloadUpdates()
|
||||
if err != nil {
|
||||
log.Printf("AutoDownloadUpdates failed: %v\n", err)
|
||||
WriteState(false, 0, fmt.Sprintf("Update failed: %v", err))
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if the browser is running
|
||||
if IsBrowserRunning() {
|
||||
log.Println("Browser is running. Waiting before installing updates.")
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
// If the browser is not running, run AutoInstallUpdates
|
||||
log.Println("\nBrowser is not running. Starting installation of updates.")
|
||||
err = spm.AutoInstallUpdates()
|
||||
if err != nil {
|
||||
log.Printf("AutoInstallUpdates failed: %v\n", err)
|
||||
WriteState(false, 0, fmt.Sprintf("Installation failed: %v", err))
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
// Write to update_state.ini indicating updates are complete
|
||||
WriteState(false, 100, "Complete")
|
||||
log.Println("Updates installed successfully. Waiting before next check.")
|
||||
|
||||
// Wait 10 seconds before checking again
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// MAIN
|
||||
// -------------------------------------------------------------------
|
||||
func main() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "--update-service" {
|
||||
isBackgroundMode = true
|
||||
runBackgroundUpdater()
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("Launcher started (foreground mode).")
|
||||
sf := ReadState()
|
||||
if sf.IsUpdating == true {
|
||||
log.Println("Stage=Installing => show update window.")
|
||||
ShowUpdateWindow()
|
||||
} else {
|
||||
LaunchBrowser()
|
||||
}
|
||||
fmt.Println("Exiting launcher.")
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue