271 lines
7.9 KiB
Go
271 lines
7.9 KiB
Go
package updater
|
|
|
|
// import (
|
|
// "errors"
|
|
// "fmt"
|
|
// "os"
|
|
// "path/filepath"
|
|
// "runtime"
|
|
// "strings"
|
|
// "sync"
|
|
|
|
// "github.com/safing/portmaster/base/log"
|
|
// "github.com/safing/portmaster/base/utils"
|
|
// )
|
|
|
|
// const (
|
|
// onWindows = runtime.GOOS == "windows"
|
|
// )
|
|
|
|
// ResourceRegistry is a registry for managing update resources.
|
|
// type ResourceRegistry struct {
|
|
// sync.RWMutex
|
|
|
|
// Name string
|
|
// storageDir *utils.DirStructure
|
|
// tmpDir *utils.DirStructure
|
|
// indexes []*Index
|
|
// state *RegistryState
|
|
|
|
// resources map[string]*Resource
|
|
// UpdateURLs []string
|
|
// UserAgent string
|
|
// MandatoryUpdates []string
|
|
// AutoUnpack []string
|
|
|
|
// // Verification holds a map of VerificationOptions assigned to their
|
|
// // applicable identifier path prefix.
|
|
// // Use an empty string to denote the default.
|
|
// // Use empty options to disable verification for a path prefix.
|
|
// Verification map[string]*VerificationOptions
|
|
|
|
// // UsePreReleases signifies that pre-releases should be used when selecting a
|
|
// // version. Even if false, a pre-release version will still be used if it is
|
|
// // defined as the current version by an index.
|
|
// UsePreReleases bool
|
|
|
|
// // DevMode specifies if a local 0.0.0 version should be always chosen, when available.
|
|
// DevMode bool
|
|
|
|
// // Online specifies if resources may be downloaded if not available locally.
|
|
// Online bool
|
|
|
|
// // StateNotifyFunc may be set to receive any changes to the registry state.
|
|
// // The specified function may lock the state, but may not block or take a
|
|
// // lot of time.
|
|
// StateNotifyFunc func(*RegistryState)
|
|
// }
|
|
|
|
// // AddIndex adds a new index to the resource registry.
|
|
// // The order is important, as indexes added later will override the current
|
|
// // release from earlier indexes.
|
|
// func (reg *ResourceRegistry) AddIndex(idx Index) {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// // Get channel name from path.
|
|
// idx.Channel = strings.TrimSuffix(
|
|
// filepath.Base(idx.Path), filepath.Ext(idx.Path),
|
|
// )
|
|
|
|
// reg.indexes = append(reg.indexes, &idx)
|
|
// }
|
|
|
|
// // PreInitUpdateState sets the initial update state of the registry before initialization.
|
|
// func (reg *ResourceRegistry) PreInitUpdateState(s UpdateState) error {
|
|
// if reg.state != nil {
|
|
// return errors.New("registry already initialized")
|
|
// }
|
|
|
|
// reg.state = &RegistryState{
|
|
// Updates: s,
|
|
// }
|
|
// return nil
|
|
// }
|
|
|
|
// // Initialize initializes a raw registry struct and makes it ready for usage.
|
|
// func (reg *ResourceRegistry) Initialize(storageDir *utils.DirStructure) error {
|
|
// // check if storage dir is available
|
|
// err := storageDir.Ensure()
|
|
// if err != nil {
|
|
// return err
|
|
// }
|
|
|
|
// // set default name
|
|
// if reg.Name == "" {
|
|
// reg.Name = "updater"
|
|
// }
|
|
|
|
// // initialize private attributes
|
|
// reg.storageDir = storageDir
|
|
// reg.tmpDir = storageDir.ChildDir("tmp", 0o0700)
|
|
// reg.resources = make(map[string]*Resource)
|
|
// if reg.state == nil {
|
|
// reg.state = &RegistryState{}
|
|
// }
|
|
// reg.state.ID = StateReady
|
|
// reg.state.reg = reg
|
|
|
|
// // remove tmp dir to delete old entries
|
|
// err = reg.Cleanup()
|
|
// if err != nil {
|
|
// log.Warningf("%s: failed to remove tmp dir: %s", reg.Name, err)
|
|
// }
|
|
|
|
// // (re-)create tmp dir
|
|
// err = reg.tmpDir.Ensure()
|
|
// if err != nil {
|
|
// log.Warningf("%s: failed to create tmp dir: %s", reg.Name, err)
|
|
// }
|
|
|
|
// // Check verification options.
|
|
// if reg.Verification != nil {
|
|
// for prefix, opts := range reg.Verification {
|
|
// // Check if verification is disable for this prefix.
|
|
// if opts == nil {
|
|
// continue
|
|
// }
|
|
|
|
// // If enabled, a trust store is required.
|
|
// if opts.TrustStore == nil {
|
|
// return fmt.Errorf("verification enabled for prefix %q, but no trust store configured", prefix)
|
|
// }
|
|
|
|
// // DownloadPolicy must be equal or stricter than DiskLoadPolicy.
|
|
// if opts.DiskLoadPolicy < opts.DownloadPolicy {
|
|
// return errors.New("verification download policy must be equal or stricter than the disk load policy")
|
|
// }
|
|
|
|
// // Warn if all policies are disabled.
|
|
// if opts.DownloadPolicy == SignaturePolicyDisable &&
|
|
// opts.DiskLoadPolicy == SignaturePolicyDisable {
|
|
// log.Warningf("%s: verification enabled for prefix %q, but all policies set to disable", reg.Name, prefix)
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// return nil
|
|
// }
|
|
|
|
// // StorageDir returns the main storage dir of the resource registry.
|
|
// func (reg *ResourceRegistry) StorageDir() *utils.DirStructure {
|
|
// return reg.storageDir
|
|
// }
|
|
|
|
// // TmpDir returns the temporary working dir of the resource registry.
|
|
// func (reg *ResourceRegistry) TmpDir() *utils.DirStructure {
|
|
// return reg.tmpDir
|
|
// }
|
|
|
|
// // SetDevMode sets the development mode flag.
|
|
// func (reg *ResourceRegistry) SetDevMode(on bool) {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// reg.DevMode = on
|
|
// }
|
|
|
|
// // SetUsePreReleases sets the UsePreReleases flag.
|
|
// func (reg *ResourceRegistry) SetUsePreReleases(yes bool) {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// reg.UsePreReleases = yes
|
|
// }
|
|
|
|
// // AddResource adds a resource to the registry. Does _not_ select new version.
|
|
// func (reg *ResourceRegistry) AddResource(identifier, version string, index *Index, available, currentRelease, preRelease bool) error {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// err := reg.addResource(identifier, version, index, available, currentRelease, preRelease)
|
|
// return err
|
|
// }
|
|
|
|
// func (reg *ResourceRegistry) addResource(identifier, version string, index *Index, available, currentRelease, preRelease bool) error {
|
|
// res, ok := reg.resources[identifier]
|
|
// if !ok {
|
|
// res = reg.newResource(identifier)
|
|
// reg.resources[identifier] = res
|
|
// }
|
|
// res.Index = index
|
|
|
|
// return res.AddVersion(version, available, currentRelease, preRelease)
|
|
// }
|
|
|
|
// // AddResources adds resources to the registry. Errors are logged, the last one is returned. Despite errors, non-failing resources are still added. Does _not_ select new versions.
|
|
// func (reg *ResourceRegistry) AddResources(versions map[string]string, index *Index, available, currentRelease, preRelease bool) error {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// // add versions and their flags to registry
|
|
// var lastError error
|
|
// for identifier, version := range versions {
|
|
// lastError = reg.addResource(identifier, version, index, available, currentRelease, preRelease)
|
|
// if lastError != nil {
|
|
// log.Warningf("%s: failed to add resource %s: %s", reg.Name, identifier, lastError)
|
|
// }
|
|
// }
|
|
|
|
// return lastError
|
|
// }
|
|
|
|
// // SelectVersions selects new resource versions depending on the current registry state.
|
|
// func (reg *ResourceRegistry) SelectVersions() {
|
|
// reg.RLock()
|
|
// defer reg.RUnlock()
|
|
|
|
// for _, res := range reg.resources {
|
|
// res.Lock()
|
|
// res.selectVersion()
|
|
// res.Unlock()
|
|
// }
|
|
// }
|
|
|
|
// // GetSelectedVersions returns a list of the currently selected versions.
|
|
// func (reg *ResourceRegistry) GetSelectedVersions() (versions map[string]string) {
|
|
// reg.RLock()
|
|
// defer reg.RUnlock()
|
|
|
|
// for _, res := range reg.resources {
|
|
// res.Lock()
|
|
// versions[res.Identifier] = res.SelectedVersion.VersionNumber
|
|
// res.Unlock()
|
|
// }
|
|
|
|
// return
|
|
// }
|
|
|
|
// // Purge deletes old updates, retaining a certain amount, specified by the keep
|
|
// // parameter. Will at least keep 2 updates per resource.
|
|
// func (reg *ResourceRegistry) Purge(keep int) {
|
|
// reg.RLock()
|
|
// defer reg.RUnlock()
|
|
|
|
// for _, res := range reg.resources {
|
|
// res.Purge(keep)
|
|
// }
|
|
// }
|
|
|
|
// // ResetResources removes all resources from the registry.
|
|
// func (reg *ResourceRegistry) ResetResources() {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// reg.resources = make(map[string]*Resource)
|
|
// }
|
|
|
|
// // ResetIndexes removes all indexes from the registry.
|
|
// func (reg *ResourceRegistry) ResetIndexes() {
|
|
// reg.Lock()
|
|
// defer reg.Unlock()
|
|
|
|
// reg.indexes = make([]*Index, 0, len(reg.indexes))
|
|
// }
|
|
|
|
// // Cleanup removes temporary files.
|
|
// func (reg *ResourceRegistry) Cleanup() error {
|
|
// // delete download tmp dir
|
|
// return os.RemoveAll(reg.tmpDir.Path)
|
|
// }
|