mirror of
https://github.com/safing/portbase
synced 2025-09-01 18:19:57 +00:00
Merge pull request #133 from safing/fix/updater-update-indexes-error
Improve updating system
This commit is contained in:
commit
0d5dc62b9c
14 changed files with 131 additions and 282 deletions
1
go.sum
1
go.sum
|
@ -232,6 +232,7 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fileVersionRegex = regexp.MustCompile(`_v([0-9]+-[0-9]+-[0-9]+b?|0)`)
|
fileVersionRegex = regexp.MustCompile(`_v[0-9]+-[0-9]+-[0-9]+(-[a-z]+)?`)
|
||||||
rawVersionRegex = regexp.MustCompile(`^([0-9]+\.[0-9]+\.[0-9]+b?\*?|0)$`)
|
rawVersionRegex = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+(-[a-z]+)?$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetIdentifierAndVersion splits the given file path into its identifier and version.
|
// GetIdentifierAndVersion splits the given file path into its identifier and version.
|
||||||
|
@ -24,7 +24,7 @@ func GetIdentifierAndVersion(versionedPath string) (identifier, version string,
|
||||||
|
|
||||||
// Trim the `_v` that gets caught by the regex and
|
// Trim the `_v` that gets caught by the regex and
|
||||||
// replace `-` with `.` to get the version string.
|
// replace `-` with `.` to get the version string.
|
||||||
version = strings.Replace(strings.TrimLeft(rawVersion, "_v"), "-", ".", -1)
|
version = strings.Replace(strings.TrimLeft(rawVersion, "_v"), "-", ".", 2)
|
||||||
|
|
||||||
// Put the filename back together without version.
|
// Put the filename back together without version.
|
||||||
i := strings.Index(filename, rawVersion)
|
i := strings.Index(filename, rawVersion)
|
||||||
|
@ -46,7 +46,7 @@ func GetVersionedPath(identifier, version string) (versionedPath string) {
|
||||||
// Split the filename where the version should go.
|
// Split the filename where the version should go.
|
||||||
splittedFilename := strings.SplitN(filename, ".", 2)
|
splittedFilename := strings.SplitN(filename, ".", 2)
|
||||||
// Replace `.` with `-` for the filename format.
|
// Replace `.` with `-` for the filename format.
|
||||||
transformedVersion := strings.Replace(version, ".", "-", -1)
|
transformedVersion := strings.Replace(version, ".", "-", 2)
|
||||||
|
|
||||||
// Put everything back together and return it.
|
// Put everything back together and return it.
|
||||||
versionedPath = identifierPath + splittedFilename[0] + "_v" + transformedVersion
|
versionedPath = identifierPath + splittedFilename[0] + "_v" + transformedVersion
|
||||||
|
|
|
@ -3,6 +3,8 @@ package updater
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testRegexMatch(t *testing.T, testRegex *regexp.Regexp, testString string, shouldMatch bool) {
|
func testRegexMatch(t *testing.T, testRegex *regexp.Regexp, testString string, shouldMatch bool) {
|
||||||
|
@ -25,12 +27,22 @@ func testRegexFind(t *testing.T, testRegex *regexp.Regexp, testString string, sh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testVersionTransformation(t *testing.T, testFilename, testIdentifier, testVersion string) {
|
||||||
|
identifier, version, ok := GetIdentifierAndVersion(testFilename)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("failed to get identifier and version of %s", testFilename)
|
||||||
|
}
|
||||||
|
assert.Equal(t, testIdentifier, identifier, "identifier does not match")
|
||||||
|
assert.Equal(t, testVersion, version, "version does not match")
|
||||||
|
|
||||||
|
versionedPath := GetVersionedPath(testIdentifier, testVersion)
|
||||||
|
assert.Equal(t, testFilename, versionedPath, "filename (versioned path) does not match")
|
||||||
|
}
|
||||||
|
|
||||||
func TestRegexes(t *testing.T) {
|
func TestRegexes(t *testing.T) {
|
||||||
testRegexMatch(t, rawVersionRegex, "0", true)
|
|
||||||
testRegexMatch(t, rawVersionRegex, "0.1.2", true)
|
testRegexMatch(t, rawVersionRegex, "0.1.2", true)
|
||||||
testRegexMatch(t, rawVersionRegex, "0.1.2*", true)
|
testRegexMatch(t, rawVersionRegex, "0.1.2-beta", true)
|
||||||
testRegexMatch(t, rawVersionRegex, "0.1.2b", true)
|
testRegexMatch(t, rawVersionRegex, "0.1.2-staging", true)
|
||||||
testRegexMatch(t, rawVersionRegex, "0.1.2b*", true)
|
|
||||||
testRegexMatch(t, rawVersionRegex, "12.13.14", true)
|
testRegexMatch(t, rawVersionRegex, "12.13.14", true)
|
||||||
|
|
||||||
testRegexMatch(t, rawVersionRegex, "v0.1.2", false)
|
testRegexMatch(t, rawVersionRegex, "v0.1.2", false)
|
||||||
|
@ -41,7 +53,7 @@ func TestRegexes(t *testing.T) {
|
||||||
testRegexMatch(t, rawVersionRegex, ".1.", false)
|
testRegexMatch(t, rawVersionRegex, ".1.", false)
|
||||||
testRegexMatch(t, rawVersionRegex, "012345", false)
|
testRegexMatch(t, rawVersionRegex, "012345", false)
|
||||||
|
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file_v0", true)
|
testRegexFind(t, fileVersionRegex, "/path/to/file_v0-0-0", true)
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2-3", true)
|
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2-3", true)
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2-3.exe", true)
|
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2-3.exe", true)
|
||||||
|
|
||||||
|
@ -50,4 +62,11 @@ func TestRegexes(t *testing.T) {
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file_1-2-3", false)
|
testRegexFind(t, fileVersionRegex, "/path/to/file_1-2-3", false)
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2", false)
|
testRegexFind(t, fileVersionRegex, "/path/to/file_v1-2", false)
|
||||||
testRegexFind(t, fileVersionRegex, "/path/to/file-v1-2-3", false)
|
testRegexFind(t, fileVersionRegex, "/path/to/file-v1-2-3", false)
|
||||||
|
|
||||||
|
testVersionTransformation(t, "/path/to/file_v0-0-0", "/path/to/file", "0.0.0")
|
||||||
|
testVersionTransformation(t, "/path/to/file_v1-2-3", "/path/to/file", "1.2.3")
|
||||||
|
testVersionTransformation(t, "/path/to/file_v1-2-3-beta", "/path/to/file", "1.2.3-beta")
|
||||||
|
testVersionTransformation(t, "/path/to/file_v1-2-3-staging", "/path/to/file", "1.2.3-staging")
|
||||||
|
testVersionTransformation(t, "/path/to/file_v1-2-3.exe", "/path/to/file.exe", "1.2.3")
|
||||||
|
testVersionTransformation(t, "/path/to/file_v1-2-3-staging.exe", "/path/to/file.exe", "1.2.3-staging")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,8 @@ type Index struct {
|
||||||
// on the update server.
|
// on the update server.
|
||||||
Path string
|
Path string
|
||||||
|
|
||||||
// Stable is set if the index file contains only stable
|
// PreRelease signifies that all versions of this index should be marked as
|
||||||
// releases.
|
// pre-releases, no matter if the versions actually have a pre-release tag or
|
||||||
Stable bool
|
// not.
|
||||||
|
PreRelease bool
|
||||||
// Beta is set if the index file contains beta
|
|
||||||
// releases.
|
|
||||||
Beta bool
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,17 @@ type ResourceRegistry struct {
|
||||||
MandatoryUpdates []string
|
MandatoryUpdates []string
|
||||||
AutoUnpack []string
|
AutoUnpack []string
|
||||||
|
|
||||||
Beta bool
|
// UsePreReleases signifies that pre-releases should be used when selecting a
|
||||||
DevMode bool
|
// version. Even if false, a pre-release version will still be used if it is
|
||||||
Online bool
|
// defined as the current version by an index.
|
||||||
|
UsePreReleases bool
|
||||||
|
DevMode bool
|
||||||
|
Online bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddIndex adds a new index to the resource registry.
|
// 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) {
|
func (reg *ResourceRegistry) AddIndex(idx Index) {
|
||||||
reg.Lock()
|
reg.Lock()
|
||||||
defer reg.Unlock()
|
defer reg.Unlock()
|
||||||
|
@ -92,41 +97,41 @@ func (reg *ResourceRegistry) SetDevMode(on bool) {
|
||||||
reg.DevMode = on
|
reg.DevMode = on
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBeta sets the beta flag.
|
// SetUsePreReleases sets the UsePreReleases flag.
|
||||||
func (reg *ResourceRegistry) SetBeta(on bool) {
|
func (reg *ResourceRegistry) SetUsePreReleases(yes bool) {
|
||||||
reg.Lock()
|
reg.Lock()
|
||||||
defer reg.Unlock()
|
defer reg.Unlock()
|
||||||
|
|
||||||
reg.Beta = on
|
reg.UsePreReleases = yes
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddResource adds a resource to the registry. Does _not_ select new version.
|
// AddResource adds a resource to the registry. Does _not_ select new version.
|
||||||
func (reg *ResourceRegistry) AddResource(identifier, version string, available, stableRelease, betaRelease bool) error {
|
func (reg *ResourceRegistry) AddResource(identifier, version string, available, currentRelease, preRelease bool) error {
|
||||||
reg.Lock()
|
reg.Lock()
|
||||||
defer reg.Unlock()
|
defer reg.Unlock()
|
||||||
|
|
||||||
err := reg.addResource(identifier, version, available, stableRelease, betaRelease)
|
err := reg.addResource(identifier, version, available, currentRelease, preRelease)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reg *ResourceRegistry) addResource(identifier, version string, available, stableRelease, betaRelease bool) error {
|
func (reg *ResourceRegistry) addResource(identifier, version string, available, currentRelease, preRelease bool) error {
|
||||||
res, ok := reg.resources[identifier]
|
res, ok := reg.resources[identifier]
|
||||||
if !ok {
|
if !ok {
|
||||||
res = reg.newResource(identifier)
|
res = reg.newResource(identifier)
|
||||||
reg.resources[identifier] = res
|
reg.resources[identifier] = res
|
||||||
}
|
}
|
||||||
return res.AddVersion(version, available, stableRelease, betaRelease)
|
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.
|
// 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, available, stableRelease, betaRelease bool) error {
|
func (reg *ResourceRegistry) AddResources(versions map[string]string, available, currentRelease, preRelease bool) error {
|
||||||
reg.Lock()
|
reg.Lock()
|
||||||
defer reg.Unlock()
|
defer reg.Unlock()
|
||||||
|
|
||||||
// add versions and their flags to registry
|
// add versions and their flags to registry
|
||||||
var lastError error
|
var lastError error
|
||||||
for identifier, version := range versions {
|
for identifier, version := range versions {
|
||||||
lastError = reg.addResource(identifier, version, available, stableRelease, betaRelease)
|
lastError = reg.addResource(identifier, version, available, currentRelease, preRelease)
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
log.Warningf("%s: failed to add resource %s: %s", reg.Name, identifier, lastError)
|
log.Warningf("%s: failed to add resource %s: %s", reg.Name, identifier, lastError)
|
||||||
}
|
}
|
||||||
|
@ -161,7 +166,8 @@ func (reg *ResourceRegistry) GetSelectedVersions() (versions map[string]string)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge deletes old updates, retaining a certain amount, specified by the keep parameter. Will at least keep 2 updates per resource.
|
// 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) {
|
func (reg *ResourceRegistry) Purge(keep int) {
|
||||||
reg.RLock()
|
reg.RLock()
|
||||||
defer reg.RUnlock()
|
defer reg.RUnlock()
|
||||||
|
@ -171,14 +177,22 @@ func (reg *ResourceRegistry) Purge(keep int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the internal state of the registry, removing all added resources.
|
// ResetResources removes all resources from the registry.
|
||||||
func (reg *ResourceRegistry) Reset() {
|
func (reg *ResourceRegistry) ResetResources() {
|
||||||
reg.Lock()
|
reg.Lock()
|
||||||
defer reg.Unlock()
|
defer reg.Unlock()
|
||||||
|
|
||||||
reg.resources = make(map[string]*Resource)
|
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, 5)
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup removes temporary files.
|
// Cleanup removes temporary files.
|
||||||
func (reg *ResourceRegistry) Cleanup() error {
|
func (reg *ResourceRegistry) Cleanup() error {
|
||||||
// delete download tmp dir
|
// delete download tmp dir
|
||||||
|
|
|
@ -19,9 +19,9 @@ func TestMain(m *testing.M) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
registry = &ResourceRegistry{
|
registry = &ResourceRegistry{
|
||||||
Beta: true,
|
UsePreReleases: true,
|
||||||
DevMode: true,
|
DevMode: true,
|
||||||
Online: true,
|
Online: true,
|
||||||
}
|
}
|
||||||
err = registry.Initialize(utils.NewDirStructure(tmpDir, 0777))
|
err = registry.Initialize(utils.NewDirStructure(tmpDir, 0777))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -65,13 +65,12 @@ type ResourceVersion struct {
|
||||||
// Available indicates if this version is available locally.
|
// Available indicates if this version is available locally.
|
||||||
Available bool
|
Available bool
|
||||||
|
|
||||||
// StableRelease indicates that this version is part of
|
// CurrentRelease indicates that this is the current release that should be
|
||||||
// a stable release index file.
|
// selected, if possible.
|
||||||
StableRelease bool
|
CurrentRelease bool
|
||||||
|
|
||||||
// BetaRelease indicates that this version is part of
|
// PreRelease indicates that this version is pre-release.
|
||||||
// a beta release index file.
|
PreRelease bool
|
||||||
BetaRelease bool
|
|
||||||
|
|
||||||
// Blacklisted may be set to true if this version should
|
// Blacklisted may be set to true if this version should
|
||||||
// be skipped and not used. This is useful if the version
|
// be skipped and not used. This is useful if the version
|
||||||
|
@ -172,19 +171,14 @@ func (reg *ResourceRegistry) newResource(identifier string) *Resource {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddVersion adds a resource version to a resource.
|
// AddVersion adds a resource version to a resource.
|
||||||
func (res *Resource) AddVersion(version string, available, stableRelease, betaRelease bool) error {
|
func (res *Resource) AddVersion(version string, available, currentRelease, preRelease bool) error {
|
||||||
res.Lock()
|
res.Lock()
|
||||||
defer res.Unlock()
|
defer res.Unlock()
|
||||||
|
|
||||||
// reset stable or beta release flags
|
// reset current release flags
|
||||||
if stableRelease || betaRelease {
|
if currentRelease {
|
||||||
for _, rv := range res.Versions {
|
for _, rv := range res.Versions {
|
||||||
if stableRelease {
|
rv.CurrentRelease = false
|
||||||
rv.StableRelease = false
|
|
||||||
}
|
|
||||||
if betaRelease {
|
|
||||||
rv.BetaRelease = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,11 +211,11 @@ func (res *Resource) AddVersion(version string, available, stableRelease, betaRe
|
||||||
if available {
|
if available {
|
||||||
rv.Available = true
|
rv.Available = true
|
||||||
}
|
}
|
||||||
if stableRelease {
|
if currentRelease {
|
||||||
rv.StableRelease = true
|
rv.CurrentRelease = true
|
||||||
}
|
}
|
||||||
if betaRelease {
|
if preRelease || rv.semVer.Prerelease() != "" {
|
||||||
rv.BetaRelease = true
|
rv.PreRelease = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -280,58 +274,50 @@ func (res *Resource) selectVersion() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target selection
|
// Target selection
|
||||||
|
|
||||||
// 1) Dev release if dev mode is active and ignore blacklisting
|
// 1) Dev release if dev mode is active and ignore blacklisting
|
||||||
if res.registry.DevMode {
|
if res.registry.DevMode {
|
||||||
// get last element
|
// Get last version, as this will be v0.0.0, if available.
|
||||||
rv := res.Versions[len(res.Versions)-1]
|
rv := res.Versions[len(res.Versions)-1]
|
||||||
// check if it's a dev version
|
// Check if it's v0.0.0.
|
||||||
if rv.semVer.Equal(devVersion) && rv.Available {
|
if rv.semVer.Equal(devVersion) && rv.Available {
|
||||||
res.SelectedVersion = rv
|
res.SelectedVersion = rv
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Beta release if beta is active
|
// 2) Find the current release. This may be also be a pre-release.
|
||||||
if res.registry.Beta {
|
|
||||||
for _, rv := range res.Versions {
|
|
||||||
if rv.BetaRelease {
|
|
||||||
if rv.isSelectable() {
|
|
||||||
res.SelectedVersion = rv
|
|
||||||
return
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Stable release
|
|
||||||
for _, rv := range res.Versions {
|
for _, rv := range res.Versions {
|
||||||
if rv.StableRelease {
|
if rv.CurrentRelease {
|
||||||
if rv.isSelectable() {
|
if rv.isSelectable() {
|
||||||
res.SelectedVersion = rv
|
res.SelectedVersion = rv
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// There can only be once current release,
|
||||||
|
// so we can abort after finding one.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Latest stable release
|
// 3) If UsePreReleases is set, find any newest version.
|
||||||
|
if res.registry.UsePreReleases {
|
||||||
|
for _, rv := range res.Versions {
|
||||||
|
if rv.isSelectable() {
|
||||||
|
res.SelectedVersion = rv
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) Find the newest stable version.
|
||||||
for _, rv := range res.Versions {
|
for _, rv := range res.Versions {
|
||||||
if !rv.isBetaVersionNumber() && rv.isSelectable() {
|
if !rv.PreRelease && rv.isSelectable() {
|
||||||
res.SelectedVersion = rv
|
res.SelectedVersion = rv
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Latest of any type
|
// 5) Default to newest.
|
||||||
for _, rv := range res.Versions {
|
|
||||||
if rv.isSelectable() {
|
|
||||||
res.SelectedVersion = rv
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6) Default to newest
|
|
||||||
res.SelectedVersion = res.Versions[0]
|
res.SelectedVersion = res.Versions[0]
|
||||||
log.Warningf("updater: falling back to version %s for %s because we failed to find a selectable one", res.SelectedVersion, res.Identifier)
|
log.Warningf("updater: falling back to version %s for %s because we failed to find a selectable one", res.SelectedVersion, res.Identifier)
|
||||||
}
|
}
|
||||||
|
@ -422,7 +408,7 @@ boundarySearch:
|
||||||
if rv == res.SelectedVersion {
|
if rv == res.SelectedVersion {
|
||||||
skippedSelectedVersion = true
|
skippedSelectedVersion = true
|
||||||
}
|
}
|
||||||
if rv.StableRelease {
|
if !rv.PreRelease {
|
||||||
skippedStableVersion = true
|
skippedStableVersion = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,27 @@ import (
|
||||||
func TestVersionSelection(t *testing.T) {
|
func TestVersionSelection(t *testing.T) {
|
||||||
res := registry.newResource("test/a")
|
res := registry.newResource("test/a")
|
||||||
|
|
||||||
err := res.AddVersion("1.2.3", true, true, false)
|
err := res.AddVersion("1.2.2", true, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
err = res.AddVersion("1.2.4b", true, false, true)
|
err = res.AddVersion("1.2.3", true, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
err = res.AddVersion("1.2.2", true, false, false)
|
err = res.AddVersion("1.2.4-beta", true, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
err = res.AddVersion("1.2.5", false, true, false)
|
err = res.AddVersion("1.2.4-staging", true, false, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = res.AddVersion("1.2.5", false, false, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = res.AddVersion("1.2.6-beta", false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -32,9 +40,9 @@ func TestVersionSelection(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.Online = true
|
registry.UsePreReleases = true
|
||||||
registry.Beta = true
|
|
||||||
registry.DevMode = true
|
registry.DevMode = true
|
||||||
|
registry.Online = true
|
||||||
res.selectVersion()
|
res.selectVersion()
|
||||||
if res.SelectedVersion.VersionNumber != "0.0.0" {
|
if res.SelectedVersion.VersionNumber != "0.0.0" {
|
||||||
t.Errorf("selected version should be 0.0.0, not %s", res.SelectedVersion.VersionNumber)
|
t.Errorf("selected version should be 0.0.0, not %s", res.SelectedVersion.VersionNumber)
|
||||||
|
@ -42,11 +50,11 @@ func TestVersionSelection(t *testing.T) {
|
||||||
|
|
||||||
registry.DevMode = false
|
registry.DevMode = false
|
||||||
res.selectVersion()
|
res.selectVersion()
|
||||||
if res.SelectedVersion.VersionNumber != "1.2.4-b" {
|
if res.SelectedVersion.VersionNumber != "1.2.6-beta" {
|
||||||
t.Errorf("selected version should be 1.2.4-b, not %s", res.SelectedVersion.VersionNumber)
|
t.Errorf("selected version should be 1.2.6-beta, not %s", res.SelectedVersion.VersionNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
registry.Beta = false
|
registry.UsePreReleases = false
|
||||||
res.selectVersion()
|
res.selectVersion()
|
||||||
if res.SelectedVersion.VersionNumber != "1.2.5" {
|
if res.SelectedVersion.VersionNumber != "1.2.5" {
|
||||||
t.Errorf("selected version should be 1.2.5, not %s", res.SelectedVersion.VersionNumber)
|
t.Errorf("selected version should be 1.2.5, not %s", res.SelectedVersion.VersionNumber)
|
||||||
|
|
|
@ -136,7 +136,7 @@ func (reg *ResourceRegistry) loadIndexFile(idx Index) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = reg.AddResources(releases, false, idx.Stable, idx.Beta)
|
err = reg.AddResources(releases, false, true, idx.PreRelease)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("%s: failed to add resource: %s", reg.Name, err)
|
log.Warningf("%s: failed to add resource: %s", reg.Name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,26 @@ import (
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpdateIndexes downloads all indexes and returns the first error encountered.
|
// UpdateIndexes downloads all indexes. An error is only returned when all
|
||||||
|
// indexes fail to update.
|
||||||
func (reg *ResourceRegistry) UpdateIndexes(ctx context.Context) error {
|
func (reg *ResourceRegistry) UpdateIndexes(ctx context.Context) error {
|
||||||
var firstErr error
|
var lastErr error
|
||||||
|
var anySuccess bool
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
for _, idx := range reg.getIndexes() {
|
for _, idx := range reg.getIndexes() {
|
||||||
if err := reg.downloadIndex(ctx, client, idx); err != nil {
|
if err := reg.downloadIndex(ctx, client, idx); err != nil {
|
||||||
if firstErr == nil {
|
lastErr = err
|
||||||
firstErr = err
|
log.Warningf("%s: failed to update index %s: %s", reg.Name, idx.Path, err)
|
||||||
}
|
} else {
|
||||||
|
anySuccess = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstErr
|
if !anySuccess {
|
||||||
|
return fmt.Errorf("failed to update all indexes, last error was: %s", lastErr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (reg *ResourceRegistry) downloadIndex(ctx context.Context, client *http.Client, idx Index) error {
|
func (reg *ResourceRegistry) downloadIndex(ctx context.Context, client *http.Client, idx Index) error {
|
||||||
|
@ -74,7 +80,7 @@ func (reg *ResourceRegistry) downloadIndex(ctx context.Context, client *http.Cli
|
||||||
}
|
}
|
||||||
|
|
||||||
// add resources to registry
|
// add resources to registry
|
||||||
err = reg.AddResources(cleanedData, false, idx.Stable, idx.Beta)
|
err = reg.AddResources(cleanedData, false, true, idx.PreRelease)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("%s: failed to add resources: %s", reg.Name, err)
|
log.Warningf("%s: failed to add resources: %s", reg.Name, err)
|
||||||
}
|
}
|
||||||
|
@ -112,7 +118,7 @@ func (reg *ResourceRegistry) DownloadUpdates(ctx context.Context) error {
|
||||||
|
|
||||||
// add all non-available and eligible versions to update queue
|
// add all non-available and eligible versions to update queue
|
||||||
for _, rv := range res.Versions {
|
for _, rv := range res.Versions {
|
||||||
if !rv.Available && (rv.StableRelease || reg.Beta && rv.BetaRelease) {
|
if !rv.Available && rv.CurrentRelease {
|
||||||
toUpdate = append(toUpdate, rv)
|
toUpdate = append(toUpdate, rv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
updater/uptool/.gitignore
vendored
1
updater/uptool/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
uptool
|
|
|
@ -1,37 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/safing/portbase/updater"
|
|
||||||
"github.com/safing/portbase/utils"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registry *updater.ResourceRegistry
|
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
|
||||||
Use: "uptool",
|
|
||||||
Short: "helper tool for the update process",
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
return cmd.Usage()
|
|
||||||
},
|
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
absPath, err := filepath.Abs(args[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
registry = &updater.ResourceRegistry{}
|
|
||||||
return registry.Initialize(utils.NewDirStructure(absPath, 0755))
|
|
||||||
},
|
|
||||||
SilenceUsage: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(scanCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var scanCmd = &cobra.Command{
|
|
||||||
Use: "scan",
|
|
||||||
Short: "Scan the specified directory and print the result",
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: scan,
|
|
||||||
}
|
|
||||||
|
|
||||||
func scan(cmd *cobra.Command, args []string) error {
|
|
||||||
err := scanStorage()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// export beta
|
|
||||||
data, err := json.MarshalIndent(exportSelected(true), "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// print
|
|
||||||
fmt.Println("beta:")
|
|
||||||
fmt.Println(string(data))
|
|
||||||
|
|
||||||
// export stable
|
|
||||||
data, err = json.MarshalIndent(exportSelected(false), "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// print
|
|
||||||
fmt.Println("\nstable:")
|
|
||||||
fmt.Println(string(data))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanStorage() error {
|
|
||||||
files, err := ioutil.ReadDir(registry.StorageDir().Path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan "all" and all "os_platform" dirs
|
|
||||||
for _, file := range files {
|
|
||||||
if file.IsDir() && (file.Name() == "all" || strings.Contains(file.Name(), "_")) {
|
|
||||||
err := registry.ScanStorage(filepath.Join(registry.StorageDir().Path, file.Name()))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func exportSelected(beta bool) map[string]string {
|
|
||||||
registry.SetBeta(beta)
|
|
||||||
registry.SelectVersions()
|
|
||||||
export := registry.Export()
|
|
||||||
|
|
||||||
versions := make(map[string]string)
|
|
||||||
for _, rv := range export {
|
|
||||||
versions[rv.Identifier] = rv.SelectedVersion.VersionNumber
|
|
||||||
}
|
|
||||||
return versions
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(updateCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var updateCmd = &cobra.Command{
|
|
||||||
Use: "update",
|
|
||||||
Short: "Update scans the specified directory and registry the index and symlink structure",
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
RunE: update,
|
|
||||||
}
|
|
||||||
|
|
||||||
func update(cmd *cobra.Command, args []string) error {
|
|
||||||
err := scanStorage()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// export beta
|
|
||||||
data, err := json.MarshalIndent(exportSelected(true), "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// print
|
|
||||||
fmt.Println("beta:")
|
|
||||||
fmt.Println(string(data))
|
|
||||||
// write index
|
|
||||||
err = ioutil.WriteFile(filepath.Join(registry.StorageDir().Dir, "beta.json"), data, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// export stable
|
|
||||||
data, err = json.MarshalIndent(exportSelected(false), "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// print
|
|
||||||
fmt.Println("\nstable:")
|
|
||||||
fmt.Println(string(data))
|
|
||||||
// write index
|
|
||||||
err = ioutil.WriteFile(filepath.Join(registry.StorageDir().Dir, "stable.json"), data, 0755)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// create symlinks
|
|
||||||
err = registry.CreateSymlinks(registry.StorageDir().ChildDir("latest", 0755))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("\nstable symlinks created")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue