mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
150 lines
3.3 KiB
Go
150 lines
3.3 KiB
Go
package updates
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sync"
|
|
|
|
"github.com/safing/portbase/log"
|
|
)
|
|
|
|
var (
|
|
stableUpdates = make(map[string]string)
|
|
betaUpdates = make(map[string]string)
|
|
localUpdates = make(map[string]string)
|
|
updatesLock sync.RWMutex
|
|
)
|
|
|
|
// LoadLatest (re)loads the latest available updates from disk.
|
|
func LoadLatest() error {
|
|
newLocalUpdates := make(map[string]string)
|
|
|
|
// all
|
|
prefix := "all"
|
|
new, err1 := ScanForLatest(filepath.Join(updateStorage.Path, prefix), false)
|
|
for key, val := range new {
|
|
newLocalUpdates[filepath.ToSlash(filepath.Join(prefix, key))] = val
|
|
}
|
|
|
|
// os_platform
|
|
prefix = fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
|
|
new, err2 := ScanForLatest(filepath.Join(updateStorage.Path, prefix), false)
|
|
for key, val := range new {
|
|
newLocalUpdates[filepath.ToSlash(filepath.Join(prefix, key))] = val
|
|
}
|
|
|
|
if err1 != nil && err2 != nil {
|
|
return fmt.Errorf("could not load latest update versions: %s, %s", err1, err2)
|
|
}
|
|
|
|
log.Tracef("updates: loading latest updates:")
|
|
|
|
for key, val := range newLocalUpdates {
|
|
log.Tracef("updates: %s v%s", key, val)
|
|
}
|
|
|
|
updatesLock.Lock()
|
|
localUpdates = newLocalUpdates
|
|
updatesLock.Unlock()
|
|
|
|
log.Tracef("updates: load complete")
|
|
|
|
// update version status
|
|
updatesLock.RLock()
|
|
defer updatesLock.RUnlock()
|
|
updateStatus(versionClassLocal, localUpdates)
|
|
|
|
return nil
|
|
}
|
|
|
|
// ScanForLatest scan the local update directory and returns a map of the latest/newest component versions.
|
|
func ScanForLatest(baseDir string, hardFail bool) (latest map[string]string, lastError error) {
|
|
var added int
|
|
latest = make(map[string]string)
|
|
|
|
filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
if !os.IsNotExist(err) {
|
|
lastError = err
|
|
if hardFail {
|
|
return err
|
|
}
|
|
log.Warningf("updates: could not read %s", path)
|
|
}
|
|
return nil
|
|
}
|
|
if !info.IsDir() {
|
|
added++
|
|
}
|
|
|
|
relativePath, err := filepath.Rel(baseDir, path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
relativePath = filepath.ToSlash(relativePath)
|
|
identifierPath, version, ok := GetIdentifierAndVersion(relativePath)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
// add/update index
|
|
storedVersion, ok := latest[identifierPath]
|
|
if ok {
|
|
// FIXME: this will fail on multi-digit version segments!
|
|
// FIXME: use https://github.com/hashicorp/go-version
|
|
if version > storedVersion {
|
|
latest[identifierPath] = version
|
|
}
|
|
} else {
|
|
latest[identifierPath] = version
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if lastError != nil {
|
|
if hardFail {
|
|
return nil, lastError
|
|
}
|
|
if added == 0 {
|
|
return latest, lastError
|
|
}
|
|
}
|
|
return latest, nil
|
|
}
|
|
|
|
// LoadIndexes loads the current update indexes from disk.
|
|
func LoadIndexes() error {
|
|
data, err := ioutil.ReadFile(filepath.Join(updateStorage.Path, "stable.json"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newStableUpdates := make(map[string]string)
|
|
err = json.Unmarshal(data, &newStableUpdates)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(newStableUpdates) == 0 {
|
|
return errors.New("stable.json is empty")
|
|
}
|
|
|
|
log.Tracef("updates: loaded stable.json")
|
|
|
|
updatesLock.Lock()
|
|
stableUpdates = newStableUpdates
|
|
updatesLock.Unlock()
|
|
|
|
// update version status
|
|
updatesLock.RLock()
|
|
defer updatesLock.RUnlock()
|
|
updateStatus(versionClassStable, stableUpdates)
|
|
|
|
return nil
|
|
}
|