133 lines
2.7 KiB
Go
133 lines
2.7 KiB
Go
package updates
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/safing/portbase/database"
|
|
"github.com/safing/portbase/database/query"
|
|
"github.com/safing/portbase/database/record"
|
|
"github.com/safing/portbase/info"
|
|
"github.com/safing/portbase/log"
|
|
"github.com/tevino/abool"
|
|
)
|
|
|
|
// database key for update information
|
|
const (
|
|
statusDBKey = "core:status/updates"
|
|
)
|
|
|
|
// version type
|
|
type versionClass int
|
|
|
|
const (
|
|
versionClassLocal versionClass = iota
|
|
versionClassStable
|
|
versionClassBeta
|
|
)
|
|
|
|
// working vars
|
|
var (
|
|
status *versionStatus
|
|
|
|
statusDB = database.NewInterface(nil)
|
|
statusHook *database.RegisteredHook
|
|
enableStatusSave = abool.NewBool(false)
|
|
)
|
|
|
|
func init() {
|
|
status = &versionStatus{
|
|
Modules: make(map[string]*versionStatusEntry),
|
|
}
|
|
status.SetKey(statusDBKey)
|
|
}
|
|
|
|
// versionStatus holds update version status information.
|
|
type versionStatus struct {
|
|
record.Base
|
|
sync.Mutex
|
|
|
|
Core *info.Info
|
|
Modules map[string]*versionStatusEntry
|
|
}
|
|
|
|
func (vs *versionStatus) save() {
|
|
enableStatusSave.SetTo(true)
|
|
err := statusDB.Put(vs)
|
|
if err != nil {
|
|
log.Warningf("could not save updates version status: %s", err)
|
|
}
|
|
}
|
|
|
|
// versionStatusEntry holds information about the update status of a module.
|
|
type versionStatusEntry struct {
|
|
LastVersionUsed string
|
|
LocalVersion string
|
|
StableVersion string
|
|
BetaVersion string
|
|
}
|
|
|
|
func updateUsedStatus(identifier string, version string) {
|
|
status.Lock()
|
|
defer status.Unlock()
|
|
|
|
entry, ok := status.Modules[identifier]
|
|
if !ok {
|
|
entry = &versionStatusEntry{}
|
|
status.Modules[identifier] = entry
|
|
}
|
|
|
|
entry.LastVersionUsed = version
|
|
|
|
log.Tracef("updates: updated last used version of %s: %s", identifier, version)
|
|
|
|
go status.save()
|
|
}
|
|
|
|
func updateStatus(vClass versionClass, state map[string]string) {
|
|
status.Lock()
|
|
defer status.Unlock()
|
|
|
|
for identifier, version := range state {
|
|
|
|
entry, ok := status.Modules[identifier]
|
|
if !ok {
|
|
entry = &versionStatusEntry{}
|
|
status.Modules[identifier] = entry
|
|
}
|
|
|
|
switch vClass {
|
|
case versionClassLocal:
|
|
entry.LocalVersion = version
|
|
case versionClassStable:
|
|
entry.StableVersion = version
|
|
case versionClassBeta:
|
|
entry.BetaVersion = version
|
|
}
|
|
}
|
|
|
|
go status.save()
|
|
}
|
|
|
|
type updateStatusHook struct {
|
|
database.HookBase
|
|
}
|
|
|
|
// UsesPrePut implements the Hook interface.
|
|
func (sh *updateStatusHook) UsesPrePut() bool {
|
|
return true
|
|
}
|
|
|
|
// PrePut implements the Hook interface.
|
|
func (sh *updateStatusHook) PrePut(r record.Record) (record.Record, error) {
|
|
if enableStatusSave.SetToIf(true, false) {
|
|
return r, nil
|
|
}
|
|
return nil, errors.New("may only be changed by updates module")
|
|
}
|
|
|
|
func initUpdateStatusHook() (err error) {
|
|
statusHook, err = database.RegisterHook(query.New(statusDBKey), &updateStatusHook{})
|
|
return err
|
|
}
|