Files
portmaster/service/updates/index.go
Vladimir Stoilov abf444630b [WIP] New updater
2024-09-05 10:25:57 +03:00

111 lines
2.4 KiB
Go

package updates
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"github.com/safing/portmaster/base/log"
)
type UpdateIndex struct {
Directory string
DownloadDirectory string
Ignore []string
IndexURLs []string
IndexFile string
AutoApply bool
}
func (ui *UpdateIndex) downloadIndexFile() (err error) {
_ = os.MkdirAll(ui.Directory, defaultDirMode)
_ = os.MkdirAll(ui.DownloadDirectory, defaultDirMode)
for _, url := range ui.IndexURLs {
err = ui.downloadIndexFileFromURL(url)
if err != nil {
log.Warningf("updates: %s", err)
continue
}
// Downloading was successful.
err = nil
break
}
return
}
func (ui *UpdateIndex) checkForUpdates() (bool, error) {
err := ui.downloadIndexFile()
if err != nil {
return false, err
}
currentBundle, err := ui.GetInstallBundle()
if err != nil {
return true, err // Current installed bundle not found, act as there is update.
}
updateBundle, err := ui.GetUpdateBundle()
if err != nil {
return false, err
}
return currentBundle.Version != updateBundle.Version, nil
}
func (ui *UpdateIndex) downloadIndexFileFromURL(url string) error {
client := http.Client{}
resp, err := client.Get(url)
if err != nil {
return fmt.Errorf("failed a get request to %s: %w", url, err)
}
defer func() { _ = resp.Body.Close() }()
filePath := fmt.Sprintf("%s/%s", ui.DownloadDirectory, ui.IndexFile)
file, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, defaultFileMode)
if err != nil {
return err
}
defer func() { _ = file.Close() }()
_, err = io.Copy(file, resp.Body)
if err != nil {
return err
}
return nil
}
func (ui *UpdateIndex) GetInstallBundle() (*Bundle, error) {
indexFile := fmt.Sprintf("%s/%s", ui.Directory, ui.IndexFile)
return ui.GetBundle(indexFile)
}
func (ui *UpdateIndex) GetUpdateBundle() (*Bundle, error) {
indexFile := fmt.Sprintf("%s/%s", ui.DownloadDirectory, ui.IndexFile)
return ui.GetBundle(indexFile)
}
func (ui *UpdateIndex) GetBundle(indexFile string) (*Bundle, error) {
// Check if the file exists.
file, err := os.Open(indexFile)
if err != nil {
return nil, fmt.Errorf("failed to open index file: %w", err)
}
defer func() { _ = file.Close() }()
// Read
content, err := io.ReadAll(file)
if err != nil {
return nil, err
}
// Parse
var bundle Bundle
err = json.Unmarshal(content, &bundle)
if err != nil {
return nil, err
}
return &bundle, nil
}