clean up
This commit is contained in:
parent
66f4191c5f
commit
44d20eb983
10 changed files with 319 additions and 72 deletions
12
README.md
12
README.md
|
@ -47,9 +47,9 @@ func main() {
|
|||
}
|
||||
|
||||
// -- Download --
|
||||
// spm.AutoDownloadSpecified(specs) downloads specified packages to temp dir and decompresses them, making them ready for install by running "spm.AutoInstallUpdates()".
|
||||
// spm.DownloadSpecified(specs) downloads specified packages to temp dir and decompresses them, making them ready for install by running "spm.InstallUpdates()".
|
||||
fmt.Println("Starting download and decompression...")
|
||||
if err := spm.AutoDownloadSpecified(specs); err != nil {
|
||||
if err := spm.DownloadSpecified(specs); err != nil {
|
||||
fmt.Println("Error downloading packages:", err)
|
||||
return
|
||||
}
|
||||
|
@ -57,15 +57,15 @@ func main() {
|
|||
fmt.Println("Download complete. Proceeding with installation...")
|
||||
|
||||
// -- Install --
|
||||
// Install and Download are separate as you cannot replace running binaries on Windows. So the final move to the correct folder is done by "spm.AutoInstallUpdates()".
|
||||
if err := spm.AutoInstallUpdates(); err != nil {
|
||||
// Install and Download are separate as you cannot replace running binaries on Windows. So the final move to the correct folder is done by "spm.InstallUpdates()".
|
||||
if err := spm.InstallUpdates(); err != nil {
|
||||
fmt.Println("Error during installation:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// -- Register --
|
||||
// spm.RegisterApp() is primarily used to modify the Windows registry so it recognizes Spitfire Browser as an installed program.
|
||||
// You shouldn’t need to run it more than once during installation. Also this function requires administrative privileges on Windows to work correctly.
|
||||
// spm.RegisterApp() is primarily used to modify the Windows registry so it recognizes Spitfire Browser as an installed program.
|
||||
// You shouldn’t need to run it more than once during installation. Also this function requires administrative privileges on Windows to work correctly.
|
||||
if err := spm.RegisterApp(); err != nil {
|
||||
fmt.Println("Error registering app:", err)
|
||||
return
|
||||
|
|
277
appindex.go
277
appindex.go
|
@ -6,14 +6,46 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
const appIndexURL = "https://downloads.sourceforge.net/project/spitfire-browser/APPINDEX"
|
||||
// AppIndexEntry represents a single entry in an app index.
|
||||
type AppIndexEntry struct {
|
||||
Name string
|
||||
Version string
|
||||
Release string // "nightly" / "stable" / etc.
|
||||
Arch string // e.g. "amd64", "386"
|
||||
OS string // e.g. "windows", "linux"
|
||||
Type string // "browser", "addon", "theme", etc.
|
||||
DownloadURL string
|
||||
}
|
||||
|
||||
func DownloadAppIndex(dest string) error {
|
||||
// RemoteIndex represents a remote APPINDEX repository.
|
||||
type RemoteIndex struct {
|
||||
Name string `json:"name"`
|
||||
Link string `json:"link"`
|
||||
}
|
||||
|
||||
var (
|
||||
// defaultRemoteIndexes holds the default remote index.
|
||||
defaultRemoteIndexes = []RemoteIndex{
|
||||
{
|
||||
Name: "default",
|
||||
Link: "https://downloads.sourceforge.net/project/spitfire-browser/APPINDEX",
|
||||
},
|
||||
}
|
||||
// remoteIndexes holds the current remote indexes in use.
|
||||
remoteIndexes = defaultRemoteIndexes
|
||||
)
|
||||
|
||||
// downloadAppIndex downloads an APPINDEX from the given URL and writes it to dest.
|
||||
func downloadAppIndex(url, dest string) error {
|
||||
UpdateProgress(0, "Downloading APPINDEX")
|
||||
resp, err := http.Get(appIndexURL)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -52,25 +84,10 @@ func DownloadAppIndex(dest string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type AppIndexEntry struct {
|
||||
Name string
|
||||
Version string
|
||||
Release string // "nightly" / "stable" / etc.
|
||||
Arch string // e.g. "amd64", "386"
|
||||
OS string // e.g. "windows", "linux"
|
||||
Type string // "browser", "addon", "theme", etc.
|
||||
DownloadURL string
|
||||
}
|
||||
|
||||
func ParseAppIndex(filePath string) ([]AppIndexEntry, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// parseAppIndexFromReader parses an APPINDEX from any io.Reader.
|
||||
func parseAppIndexFromReader(r io.Reader) ([]AppIndexEntry, error) {
|
||||
var entries []AppIndexEntry
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner := bufio.NewScanner(r)
|
||||
entry := AppIndexEntry{}
|
||||
|
||||
for scanner.Scan() {
|
||||
|
@ -112,12 +129,222 @@ func ParseAppIndex(filePath string) ([]AppIndexEntry, error) {
|
|||
entries = append(entries, entry)
|
||||
}
|
||||
|
||||
// Log all parsed entries
|
||||
fmt.Printf("[INFO] Total parsed entries: %d\n", len(entries))
|
||||
return entries, scanner.Err()
|
||||
}
|
||||
|
||||
// parseAppIndex reads the APPINDEX file at filePath and parses its contents.
|
||||
func parseAppIndex(filePath string) ([]AppIndexEntry, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
entries, err := parseAppIndexFromReader(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("[INFO] Total parsed entries from %s: %d\n", filePath, len(entries))
|
||||
for _, e := range entries {
|
||||
fmt.Printf(" - Name: %s, Release: %s, Type: %s, OS: %s, Arch: %s, Version: %s, URL: %s\n",
|
||||
e.Name, e.Release, e.Type, e.OS, e.Arch, e.Version, e.DownloadURL)
|
||||
}
|
||||
|
||||
return entries, scanner.Err()
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
// saveIndex saves the current list of remote indexes to an INI file located in
|
||||
// the spm directory under installDir, but only if it's different from the default.
|
||||
func saveIndex() error {
|
||||
// Only save if remoteIndexes differs from defaultRemoteIndexes.
|
||||
if len(remoteIndexes) == len(defaultRemoteIndexes) {
|
||||
same := true
|
||||
for i, ri := range remoteIndexes {
|
||||
if ri != defaultRemoteIndexes[i] {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if same {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
installDir, err := GetInstallDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
spmDir := filepath.Join(installDir, "spm")
|
||||
if err := os.MkdirAll(spmDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
filePath := filepath.Join(spmDir, "sources.ini")
|
||||
|
||||
cfg := ini.Empty()
|
||||
sec, err := cfg.NewSection("RemoteIndexes")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Save each remote index as a key/value pair.
|
||||
for _, ri := range remoteIndexes {
|
||||
if _, err := sec.NewKey(ri.Name, ri.Link); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return cfg.SaveTo(filePath)
|
||||
}
|
||||
|
||||
// loadIndex loads the list of remote indexes from an INI file located in
|
||||
// the spm directory under installDir. If the file is missing, it sets remoteIndexes to the default.
|
||||
func loadIndex() error {
|
||||
installDir, err := GetInstallDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
spmDir := filepath.Join(installDir, "spm")
|
||||
filePath := filepath.Join(spmDir, "sources.ini")
|
||||
cfg, err := ini.Load(filePath)
|
||||
if err != nil {
|
||||
// If file is missing or can't be loaded, use the default.
|
||||
remoteIndexes = defaultRemoteIndexes
|
||||
return nil
|
||||
}
|
||||
sec := cfg.Section("RemoteIndexes")
|
||||
var loaded []RemoteIndex
|
||||
for _, key := range sec.Keys() {
|
||||
loaded = append(loaded, RemoteIndex{
|
||||
Name: key.Name(),
|
||||
Link: key.Value(),
|
||||
})
|
||||
}
|
||||
remoteIndexes = loaded
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateIndex downloads fresh APPINDEX files from all remote sources and saves them
|
||||
// into the temp directory. If the app is registered, it loads the remote indexes
|
||||
// from the INI file (or uses the default if not available) and saves them after updating.
|
||||
func UpdateIndex() error {
|
||||
tempDir := GetTempDir()
|
||||
var sources []RemoteIndex
|
||||
if IsRegistered() {
|
||||
// Try to load persisted remote indexes.
|
||||
if err := loadIndex(); err != nil {
|
||||
// If loading fails, fall back to the default remote indexes.
|
||||
sources = defaultRemoteIndexes
|
||||
} else {
|
||||
sources = remoteIndexes
|
||||
}
|
||||
} else {
|
||||
// Not registered: use default remote indexes.
|
||||
sources = defaultRemoteIndexes
|
||||
}
|
||||
|
||||
// Download each APPINDEX file.
|
||||
for _, ri := range sources {
|
||||
localPath := filepath.Join(tempDir, fmt.Sprintf("appindex_%s.txt", ri.Name))
|
||||
if err := downloadAppIndex(ri.Link, localPath); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed downloading %s: %v", ri.Link, err)
|
||||
}
|
||||
}
|
||||
|
||||
// If registered, save the current remote indexes.
|
||||
if IsRegistered() {
|
||||
if err := saveIndex(); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed saving indexes: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetIndex parses APPINDEX data from local files in the temp directory.
|
||||
// If a file is missing, it downloads the corresponding APPINDEX first.
|
||||
// If the app is registered, it loads remote indexes from the INI file.
|
||||
// Otherwise, it uses the default remote index.
|
||||
func GetIndex() ([]AppIndexEntry, error) {
|
||||
var allEntries []AppIndexEntry
|
||||
tempDir := GetTempDir()
|
||||
var sources []RemoteIndex
|
||||
if IsRegistered() {
|
||||
if err := loadIndex(); err != nil {
|
||||
sources = defaultRemoteIndexes
|
||||
} else {
|
||||
sources = remoteIndexes
|
||||
}
|
||||
} else {
|
||||
sources = defaultRemoteIndexes
|
||||
}
|
||||
|
||||
// For each remote source, ensure the APPINDEX file exists (downloading if needed),
|
||||
// then parse its contents.
|
||||
for _, ri := range sources {
|
||||
localPath := filepath.Join(tempDir, fmt.Sprintf("appindex_%s.txt", ri.Name))
|
||||
if _, err := os.Stat(localPath); os.IsNotExist(err) {
|
||||
if err := downloadAppIndex(ri.Link, localPath); err != nil {
|
||||
return nil, fmt.Errorf("[WARN] AppIndex: failed downloading %s: %v", ri.Link, err)
|
||||
}
|
||||
}
|
||||
entries, err := parseAppIndex(localPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[WARN] AppIndex: failed parsing %s: %v", localPath, err)
|
||||
}
|
||||
allEntries = append(allEntries, entries...)
|
||||
}
|
||||
return allEntries, nil
|
||||
}
|
||||
|
||||
// AddIndex adds a new remote index (name and link) into the list,
|
||||
// sorts the list by name, and if the app is registered, saves the updated list.
|
||||
func AddIndex(name, link string) error {
|
||||
// If registered, load current indexes first.
|
||||
if IsRegistered() {
|
||||
if err := loadIndex(); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed loading indexes: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ri := RemoteIndex{
|
||||
Name: name,
|
||||
Link: link,
|
||||
}
|
||||
remoteIndexes = append(remoteIndexes, ri)
|
||||
sort.Slice(remoteIndexes, func(i, j int) bool {
|
||||
return remoteIndexes[i].Name < remoteIndexes[j].Name
|
||||
})
|
||||
|
||||
// If registered, persist the changes.
|
||||
if IsRegistered() {
|
||||
if err := saveIndex(); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed saving indexes: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveIndex removes any remote index with the given name from the list,
|
||||
// and if the app is registered, saves the updated list.
|
||||
func RemoveIndex(name string) error {
|
||||
// If registered, load current indexes first.
|
||||
if IsRegistered() {
|
||||
if err := loadIndex(); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed loading indexes: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var updated []RemoteIndex
|
||||
for _, ri := range remoteIndexes {
|
||||
if ri.Name != name {
|
||||
updated = append(updated, ri)
|
||||
}
|
||||
}
|
||||
remoteIndexes = updated
|
||||
|
||||
// If registered, persist the changes.
|
||||
if IsRegistered() {
|
||||
if err := saveIndex(); err != nil {
|
||||
return fmt.Errorf("[WARN] AppIndex: failed saving indexes: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
38
auto.go
38
auto.go
|
@ -2,7 +2,6 @@ package spm
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
|
@ -10,22 +9,19 @@ import (
|
|||
// but not yet moved to the final install location, cuz Windows has this stupid file locking mechanism
|
||||
var pendingUpdates []AppIndexEntry
|
||||
|
||||
// AutoDownloadUpdates downloads the APPINDEX file, parses it, compares against
|
||||
// DownloadUpdates downloads the APPINDEX file, parses it, compares against
|
||||
// currently installed packages, and if it finds a newer version, downloads
|
||||
// and decompresses it into a temporary folder. The result is stored in pendingUpdates, so it can be used by AutoInstallUpdates().
|
||||
func AutoDownloadUpdates() error {
|
||||
// and decompresses it into a temporary folder. The result is stored in pendingUpdates, so it can be used by InstallUpdates().
|
||||
func DownloadUpdates() error {
|
||||
// 1) Download the APPINDEX file to a temporary location
|
||||
appIndexPath := filepath.Join(os.TempDir(), "APPINDEX")
|
||||
fmt.Println("[INFO] Starting APPINDEX download to:", appIndexPath)
|
||||
err := DownloadAppIndex(appIndexPath)
|
||||
err := UpdateIndex()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] Failed to download APPINDEX: %w", err)
|
||||
}
|
||||
fmt.Println("[INFO] APPINDEX downloaded successfully")
|
||||
|
||||
// 2) Parse the APPINDEX file
|
||||
fmt.Println("[INFO] Parsing APPINDEX file:", appIndexPath)
|
||||
entries, err := ParseAppIndex(appIndexPath)
|
||||
entries, err := GetIndex()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] Failed to parse APPINDEX: %w", err)
|
||||
}
|
||||
|
@ -84,7 +80,7 @@ func AutoDownloadUpdates() error {
|
|||
downloadDir := GetTempDir()
|
||||
fmt.Printf("[INFO] Downloading package '%s' to temporary folder: %s\n", matchingEntry.Name, downloadDir)
|
||||
|
||||
err = DownloadPackageFromAppIndex(appIndexPath, matchingEntry.Name, matchingEntry.Release, matchingEntry.Type, downloadDir)
|
||||
err = DownloadPackageFromAppIndex(matchingEntry.Name, matchingEntry.Release, matchingEntry.Type, downloadDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] Failed to download package '%s': %w", matchingEntry.Name, err)
|
||||
}
|
||||
|
@ -99,7 +95,7 @@ func AutoDownloadUpdates() error {
|
|||
}
|
||||
fmt.Printf("[INFO] Package '%s' decompressed successfully to: %s\n", matchingEntry.Name, tempDir)
|
||||
|
||||
// 7) Store in pendingUpdates so that AutoInstallUpdates can finish the job
|
||||
// 7) Store in pendingUpdates so that InstallUpdates can finish the job
|
||||
fmt.Printf("[INFO] Adding '%s' to pending updates\n", matchingEntry.Name)
|
||||
pendingUpdates = append(pendingUpdates, AppIndexEntry{
|
||||
Name: matchingEntry.Name,
|
||||
|
@ -111,13 +107,13 @@ func AutoDownloadUpdates() error {
|
|||
})
|
||||
}
|
||||
|
||||
fmt.Println("[INFO] AutoDownloadUpdates completed successfully")
|
||||
fmt.Println("[INFO] DownloadUpdates completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// AutoInstallUpdates installs any packages that were downloaded and decompressed by AutoDownloadUpdates.
|
||||
// InstallUpdates installs any packages that were downloaded and decompressed by DownloadUpdates.
|
||||
// It moves files from their temp directories to the final location and updates installed.ini.
|
||||
func AutoInstallUpdates() error {
|
||||
func InstallUpdates() error {
|
||||
installDir, err := GetInstallDir()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -146,7 +142,7 @@ func AutoInstallUpdates() error {
|
|||
}
|
||||
|
||||
// 5) Finalize
|
||||
err = FinalizeInstall(entry.Name, entry.Release, entry.Version, entry.Arch, entry.OS)
|
||||
err = finalizeInstall(entry.Name, entry.Release, entry.Version, entry.Arch, entry.OS)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to finalize install for %s: %w", entry.Name, err)
|
||||
}
|
||||
|
@ -156,18 +152,15 @@ func AutoInstallUpdates() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func AutoDownloadSpecified(specs []AppIndexEntry) error {
|
||||
func DownloadSpecified(specs []AppIndexEntry) error {
|
||||
// 1) Download the APPINDEX file to a temporary location
|
||||
appIndexPath := filepath.Join(os.TempDir(), "APPINDEX")
|
||||
fmt.Println("[INFO] Starting APPINDEX download to:", appIndexPath)
|
||||
if err := DownloadAppIndex(appIndexPath); err != nil {
|
||||
if err := UpdateIndex(); err != nil {
|
||||
return fmt.Errorf("[ERROR] Failed to download APPINDEX: %w", err)
|
||||
}
|
||||
fmt.Println("[INFO] APPINDEX downloaded successfully")
|
||||
|
||||
// 2) Parse the APPINDEX file
|
||||
fmt.Println("[INFO] Parsing APPINDEX file:", appIndexPath)
|
||||
entries, err := ParseAppIndex(appIndexPath)
|
||||
entries, err := GetIndex()
|
||||
if err != nil {
|
||||
return fmt.Errorf("[ERROR] Failed to parse APPINDEX: %w", err)
|
||||
}
|
||||
|
@ -225,7 +218,6 @@ func AutoDownloadSpecified(specs []AppIndexEntry) error {
|
|||
downloadDir := GetTempDir()
|
||||
fmt.Printf("[INFO] Downloading package '%s' to temporary folder: %s\n", matchingEntry.Name, downloadDir)
|
||||
if err := DownloadPackageFromAppIndex(
|
||||
appIndexPath,
|
||||
matchingEntry.Name,
|
||||
matchingEntry.Release,
|
||||
matchingEntry.Type,
|
||||
|
@ -251,7 +243,7 @@ func AutoDownloadSpecified(specs []AppIndexEntry) error {
|
|||
}
|
||||
fmt.Printf("[INFO] Package '%s' decompressed successfully to: %s\n", matchingEntry.Name, tempDir)
|
||||
|
||||
// 7) Store in pendingUpdates for AutoInstallUpdates
|
||||
// 7) Store in pendingUpdates for InstallUpdates
|
||||
fmt.Printf("[INFO] Adding '%s' to pending updates\n", matchingEntry.Name)
|
||||
pendingUpdates = append(pendingUpdates, *matchingEntry)
|
||||
}
|
||||
|
|
|
@ -108,7 +108,11 @@ func decompressTarGz(srcFile, destDir string, updateProgress func(int, string))
|
|||
// Update progress after extracting each file.
|
||||
if updateProgress != nil {
|
||||
percent := int((progressReader.BytesRead * 100) / totalSize)
|
||||
updateProgress(percent, fmt.Sprintf("Extracted: %s", header.Name))
|
||||
name := header.Name
|
||||
if len(name) > 50 {
|
||||
name = name[len(name)-50:]
|
||||
}
|
||||
updateProgress(percent, fmt.Sprintf("Extracted: %s", name))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
10
download.go
10
download.go
|
@ -11,9 +11,9 @@ import (
|
|||
)
|
||||
|
||||
// DownloadPackageFromAppIndex selects and downloads the correct package from the APPINDEX.
|
||||
func DownloadPackageFromAppIndex(appIndexPath string, packageName string, release string, pkgType string, destDir string) error {
|
||||
func DownloadPackageFromAppIndex(packageName string, release string, pkgType string, destDir string) error {
|
||||
// Parse the APPINDEX
|
||||
entries, err := ParseAppIndex(appIndexPath)
|
||||
entries, err := GetIndex()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse APPINDEX: %w", err)
|
||||
}
|
||||
|
@ -99,8 +99,8 @@ func DownloadPackageFromAppIndex(appIndexPath string, packageName string, releas
|
|||
|
||||
expectedFilePath := filepath.Join(destDir, expectedFileName)
|
||||
|
||||
// I dont know why is this happening, I dont want to know but sometimes some process is helding up the donwloaded files so thats why it retries here
|
||||
maxRetries := 5
|
||||
// I dont know why is this happening, I dont want to know but sometimes some process is helding up the downloaded files so thats why it retries here
|
||||
maxRetries := 10
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
err = os.Rename(downloadedFilePath, expectedFilePath)
|
||||
if err == nil {
|
||||
|
@ -115,7 +115,7 @@ func DownloadPackageFromAppIndex(appIndexPath string, packageName string, releas
|
|||
f.Close()
|
||||
|
||||
if i < maxRetries-1 {
|
||||
time.Sleep(500 * time.Millisecond) // Wait before retrying
|
||||
time.Sleep(250 * time.Millisecond) // Wait before retrying
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,8 +287,8 @@ func copyFile(src, dst string) error {
|
|||
return os.Chmod(dst, info.Mode())
|
||||
}
|
||||
|
||||
// FinalizeInstall finalizes the installation by updating installed.ini.
|
||||
func FinalizeInstall(packageName, release, version, arch, osName string) error {
|
||||
// finalizeInstall finalizes the installation by updating installed.ini.
|
||||
func finalizeInstall(packageName, release, version, arch, osName string) error {
|
||||
installDir, err := GetInstallDir()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
package spm
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// RegisterApp is not supported on non-Windows platforms.
|
||||
func RegisterApp() error {
|
||||
|
@ -15,3 +19,19 @@ func RegisterApp() error {
|
|||
func UnregisterApp() error {
|
||||
return fmt.Errorf("UnregisterApp is only available on Windows")
|
||||
}
|
||||
|
||||
// IsRegistered returns true if the application is detected as installed.
|
||||
// On Linux, we assume it is installed if the main executable exists in the install directory.
|
||||
func IsRegistered() bool {
|
||||
installDir, err := GetInstallDir()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Assume the executable is named "spitfire" and is located in installDir.
|
||||
exePath := filepath.Join(installDir, "browser", "spitfire")
|
||||
if _, err := os.Stat(exePath); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
// RegisterApp writes the necessary registry keys, making it appear as offically installed app
|
||||
// RegisterApp writes the necessary registry keys, making it appear as officially installed app
|
||||
func RegisterApp() error {
|
||||
exePath, err := GetInstallDir()
|
||||
if err != nil {
|
||||
|
@ -133,3 +133,15 @@ func deleteRegistryTree(root registry.Key, path string) error {
|
|||
// Finally, delete the (now empty) key.
|
||||
return registry.DeleteKey(root, path)
|
||||
}
|
||||
|
||||
// IsRegistered returns true if the application is registered (installed) in the registry.
|
||||
func IsRegistered() bool {
|
||||
// Try to open the uninstall key with read-only access.
|
||||
key, err := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Uninstall\SpitfireBrowser`, registry.READ)
|
||||
if err != nil {
|
||||
// If the key cannot be opened, assume the app is not registered.
|
||||
return false
|
||||
}
|
||||
defer key.Close()
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
@ -21,9 +20,6 @@ func Run() error {
|
|||
}
|
||||
|
||||
exePath := filepath.Join(installDir, "browser", "spitfire.exe")
|
||||
if runtime.GOOS != "windows" {
|
||||
exePath = filepath.Join(installDir, "browser", "spitfire")
|
||||
}
|
||||
|
||||
cmd := exec.Command(exePath)
|
||||
cmd.Dir = filepath.Join(installDir, "browser")
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
@ -21,9 +20,6 @@ func Run() error {
|
|||
}
|
||||
|
||||
exePath := filepath.Join(installDir, "browser", "spitfire.exe")
|
||||
if runtime.GOOS != "windows" {
|
||||
exePath = filepath.Join(installDir, "browser", "spitfire")
|
||||
}
|
||||
|
||||
cmd := exec.Command(exePath)
|
||||
cmd.Dir = filepath.Join(installDir, "browser")
|
||||
|
|
Loading…
Add table
Reference in a new issue