[WIP] New updater first working prototype

This commit is contained in:
Vladimir Stoilov
2024-08-16 16:05:01 +03:00
parent abf444630b
commit 9bae1afd73
46 changed files with 4107 additions and 4149 deletions

View File

@@ -1,238 +1,237 @@
package updates
import (
"fmt"
"sort"
"strings"
"sync"
// import (
// "fmt"
// "sort"
// "sync"
"github.com/safing/portmaster/base/database/record"
"github.com/safing/portmaster/base/info"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
"github.com/safing/portmaster/base/utils/debug"
"github.com/safing/portmaster/service/mgr"
"github.com/safing/portmaster/service/updates/helper"
)
// "github.com/safing/portmaster/base/database/record"
// "github.com/safing/portmaster/base/info"
// "github.com/safing/portmaster/base/log"
// "github.com/safing/portmaster/base/updater"
// "github.com/safing/portmaster/base/utils/debug"
// "github.com/safing/portmaster/service/mgr"
// "github.com/safing/portmaster/service/updates/helper"
// )
const (
// versionsDBKey is the database key for update version information.
versionsDBKey = "core:status/versions"
// const (
// // versionsDBKey is the database key for update version information.
// versionsDBKey = "core:status/versions"
// versionsDBKey is the database key for simple update version information.
simpleVersionsDBKey = "core:status/simple-versions"
// // versionsDBKey is the database key for simple update version information.
// simpleVersionsDBKey = "core:status/simple-versions"
// updateStatusDBKey is the database key for update status information.
updateStatusDBKey = "core:status/updates"
)
// // updateStatusDBKey is the database key for update status information.
// updateStatusDBKey = "core:status/updates"
// )
// Versions holds update versions and status information.
type Versions struct {
record.Base
sync.Mutex
// // Versions holds update versions and status information.
// type Versions struct {
// record.Base
// sync.Mutex
Core *info.Info
Resources map[string]*updater.Resource
Channel string
Beta bool
Staging bool
}
// Core *info.Info
// Resources map[string]*updater.Resource
// Channel string
// Beta bool
// Staging bool
// }
// SimpleVersions holds simplified update versions and status information.
type SimpleVersions struct {
record.Base
sync.Mutex
// // SimpleVersions holds simplified update versions and status information.
// type SimpleVersions struct {
// record.Base
// sync.Mutex
Build *info.Info
Resources map[string]*SimplifiedResourceVersion
Channel string
}
// Build *info.Info
// Resources map[string]*SimplifiedResourceVersion
// Channel string
// }
// SimplifiedResourceVersion holds version information about one resource.
type SimplifiedResourceVersion struct {
Version string
}
// // SimplifiedResourceVersion holds version information about one resource.
// type SimplifiedResourceVersion struct {
// Version string
// }
// UpdateStateExport is a wrapper to export the updates state.
type UpdateStateExport struct {
record.Base
sync.Mutex
// // UpdateStateExport is a wrapper to export the updates state.
// type UpdateStateExport struct {
// record.Base
// sync.Mutex
*updater.UpdateState
}
// *updater.UpdateState
// }
// GetVersions returns the update versions and status information.
// Resources must be locked when accessed.
func GetVersions() *Versions {
return &Versions{
Core: info.GetInfo(),
Resources: registry.Export(),
Channel: initialReleaseChannel,
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
}
}
// // GetVersions returns the update versions and status information.
// // Resources must be locked when accessed.
// func GetVersions() *Versions {
// return &Versions{
// Core: info.GetInfo(),
// Resources: nil,
// Channel: initialReleaseChannel,
// Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
// Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
// }
// }
// GetSimpleVersions returns the simplified update versions and status information.
func GetSimpleVersions() *SimpleVersions {
// Fill base info.
v := &SimpleVersions{
Build: info.GetInfo(),
Resources: make(map[string]*SimplifiedResourceVersion),
Channel: initialReleaseChannel,
}
// // GetSimpleVersions returns the simplified update versions and status information.
// func GetSimpleVersions() *SimpleVersions {
// // Fill base info.
// v := &SimpleVersions{
// Build: info.GetInfo(),
// Resources: make(map[string]*SimplifiedResourceVersion),
// Channel: initialReleaseChannel,
// }
// Iterate through all versions and add version info.
for id, resource := range registry.Export() {
func() {
resource.Lock()
defer resource.Unlock()
// // Iterate through all versions and add version info.
// // for id, resource := range registry.Export() {
// // func() {
// // resource.Lock()
// // defer resource.Unlock()
// Get current in-used or selected version.
var rv *updater.ResourceVersion
switch {
case resource.ActiveVersion != nil:
rv = resource.ActiveVersion
case resource.SelectedVersion != nil:
rv = resource.SelectedVersion
}
// // // Get current in-used or selected version.
// // var rv *updater.ResourceVersion
// // switch {
// // case resource.ActiveVersion != nil:
// // rv = resource.ActiveVersion
// // case resource.SelectedVersion != nil:
// // rv = resource.SelectedVersion
// // }
// Get information from resource.
if rv != nil {
v.Resources[id] = &SimplifiedResourceVersion{
Version: rv.VersionNumber,
}
}
}()
}
// // // Get information from resource.
// // if rv != nil {
// // v.Resources[id] = &SimplifiedResourceVersion{
// // Version: rv.VersionNumber,
// // }
// // }
// // }()
// // }
return v
}
// return v
// }
// GetStateExport gets the update state from the registry and returns it in an
// exportable struct.
func GetStateExport() *UpdateStateExport {
export := registry.GetState()
return &UpdateStateExport{
UpdateState: &export.Updates,
}
}
// // GetStateExport gets the update state from the registry and returns it in an
// // exportable struct.
// func GetStateExport() *UpdateStateExport {
// // export := registry.GetState()
// return &UpdateStateExport{
// // UpdateState: &export.Updates,
// }
// }
// LoadStateExport loads the exported update state from the database.
func LoadStateExport() (*UpdateStateExport, error) {
r, err := db.Get(updateStatusDBKey)
if err != nil {
return nil, err
}
// // LoadStateExport loads the exported update state from the database.
// func LoadStateExport() (*UpdateStateExport, error) {
// r, err := db.Get(updateStatusDBKey)
// if err != nil {
// return nil, err
// }
// unwrap
if r.IsWrapped() {
// only allocate a new struct, if we need it
newRecord := &UpdateStateExport{}
err = record.Unwrap(r, newRecord)
if err != nil {
return nil, err
}
return newRecord, nil
}
// // unwrap
// if r.IsWrapped() {
// // only allocate a new struct, if we need it
// newRecord := &UpdateStateExport{}
// err = record.Unwrap(r, newRecord)
// if err != nil {
// return nil, err
// }
// return newRecord, nil
// }
// or adjust type
newRecord, ok := r.(*UpdateStateExport)
if !ok {
return nil, fmt.Errorf("record not of type *UpdateStateExport, but %T", r)
}
return newRecord, nil
}
// // or adjust type
// newRecord, ok := r.(*UpdateStateExport)
// if !ok {
// return nil, fmt.Errorf("record not of type *UpdateStateExport, but %T", r)
// }
// return newRecord, nil
// }
func initVersionExport() (err error) {
if err := GetVersions().save(); err != nil {
log.Warningf("updates: failed to export version information: %s", err)
}
if err := GetSimpleVersions().save(); err != nil {
log.Warningf("updates: failed to export version information: %s", err)
}
// func initVersionExport() (err error) {
// if err := GetVersions().save(); err != nil {
// log.Warningf("updates: failed to export version information: %s", err)
// }
// if err := GetSimpleVersions().save(); err != nil {
// log.Warningf("updates: failed to export version information: %s", err)
// }
module.EventVersionsUpdated.AddCallback("export version status", export)
return nil
}
// // module.EventVersionsUpdated.AddCallback("export version status", export)
// return nil
// }
func (v *Versions) save() error {
if !v.KeyIsSet() {
v.SetKey(versionsDBKey)
}
return db.Put(v)
}
// func (v *Versions) save() error {
// if !v.KeyIsSet() {
// v.SetKey(versionsDBKey)
// }
// return db.Put(v)
// }
func (v *SimpleVersions) save() error {
if !v.KeyIsSet() {
v.SetKey(simpleVersionsDBKey)
}
return db.Put(v)
}
// func (v *SimpleVersions) save() error {
// if !v.KeyIsSet() {
// v.SetKey(simpleVersionsDBKey)
// }
// return db.Put(v)
// }
func (s *UpdateStateExport) save() error {
if !s.KeyIsSet() {
s.SetKey(updateStatusDBKey)
}
return db.Put(s)
}
// func (s *UpdateStateExport) save() error {
// if !s.KeyIsSet() {
// s.SetKey(updateStatusDBKey)
// }
// return db.Put(s)
// }
// export is an event hook.
func export(_ *mgr.WorkerCtx, _ struct{}) (cancel bool, err error) {
// Export versions.
if err := GetVersions().save(); err != nil {
return false, err
}
if err := GetSimpleVersions().save(); err != nil {
return false, err
}
// Export udpate state.
if err := GetStateExport().save(); err != nil {
return false, err
}
// // export is an event hook.
// func export(_ *mgr.WorkerCtx, _ struct{}) (cancel bool, err error) {
// // Export versions.
// if err := GetVersions().save(); err != nil {
// return false, err
// }
// if err := GetSimpleVersions().save(); err != nil {
// return false, err
// }
// // Export udpate state.
// if err := GetStateExport().save(); err != nil {
// return false, err
// }
return false, nil
}
// return false, nil
// }
// AddToDebugInfo adds the update system status to the given debug.Info.
func AddToDebugInfo(di *debug.Info) {
// Get resources from registry.
resources := registry.Export()
platformPrefix := helper.PlatformIdentifier("")
// // AddToDebugInfo adds the update system status to the given debug.Info.
// func AddToDebugInfo(di *debug.Info) {
// // Get resources from registry.
// // resources := registry.Export()
// // platformPrefix := helper.PlatformIdentifier("")
// Collect data for debug info.
var active, selected []string
var activeCnt, totalCnt int
for id, r := range resources {
// Ignore resources for other platforms.
if !strings.HasPrefix(id, "all/") && !strings.HasPrefix(id, platformPrefix) {
continue
}
// // Collect data for debug info.
// var active, selected []string
// var activeCnt, totalCnt int
// // for id, r := range resources {
// // // Ignore resources for other platforms.
// // if !strings.HasPrefix(id, "all/") && !strings.HasPrefix(id, platformPrefix) {
// // continue
// // }
totalCnt++
if r.ActiveVersion != nil {
activeCnt++
active = append(active, fmt.Sprintf("%s: %s", id, r.ActiveVersion.VersionNumber))
}
if r.SelectedVersion != nil {
selected = append(selected, fmt.Sprintf("%s: %s", id, r.SelectedVersion.VersionNumber))
}
}
sort.Strings(active)
sort.Strings(selected)
// // totalCnt++
// // if r.ActiveVersion != nil {
// // activeCnt++
// // active = append(active, fmt.Sprintf("%s: %s", id, r.ActiveVersion.VersionNumber))
// // }
// // if r.SelectedVersion != nil {
// // selected = append(selected, fmt.Sprintf("%s: %s", id, r.SelectedVersion.VersionNumber))
// // }
// // }
// sort.Strings(active)
// sort.Strings(selected)
// Compile to one list.
lines := make([]string, 0, len(active)+len(selected)+3)
lines = append(lines, "Active:")
lines = append(lines, active...)
lines = append(lines, "")
lines = append(lines, "Selected:")
lines = append(lines, selected...)
// // Compile to one list.
// lines := make([]string, 0, len(active)+len(selected)+3)
// lines = append(lines, "Active:")
// lines = append(lines, active...)
// lines = append(lines, "")
// lines = append(lines, "Selected:")
// lines = append(lines, selected...)
// Add section.
di.AddSection(
fmt.Sprintf("Updates: %s (%d/%d)", initialReleaseChannel, activeCnt, totalCnt),
debug.UseCodeSection|debug.AddContentLineBreaks,
lines...,
)
}
// // Add section.
// di.AddSection(
// fmt.Sprintf("Updates: %s (%d/%d)", initialReleaseChannel, activeCnt, totalCnt),
// debug.UseCodeSection|debug.AddContentLineBreaks,
// lines...,
// )
// }