Merge pull request #331 from safing/fix/index-update-error
Improve release channels
This commit is contained in:
@@ -14,7 +14,6 @@ import (
|
||||
)
|
||||
|
||||
func checkAndCreateInstanceLock(path, name string) (pid int32, err error) {
|
||||
|
||||
lockFilePath := filepath.Join(dataRoot.Path, path, fmt.Sprintf("%s-lock.pid", name))
|
||||
|
||||
// read current pid file
|
||||
@@ -86,7 +85,8 @@ func createInstanceLock(lockFilePath string) error {
|
||||
}
|
||||
|
||||
// create lock file
|
||||
err = ioutil.WriteFile(lockFilePath, []byte(fmt.Sprintf("%d", os.Getpid())), 0666)
|
||||
// TODO: Investigate required permissions.
|
||||
err = ioutil.WriteFile(lockFilePath, []byte(fmt.Sprintf("%d", os.Getpid())), 0666) //nolint:gosec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func getPmStartLogFile(ext string) *os.File {
|
||||
}, info.Version(), ext)
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
//nolint:unused // false positive on linux, currently used by windows only. TODO: move to a _windows file.
|
||||
func logControlError(cErr error) {
|
||||
// check if error present
|
||||
if cErr == nil {
|
||||
@@ -112,7 +112,7 @@ func logControlError(cErr error) {
|
||||
fmt.Fprintln(errorFile, cErr.Error())
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only. TODO: move to a _windows file.
|
||||
func runAndLogControlError(wrappedFunc func(cmd *cobra.Command, args []string) error) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
err := wrappedFunc(cmd, args)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -11,6 +12,10 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/safing/portbase/dataroot"
|
||||
"github.com/safing/portbase/info"
|
||||
portlog "github.com/safing/portbase/log"
|
||||
@@ -33,7 +38,6 @@ var (
|
||||
UpdateURLs: []string{
|
||||
"https://updates.safing.io",
|
||||
},
|
||||
Beta: false,
|
||||
DevMode: false,
|
||||
Online: true, // is disabled later based on command
|
||||
}
|
||||
@@ -65,7 +69,7 @@ func init() {
|
||||
{
|
||||
flags.StringVar(&dataDir, "data", "", "Configures the data directory. Alternatively, this can also be set via the environment variable PORTMASTER_DATA.")
|
||||
flags.StringVar(®istry.UserAgent, "update-agent", "Start", "Sets the user agent for requests to the update server")
|
||||
flags.BoolVar(&staging, "staging", false, "Use staging update channel (for testing only)")
|
||||
flags.BoolVar(&staging, "staging", false, "Deprecated, configure in settings instead.")
|
||||
flags.IntVar(&maxRetries, "max-retries", 5, "Maximum number of retries when starting a Portmaster component")
|
||||
flags.BoolVar(&stdinSignals, "input-signals", false, "Emulate signals using stdin.")
|
||||
_ = rootCmd.MarkPersistentFlagDirname("data")
|
||||
@@ -164,32 +168,6 @@ func configureRegistry(mustLoadIndex bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "stable.json",
|
||||
Stable: true,
|
||||
Beta: false,
|
||||
})
|
||||
|
||||
// TODO: enable loading beta versions
|
||||
// registry.AddIndex(updater.Index{
|
||||
// Path: "beta.json",
|
||||
// Stable: false,
|
||||
// Beta: true,
|
||||
// })
|
||||
|
||||
if stagingActive() {
|
||||
// Set flag no matter how staging was activated.
|
||||
staging = true
|
||||
|
||||
log.Println("WARNING: staging environment is active.")
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "staging.json",
|
||||
Stable: true,
|
||||
Beta: true,
|
||||
})
|
||||
}
|
||||
|
||||
return updateRegistryIndex(mustLoadIndex)
|
||||
}
|
||||
|
||||
@@ -210,6 +188,16 @@ func configureLogging() error {
|
||||
}
|
||||
|
||||
func updateRegistryIndex(mustLoadIndex bool) error {
|
||||
// Get release channel from config.
|
||||
releaseChannel := getReleaseChannel(dataRoot)
|
||||
|
||||
// Set indexes based on the release channel.
|
||||
helper.SetIndexes(registry, releaseChannel)
|
||||
|
||||
// Update registry to use pre-releases or not.
|
||||
registry.SetUsePreReleases(releaseChannel != helper.ReleaseChannelStable)
|
||||
|
||||
// Load indexes from disk or network, if needed and desired.
|
||||
err := registry.LoadIndexes(context.Background())
|
||||
if err != nil {
|
||||
log.Printf("WARNING: error loading indexes: %s\n", err)
|
||||
@@ -218,6 +206,7 @@ func updateRegistryIndex(mustLoadIndex bool) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Load versions from disk to know which others we have and which are available.
|
||||
err = registry.ScanStorage("")
|
||||
if err != nil {
|
||||
log.Printf("WARNING: error during storage scan: %s\n", err)
|
||||
@@ -247,13 +236,23 @@ func detectInstallationDir() string {
|
||||
return parent
|
||||
}
|
||||
|
||||
func stagingActive() bool {
|
||||
// Check flag and env variable.
|
||||
if staging || os.Getenv("PORTMASTER_STAGING") == "enabled" {
|
||||
return true
|
||||
func getReleaseChannel(dataRoot *utils.DirStructure) string {
|
||||
configData, err := ioutil.ReadFile(filepath.Join(dataRoot.Path, "config.json"))
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Printf("WARNING: failed to read config.json to get release channel: %s", err)
|
||||
}
|
||||
return helper.ReleaseChannelStable
|
||||
}
|
||||
|
||||
// Check if staging index is present and acessible.
|
||||
_, err := os.Stat(filepath.Join(registry.StorageDir().Path, "staging.json"))
|
||||
return err == nil
|
||||
// Get release channel from config, validate and return it.
|
||||
channel := gjson.GetBytes(configData, helper.ReleaseChannelJSONKey).String()
|
||||
switch channel {
|
||||
case helper.ReleaseChannelStable,
|
||||
helper.ReleaseChannelBeta,
|
||||
helper.ReleaseChannelStaging:
|
||||
return channel
|
||||
default:
|
||||
return helper.ReleaseChannelStable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ var recoverIPTablesCmd = &cobra.Command{
|
||||
// we don't get the errno of the actual error and need to parse the
|
||||
// output instead. Make sure it's always english by setting LC_ALL=C
|
||||
currentLocale := os.Getenv("LC_ALL")
|
||||
os.Setenv("LC_ALL", "C") // nolint:errcheck - we tried at least ...
|
||||
defer os.Setenv("LC_ALL", currentLocale) // nolint:errcheck
|
||||
os.Setenv("LC_ALL", "C")
|
||||
defer os.Setenv("LC_ALL", currentLocale)
|
||||
|
||||
err := interception.DeactivateNfqueueFirewall()
|
||||
if err == nil {
|
||||
|
||||
@@ -33,17 +33,17 @@ var (
|
||||
childIsRunning = abool.NewBool(false)
|
||||
)
|
||||
|
||||
// Options for starting component
|
||||
// Options for starting component.
|
||||
type Options struct {
|
||||
Name string
|
||||
Identifier string // component identifier
|
||||
ShortIdentifier string // populated automatically
|
||||
LockPathPrefix string
|
||||
PIDFile bool
|
||||
ShortIdentifier string // populated automatically
|
||||
SuppressArgs bool // do not use any args
|
||||
AllowDownload bool // allow download of component if it is not yet available
|
||||
AllowHidingWindow bool // allow hiding the window of the subprocess
|
||||
NoOutput bool // do not use stdout/err if logging to file is available (did not fail to open log file)
|
||||
SuppressArgs bool // do not use any args
|
||||
AllowDownload bool // allow download of component if it is not yet available
|
||||
AllowHidingWindow bool // allow hiding the window of the subprocess
|
||||
NoOutput bool // do not use stdout/err if logging to file is available (did not fail to open log file)
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -313,7 +313,7 @@ func execute(opts *Options, args []string) (cont bool, err error) {
|
||||
log.Printf("starting %s %s\n", binPath, strings.Join(args, " "))
|
||||
|
||||
// create command
|
||||
exc := exec.Command(binPath, args...) //nolint:gosec // everything is okay
|
||||
exc := exec.Command(binPath, args...)
|
||||
|
||||
if !runningInConsole && opts.AllowHidingWindow {
|
||||
// Windows only:
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
startupComplete = make(chan struct{}) // signal that the start procedure completed (is never closed, just signaled once)
|
||||
shuttingDown = make(chan struct{}) // signal that we are shutting down (will be closed, may not be closed directly, use initiateShutdown)
|
||||
//nolint:deadcode,unused // false positive on linux, currently used by windows only
|
||||
//nolint:unused // false positive on linux, currently used by windows only
|
||||
shutdownError error // protected by shutdownLock
|
||||
shutdownLock sync.Mutex
|
||||
)
|
||||
|
||||
@@ -40,8 +40,7 @@ var (
|
||||
|
||||
func indexRequired(cmd *cobra.Command) bool {
|
||||
switch cmd {
|
||||
case updateCmd,
|
||||
purgeCmd:
|
||||
case updateCmd, purgeCmd:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@@ -49,35 +48,9 @@ func indexRequired(cmd *cobra.Command) bool {
|
||||
}
|
||||
|
||||
func downloadUpdates() error {
|
||||
// mark required updates
|
||||
if onWindows {
|
||||
registry.MandatoryUpdates = []string{
|
||||
helper.PlatformIdentifier("core/portmaster-core.exe"),
|
||||
helper.PlatformIdentifier("kext/portmaster-kext.dll"),
|
||||
helper.PlatformIdentifier("kext/portmaster-kext.sys"),
|
||||
helper.PlatformIdentifier("start/portmaster-start.exe"),
|
||||
helper.PlatformIdentifier("notifier/portmaster-notifier.exe"),
|
||||
helper.PlatformIdentifier("notifier/portmaster-snoretoast.exe"),
|
||||
}
|
||||
} else {
|
||||
registry.MandatoryUpdates = []string{
|
||||
helper.PlatformIdentifier("core/portmaster-core"),
|
||||
helper.PlatformIdentifier("start/portmaster-start"),
|
||||
helper.PlatformIdentifier("notifier/portmaster-notifier"),
|
||||
}
|
||||
}
|
||||
|
||||
// add updates that we require on all platforms.
|
||||
registry.MandatoryUpdates = append(
|
||||
registry.MandatoryUpdates,
|
||||
helper.PlatformIdentifier("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
)
|
||||
|
||||
// Add assets that need unpacking.
|
||||
registry.AutoUnpack = []string{
|
||||
helper.PlatformIdentifier("app/portmaster-app.zip"),
|
||||
}
|
||||
// Set required updates.
|
||||
registry.MandatoryUpdates = helper.MandatoryUpdates()
|
||||
registry.AutoUnpack = helper.AutoUnpackUpdates()
|
||||
|
||||
// logging is configured as a persistent pre-run method inherited from
|
||||
// the root command but since we don't use run.Run() we need to start
|
||||
@@ -100,8 +73,8 @@ func downloadUpdates() error {
|
||||
return fmt.Errorf("failed to create update dir: %w", err)
|
||||
}
|
||||
|
||||
// Reset registry state.
|
||||
registry.Reset()
|
||||
// Reset registry resources.
|
||||
registry.ResetResources()
|
||||
}
|
||||
|
||||
// Update all indexes.
|
||||
|
||||
@@ -12,62 +12,64 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var showShortVersion bool
|
||||
var showAllVersions bool
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display various portmaster versions",
|
||||
Args: cobra.NoArgs,
|
||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||
if showAllVersions {
|
||||
// If we are going to show all component versions,
|
||||
// we need the registry to be configured.
|
||||
if err := configureRegistry(false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(*cobra.Command, []string) error {
|
||||
if !showAllVersions {
|
||||
if showShortVersion {
|
||||
fmt.Println(info.Version())
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println(info.FullVersion())
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("portmaster-start %s\n\n", info.Version())
|
||||
fmt.Printf("Assets:\n")
|
||||
|
||||
all := registry.Export()
|
||||
keys := make([]string, 0, len(all))
|
||||
for identifier := range all {
|
||||
keys = append(keys, identifier)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
for _, identifier := range keys {
|
||||
res := all[identifier]
|
||||
|
||||
if showShortVersion {
|
||||
// in "short" mode, skip all resources that are irrelevant on that platform
|
||||
if !strings.HasPrefix(identifier, "all") && !strings.HasPrefix(identifier, runtime.GOOS) {
|
||||
continue
|
||||
var (
|
||||
showShortVersion bool
|
||||
showAllVersions bool
|
||||
versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display various portmaster versions",
|
||||
Args: cobra.NoArgs,
|
||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||
if showAllVersions {
|
||||
// If we are going to show all component versions,
|
||||
// we need the registry to be configured.
|
||||
if err := configureRegistry(false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(tw, " %s\t%s\n", identifier, res.SelectedVersion.VersionNumber)
|
||||
}
|
||||
tw.Flush()
|
||||
return nil
|
||||
},
|
||||
RunE: func(*cobra.Command, []string) error {
|
||||
if !showAllVersions {
|
||||
if showShortVersion {
|
||||
fmt.Println(info.Version())
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
fmt.Println(info.FullVersion())
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Printf("portmaster-start %s\n\n", info.Version())
|
||||
fmt.Printf("Assets:\n")
|
||||
|
||||
all := registry.Export()
|
||||
keys := make([]string, 0, len(all))
|
||||
for identifier := range all {
|
||||
keys = append(keys, identifier)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
|
||||
for _, identifier := range keys {
|
||||
res := all[identifier]
|
||||
|
||||
if showShortVersion {
|
||||
// in "short" mode, skip all resources that are irrelevant on that platform
|
||||
if !strings.HasPrefix(identifier, "all") && !strings.HasPrefix(identifier, runtime.GOOS) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(tw, " %s\t%s\n", identifier, res.SelectedVersion.VersionNumber)
|
||||
}
|
||||
tw.Flush()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
flags := versionCmd.Flags()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -31,24 +30,7 @@ var rootCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
registry = &updater.ResourceRegistry{}
|
||||
err = registry.Initialize(utils.NewDirStructure(absDistPath, 0o755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "stable.json",
|
||||
Stable: true,
|
||||
Beta: false,
|
||||
})
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "beta.json",
|
||||
Stable: false,
|
||||
Beta: true,
|
||||
})
|
||||
|
||||
err = registry.LoadIndexes(context.TODO())
|
||||
err = registry.Initialize(utils.NewDirStructure(absDistPath, 0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,83 +4,140 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
releaseCmd = &cobra.Command{
|
||||
Use: "release",
|
||||
Short: "Release scans the distribution directory and creates registry indexes and the symlink structure",
|
||||
RunE: release,
|
||||
}
|
||||
preReleaseCmd = &cobra.Command{
|
||||
Use: "prerelease",
|
||||
Short: "Stage scans the specified directory and loads the indexes - it then creates a staging index with all files newer than the stable and beta indexes",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: prerelease,
|
||||
}
|
||||
resetPreReleases bool
|
||||
includeUnreleased bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(releaseCmd)
|
||||
}
|
||||
|
||||
var releaseCmd = &cobra.Command{
|
||||
Use: "release",
|
||||
Short: "Release scans the distribution directory and creates registry indexes and the symlink structure",
|
||||
RunE: release,
|
||||
rootCmd.AddCommand(preReleaseCmd)
|
||||
preReleaseCmd.Flags().BoolVar(&resetPreReleases, "reset", false, "Reset pre-release assets")
|
||||
}
|
||||
|
||||
func release(cmd *cobra.Command, args []string) error {
|
||||
// Set stable and beta to latest version.
|
||||
updateToLatestVersion(true, true)
|
||||
return writeIndex(
|
||||
"stable",
|
||||
getChannelVersions("", false),
|
||||
)
|
||||
}
|
||||
|
||||
// Export versions.
|
||||
betaData, err := json.MarshalIndent(exportSelected(true), "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
func prerelease(cmd *cobra.Command, args []string) error {
|
||||
channel := args[0]
|
||||
|
||||
// Check if we want to reset instead.
|
||||
if resetPreReleases {
|
||||
return removeFilesFromIndex(getChannelVersions(channel, true))
|
||||
}
|
||||
stableData, err := json.MarshalIndent(exportSelected(false), "", " ")
|
||||
|
||||
return writeIndex(
|
||||
channel,
|
||||
getChannelVersions(channel, false),
|
||||
)
|
||||
}
|
||||
|
||||
func writeIndex(channel string, versions map[string]string) error {
|
||||
// Export versions and format them.
|
||||
versionData, err := json.MarshalIndent(versions, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build destination paths.
|
||||
betaIndexFilePath := filepath.Join(registry.StorageDir().Path, "beta.json")
|
||||
stableIndexFilePath := filepath.Join(registry.StorageDir().Path, "stable.json")
|
||||
// Build destination path.
|
||||
indexFilePath := filepath.Join(registry.StorageDir().Path, channel+".json")
|
||||
|
||||
// Print previews.
|
||||
fmt.Printf("beta (%s):\n", betaIndexFilePath)
|
||||
fmt.Println(string(betaData))
|
||||
fmt.Printf("\nstable: (%s)\n", stableIndexFilePath)
|
||||
fmt.Println(string(stableData))
|
||||
// Print preview.
|
||||
fmt.Printf("%s (%s):\n", channel, indexFilePath)
|
||||
fmt.Println(string(versionData))
|
||||
|
||||
// Ask for confirmation.
|
||||
if !confirm("\nDo you want to write these new indexes (and update latest symlinks)?") {
|
||||
if !confirm("\nDo you want to write this index?") {
|
||||
fmt.Println("aborted...")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write indexes.
|
||||
err = ioutil.WriteFile(betaIndexFilePath, betaData, 0o644) //nolint:gosec // 0644 is intended
|
||||
// Write new index to disk.
|
||||
err = ioutil.WriteFile(indexFilePath, versionData, 0644) //nolint:gosec // 0644 is intended
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("written %s\n", betaIndexFilePath)
|
||||
|
||||
err = ioutil.WriteFile(stableIndexFilePath, stableData, 0o644) //nolint:gosec // 0644 is intended
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("written %s\n", stableIndexFilePath)
|
||||
|
||||
// Create symlinks to latest stable versions.
|
||||
symlinksDir := registry.StorageDir().ChildDir("latest", 0o755)
|
||||
err = registry.CreateSymlinks(symlinksDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("updated stable symlinks in %s\n", symlinksDir.Path)
|
||||
fmt.Printf("written %s\n", indexFilePath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateToLatestVersion(stable, beta bool) error {
|
||||
for _, resource := range registry.Export() {
|
||||
sort.Sort(resource)
|
||||
err := resource.AddVersion(resource.Versions[0].VersionNumber, false, stable, beta)
|
||||
func removeFilesFromIndex(versions map[string]string) error {
|
||||
// Print preview.
|
||||
fmt.Println("To be deleted:")
|
||||
for _, filePath := range versions {
|
||||
fmt.Println(filePath)
|
||||
}
|
||||
|
||||
// Ask for confirmation.
|
||||
if !confirm("\nDo you want to delete these files?") {
|
||||
fmt.Println("aborted...")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete files.
|
||||
for _, filePath := range versions {
|
||||
err := os.Remove(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("deleted")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getChannelVersions(channel string, storagePath bool) map[string]string {
|
||||
// Sort all versions.
|
||||
registry.SelectVersions()
|
||||
export := registry.Export()
|
||||
|
||||
// Go through all versions and save the highest version, if not stable or beta.
|
||||
versions := make(map[string]string)
|
||||
for _, rv := range export {
|
||||
for _, v := range rv.Versions {
|
||||
// Ignore versions that don't match the release channel.
|
||||
if v.SemVer().Prerelease() != channel {
|
||||
// Stop at the first stable version, nothing should ever be selected
|
||||
// beyond that.
|
||||
if v.SemVer().Prerelease() == "" {
|
||||
break
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Add highest version of matching release channel.
|
||||
if storagePath {
|
||||
versions[rv.Identifier] = rv.GetFile().Path()
|
||||
} else {
|
||||
versions[rv.Identifier] = v.VersionNumber
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return versions
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ var scanCmd = &cobra.Command{
|
||||
|
||||
func scan(cmd *cobra.Command, args []string) error {
|
||||
// Reset and rescan.
|
||||
registry.Reset()
|
||||
registry.ResetResources()
|
||||
err := registry.ScanStorage("")
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -36,8 +36,8 @@ func scan(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportSelected(beta bool) map[string]string {
|
||||
registry.SetBeta(beta)
|
||||
func exportSelected(preReleases bool) map[string]string {
|
||||
registry.SetUsePreReleases(preReleases)
|
||||
registry.SelectVersions()
|
||||
export := registry.Export()
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
stageReset bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(stageCmd)
|
||||
stageCmd.Flags().BoolVar(&stageReset, "reset", false, "Reset staging assets")
|
||||
}
|
||||
|
||||
var stageCmd = &cobra.Command{
|
||||
Use: "stage",
|
||||
Short: "Stage scans the specified directory and loads the indexes - it then creates a staging index with all files newer than the stable and beta indexes",
|
||||
RunE: stage,
|
||||
}
|
||||
|
||||
func stage(cmd *cobra.Command, args []string) error {
|
||||
// Check if we want to reset staging instead.
|
||||
if stageReset {
|
||||
for _, stagedPath := range exportStaging(true) {
|
||||
err := os.Remove(stagedPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Export all staged versions and format them.
|
||||
stagingData, err := json.MarshalIndent(exportStaging(false), "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build destination path.
|
||||
stagingIndexFilePath := filepath.Join(registry.StorageDir().Path, "staging.json")
|
||||
|
||||
// Print preview.
|
||||
fmt.Printf("staging (%s):\n", stagingIndexFilePath)
|
||||
fmt.Println(string(stagingData))
|
||||
|
||||
// Ask for confirmation.
|
||||
if !confirm("\nDo you want to write this index?") {
|
||||
fmt.Println("aborted...")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write new index to disk.
|
||||
err = ioutil.WriteFile(stagingIndexFilePath, stagingData, 0o644) //nolint:gosec // 0644 is intended
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("written %s\n", stagingIndexFilePath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func exportStaging(storagePath bool) map[string]string {
|
||||
// Sort all versions.
|
||||
registry.SetBeta(false)
|
||||
registry.SelectVersions()
|
||||
export := registry.Export()
|
||||
|
||||
// Go through all versions and save the highest version, if not stable or beta.
|
||||
versions := make(map[string]string)
|
||||
for _, rv := range export {
|
||||
// Get highest version.
|
||||
v := rv.Versions[0]
|
||||
|
||||
// Do not take stable or beta releases into account.
|
||||
if v.StableRelease || v.BetaRelease {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add highest version to staging
|
||||
if storagePath {
|
||||
rv.SelectedVersion = v
|
||||
versions[rv.Identifier] = rv.GetFile().Path()
|
||||
} else {
|
||||
versions[rv.Identifier] = v.VersionNumber
|
||||
}
|
||||
}
|
||||
|
||||
return versions
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -30,7 +30,7 @@ require (
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
|
||||
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
|
||||
github.com/tevino/abool v1.2.0
|
||||
github.com/tidwall/gjson v1.7.5 // indirect
|
||||
github.com/tidwall/gjson v1.7.5
|
||||
github.com/tidwall/sjson v1.1.6 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/safing/portbase/notifications"
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
"github.com/tevino/abool"
|
||||
|
||||
"github.com/safing/portbase/config"
|
||||
@@ -20,6 +21,7 @@ var (
|
||||
devMode config.BoolOption
|
||||
enableUpdates config.BoolOption
|
||||
|
||||
initialReleaseChannel string
|
||||
previousReleaseChannel string
|
||||
updatesCurrentlyEnabled bool
|
||||
previousDevMode bool
|
||||
@@ -29,21 +31,33 @@ var (
|
||||
func registerConfig() error {
|
||||
err := config.Register(&config.Option{
|
||||
Name: "Release Channel",
|
||||
Key: releaseChannelKey,
|
||||
Key: helper.ReleaseChannelKey,
|
||||
Description: "Switch release channel.",
|
||||
OptType: config.OptTypeString,
|
||||
ExpertiseLevel: config.ExpertiseLevelDeveloper,
|
||||
ReleaseLevel: config.ReleaseLevelExperimental,
|
||||
RequiresRestart: false,
|
||||
DefaultValue: releaseChannelStable,
|
||||
RequiresRestart: true,
|
||||
DefaultValue: helper.ReleaseChannelStable,
|
||||
PossibleValues: []config.PossibleValue{
|
||||
{
|
||||
Name: "Stable",
|
||||
Value: releaseChannelStable,
|
||||
Name: "Stable",
|
||||
Description: "Production releases.",
|
||||
Value: helper.ReleaseChannelStable,
|
||||
},
|
||||
{
|
||||
Name: "Beta",
|
||||
Value: releaseChannelBeta,
|
||||
Name: "Beta",
|
||||
Description: "Production releases for testing new features that may break and cause interruption.",
|
||||
Value: helper.ReleaseChannelBeta,
|
||||
},
|
||||
{
|
||||
Name: "Special",
|
||||
Description: "Special releases or version changes for troubleshooting. Only use temporarily and when instructed.",
|
||||
Value: helper.ReleaseChannelSpecial,
|
||||
},
|
||||
{
|
||||
Name: "Staging",
|
||||
Description: "Dangerous development releases for testing random things and experimenting. Only use temporarily and when instructed.",
|
||||
Value: helper.ReleaseChannelStaging,
|
||||
},
|
||||
},
|
||||
Annotations: config.Annotations{
|
||||
@@ -78,7 +92,8 @@ func registerConfig() error {
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
releaseChannel = config.GetAsString(releaseChannelKey, releaseChannelStable)
|
||||
releaseChannel = config.GetAsString(helper.ReleaseChannelKey, helper.ReleaseChannelStable)
|
||||
initialReleaseChannel = releaseChannel()
|
||||
previousReleaseChannel = releaseChannel()
|
||||
|
||||
enableUpdates = config.GetAsBool(enableUpdatesKey, true)
|
||||
@@ -107,7 +122,7 @@ func updateRegistryConfig(_ context.Context, _ interface{}) error {
|
||||
changed := false
|
||||
|
||||
if releaseChannel() != previousReleaseChannel {
|
||||
registry.SetBeta(releaseChannel() == releaseChannelBeta)
|
||||
registry.SetUsePreReleases(releaseChannel() != helper.ReleaseChannelStable)
|
||||
previousReleaseChannel = releaseChannel()
|
||||
changed = true
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ import (
|
||||
"github.com/safing/portbase/info"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/updater"
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
)
|
||||
|
||||
// database key for update information
|
||||
// Database key for update information.
|
||||
const (
|
||||
versionsDBKey = "core:status/versions"
|
||||
)
|
||||
|
||||
// working vars
|
||||
var (
|
||||
versionExport *versions
|
||||
versionExportDB = database.NewInterface(&database.Options{
|
||||
@@ -35,6 +35,7 @@ type versions struct {
|
||||
|
||||
Core *info.Info
|
||||
Resources map[string]*updater.Resource
|
||||
Channel string
|
||||
Beta bool
|
||||
Staging bool
|
||||
|
||||
@@ -45,8 +46,9 @@ func initVersionExport() (err error) {
|
||||
// init export struct
|
||||
versionExport = &versions{
|
||||
internalSave: true,
|
||||
Beta: registry.Beta,
|
||||
Staging: staging,
|
||||
Channel: initialReleaseChannel,
|
||||
Beta: initialReleaseChannel == helper.ReleaseChannelBeta,
|
||||
Staging: initialReleaseChannel == helper.ReleaseChannelStaging,
|
||||
}
|
||||
versionExport.SetKey(versionsDBKey)
|
||||
|
||||
@@ -68,7 +70,7 @@ func stopVersionExport() error {
|
||||
return versionExportHook.Cancel()
|
||||
}
|
||||
|
||||
// export is an event hook
|
||||
// export is an event hook.
|
||||
func export(_ context.Context, _ interface{}) error {
|
||||
// populate
|
||||
versionExport.lock.Lock()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -54,14 +53,6 @@ func EnsureChromeSandboxPermissions(reg *updater.ResourceRegistry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PlatformIdentifier converts identifier for the current platform.
|
||||
func PlatformIdentifier(identifier string) string {
|
||||
// From https://golang.org/pkg/runtime/#GOARCH
|
||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
func checkSysctl(setting string, value byte) bool {
|
||||
c, err := sysctl(setting)
|
||||
if err != nil {
|
||||
|
||||
58
updates/helper/indexes.go
Normal file
58
updates/helper/indexes.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/updater"
|
||||
)
|
||||
|
||||
const (
|
||||
ReleaseChannelKey = "core/releaseChannel"
|
||||
ReleaseChannelJSONKey = "core.releaseChannel"
|
||||
ReleaseChannelStable = "stable"
|
||||
ReleaseChannelBeta = "beta"
|
||||
ReleaseChannelStaging = "staging"
|
||||
ReleaseChannelSpecial = "special"
|
||||
)
|
||||
|
||||
func SetIndexes(registry *updater.ResourceRegistry, releaseChannel string) {
|
||||
// Be reminded that the order is important, as indexes added later will
|
||||
// override the current release from earlier indexes.
|
||||
|
||||
// Reset indexes before adding them (again).
|
||||
registry.ResetIndexes()
|
||||
|
||||
// Always add the stable index as a base.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: ReleaseChannelStable + ".json",
|
||||
})
|
||||
|
||||
// Add beta index if in beta or staging channel.
|
||||
if releaseChannel == ReleaseChannelBeta ||
|
||||
releaseChannel == ReleaseChannelStaging {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: ReleaseChannelBeta + ".json",
|
||||
PreRelease: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add staging index if in staging channel.
|
||||
if releaseChannel == ReleaseChannelStaging {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: ReleaseChannelStaging + ".json",
|
||||
PreRelease: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add special index if in special channel.
|
||||
if releaseChannel == ReleaseChannelSpecial {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: ReleaseChannelSpecial + ".json",
|
||||
})
|
||||
}
|
||||
|
||||
// Add the intel index last, as it updates the fastest and should not be
|
||||
// crippled by other faulty indexes. It can only specify versions for its
|
||||
// scope anyway.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "all/intel/intel.json",
|
||||
})
|
||||
}
|
||||
68
updates/helper/updates.go
Normal file
68
updates/helper/updates.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
onWindows = runtime.GOOS == "windows"
|
||||
)
|
||||
|
||||
// PlatformIdentifier converts identifier for the current platform.
|
||||
func PlatformIdentifier(identifier string) string {
|
||||
// From https://golang.org/pkg/runtime/#GOARCH
|
||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
// MandatoryUpdates returns mandatory updates that should be loaded on install
|
||||
// or reset.
|
||||
func MandatoryUpdates() (identifiers []string) {
|
||||
// Binaries
|
||||
if onWindows {
|
||||
identifiers = []string{
|
||||
PlatformIdentifier("core/portmaster-core.exe"),
|
||||
PlatformIdentifier("kext/portmaster-kext.dll"),
|
||||
PlatformIdentifier("kext/portmaster-kext.sys"),
|
||||
PlatformIdentifier("start/portmaster-start.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-snoretoast.exe"),
|
||||
}
|
||||
} else {
|
||||
identifiers = []string{
|
||||
PlatformIdentifier("core/portmaster-core"),
|
||||
PlatformIdentifier("start/portmaster-start"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier"),
|
||||
}
|
||||
}
|
||||
|
||||
// Components, Assets and Data
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
|
||||
// User interface components
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
"all/ui/modules/assets.zip",
|
||||
|
||||
// Filter lists data
|
||||
"all/intel/lists/base.dsdl",
|
||||
"all/intel/lists/intermediate.dsdl",
|
||||
"all/intel/lists/urgent.dsdl",
|
||||
|
||||
// Geo IP data
|
||||
"all/intel/geoip/geoipv4.mmdb.gz",
|
||||
"all/intel/geoip/geoipv6.mmdb.gz",
|
||||
)
|
||||
|
||||
return identifiers
|
||||
}
|
||||
|
||||
// AutoUnpackUpdates returns assets that need unpacking.
|
||||
func AutoUnpackUpdates() []string {
|
||||
return []string{
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
}
|
||||
}
|
||||
114
updates/main.go
114
updates/main.go
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/updates/helper"
|
||||
|
||||
"github.com/safing/portbase/dataroot"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/modules"
|
||||
@@ -19,10 +19,6 @@ import (
|
||||
const (
|
||||
onWindows = runtime.GOOS == "windows"
|
||||
|
||||
releaseChannelKey = "core/releaseChannel"
|
||||
releaseChannelStable = "stable"
|
||||
releaseChannelBeta = "beta"
|
||||
|
||||
enableUpdatesKey = "core/automaticUpdates"
|
||||
|
||||
// ModuleName is the name of the update module
|
||||
@@ -48,16 +44,11 @@ var (
|
||||
module *modules.Module
|
||||
registry *updater.ResourceRegistry
|
||||
userAgentFromFlag string
|
||||
staging bool
|
||||
|
||||
updateTask *modules.Task
|
||||
updateASAP bool
|
||||
disableTaskSchedule bool
|
||||
|
||||
// MandatoryUpdates is a list of full identifiers that
|
||||
// should always be kept up to date.
|
||||
MandatoryUpdates []string
|
||||
|
||||
// UserAgent is an HTTP User-Agent that is used to add
|
||||
// more context to requests made by the registry when
|
||||
// fetching resources from the update server.
|
||||
@@ -65,9 +56,8 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
updateInProgress = "updates:in-progress"
|
||||
updateFailed = "updates:failed"
|
||||
updateSuccess = "updates:success"
|
||||
updateFailed = "updates:failed"
|
||||
updateSuccess = "updates:success"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -76,29 +66,9 @@ func init() {
|
||||
module.RegisterEvent(ResourceUpdateEvent, true)
|
||||
|
||||
flag.StringVar(&userAgentFromFlag, "update-agent", "", "set the user agent for requests to the update server")
|
||||
flag.BoolVar(&staging, "staging", false, "use staging update channel; for testing only")
|
||||
|
||||
// initialize mandatory updates
|
||||
if onWindows {
|
||||
MandatoryUpdates = []string{
|
||||
platform("core/portmaster-core.exe"),
|
||||
platform("start/portmaster-start.exe"),
|
||||
platform("notifier/portmaster-notifier.exe"),
|
||||
platform("notifier/portmaster-snoretoast.exe"),
|
||||
}
|
||||
} else {
|
||||
MandatoryUpdates = []string{
|
||||
platform("core/portmaster-core"),
|
||||
platform("start/portmaster-start"),
|
||||
platform("notifier/portmaster-notifier"),
|
||||
}
|
||||
}
|
||||
|
||||
MandatoryUpdates = append(
|
||||
MandatoryUpdates,
|
||||
platform("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
)
|
||||
var dummy bool
|
||||
flag.BoolVar(&dummy, "staging", false, "deprecated, configure in settings instead")
|
||||
}
|
||||
|
||||
func prep() error {
|
||||
@@ -107,8 +77,6 @@ func prep() error {
|
||||
}
|
||||
|
||||
return registerAPIEndpoints()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func start() error {
|
||||
@@ -131,13 +99,11 @@ func start() error {
|
||||
"https://updates.safing.io",
|
||||
},
|
||||
UserAgent: UserAgent,
|
||||
MandatoryUpdates: MandatoryUpdates,
|
||||
AutoUnpack: []string{
|
||||
platform("app/portmaster-app.zip"),
|
||||
},
|
||||
Beta: releaseChannel() == releaseChannelBeta,
|
||||
DevMode: devMode(),
|
||||
Online: true,
|
||||
MandatoryUpdates: helper.MandatoryUpdates(),
|
||||
AutoUnpack: helper.AutoUnpackUpdates(),
|
||||
UsePreReleases: initialReleaseChannel != helper.ReleaseChannelStable,
|
||||
DevMode: devMode(),
|
||||
Online: true,
|
||||
}
|
||||
if userAgentFromFlag != "" {
|
||||
// override with flag value
|
||||
@@ -149,38 +115,8 @@ func start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "stable.json",
|
||||
Stable: true,
|
||||
Beta: false,
|
||||
})
|
||||
|
||||
if registry.Beta {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "beta.json",
|
||||
Stable: false,
|
||||
Beta: true,
|
||||
})
|
||||
}
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "all/intel/intel.json",
|
||||
Stable: true,
|
||||
Beta: true,
|
||||
})
|
||||
|
||||
if stagingActive() {
|
||||
// Set flag no matter how staging was activated.
|
||||
staging = true
|
||||
|
||||
log.Warning("updates: staging environment is active")
|
||||
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "staging.json",
|
||||
Stable: true,
|
||||
Beta: true,
|
||||
})
|
||||
}
|
||||
// Set indexes based on the release channel.
|
||||
helper.SetIndexes(registry, initialReleaseChannel)
|
||||
|
||||
err = registry.LoadIndexes(module.Ctx)
|
||||
if err != nil {
|
||||
@@ -293,7 +229,7 @@ func checkForUpdates(ctx context.Context) (err error) {
|
||||
notifications.NotifyWarn(
|
||||
updateFailed,
|
||||
"Update Check Failed",
|
||||
"The Portmaster failed to check for updates. This might be a temporary issue of your device, your network or the update servers. The Portmaster will automatically try again later.",
|
||||
"The Portmaster failed to check for updates. This might be a temporary issue of your device, your network or the update servers. The Portmaster will automatically try again later. If you just installed the Portmaster, please try disabling potentially conflicting software, such as other firewalls or VPNs.",
|
||||
notifications.Action{
|
||||
ID: "retry",
|
||||
Text: "Try Again Now",
|
||||
@@ -308,12 +244,13 @@ func checkForUpdates(ctx context.Context) (err error) {
|
||||
}()
|
||||
|
||||
if err = registry.UpdateIndexes(ctx); err != nil {
|
||||
log.Warningf("updates: failed to update indexes: %s", err)
|
||||
err = fmt.Errorf("failed to update indexes: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = registry.DownloadUpdates(ctx)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update: %w", err)
|
||||
err = fmt.Errorf("failed to download updates: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -322,7 +259,7 @@ func checkForUpdates(ctx context.Context) (err error) {
|
||||
// Unpack selected resources.
|
||||
err = registry.UnpackResources()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to update: %w", err)
|
||||
err = fmt.Errorf("failed to unpack updates: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -341,21 +278,6 @@ func stop() error {
|
||||
return stopVersionExport()
|
||||
}
|
||||
|
||||
func platform(identifier string) string {
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
func stagingActive() bool {
|
||||
// Check flag and env variable.
|
||||
if staging || os.Getenv("PORTMASTER_STAGING") == "enabled" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if staging index is present and acessible.
|
||||
_, err := os.Stat(filepath.Join(registry.StorageDir().Path, "staging.json"))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// RootPath returns the root path used for storing updates.
|
||||
func RootPath() string {
|
||||
if !module.Online() {
|
||||
|
||||
@@ -351,10 +351,9 @@ func upgradeFile(fileToUpgrade string, file *updater.File) error {
|
||||
}
|
||||
|
||||
// CopyFile atomically copies a file using the update registry's tmp dir.
|
||||
func CopyFile(srcPath, dstPath string) (err error) {
|
||||
|
||||
func CopyFile(srcPath, dstPath string) error {
|
||||
// check tmp dir
|
||||
err = registry.TmpDir().Ensure()
|
||||
err := registry.TmpDir().Ensure()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not prepare tmp directory for copying file: %w", err)
|
||||
}
|
||||
@@ -369,14 +368,14 @@ func CopyFile(srcPath, dstPath string) (err error) {
|
||||
// open source
|
||||
srcFile, err := os.Open(srcPath)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// copy data
|
||||
_, err = io.Copy(atomicDstFile, srcFile)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// finalize file
|
||||
|
||||
Reference in New Issue
Block a user