diff --git a/updates.go b/updates.go index 9f4c3c0..8ecccf6 100644 --- a/updates.go +++ b/updates.go @@ -1,130 +1,131 @@ /* * Copyright © 2019-2020 A Bunch Tell LLC. * * This file is part of WriteFreely. * * WriteFreely is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, included * in the LICENSE file in this source code package. */ package writefreely import ( "github.com/writeas/web-core/log" "io/ioutil" "net/http" "strings" "sync" "time" ) // updatesCacheTime is the default interval between cache updates for new // software versions const defaultUpdatesCacheTime = 12 * time.Hour // updatesCache holds data about current and new releases of the writefreely // software type updatesCache struct { mu sync.Mutex frequency time.Duration lastCheck time.Time latestVersion string currentVersion string checkError error } // CheckNow asks for the latest released version of writefreely and updates // the cache last checked time. If the version postdates the current 'latest' // the version value is replaced. func (uc *updatesCache) CheckNow() error { if debugging { log.Info("[update check] Checking for update now.") } uc.mu.Lock() defer uc.mu.Unlock() uc.lastCheck = time.Now() latestRemote, err := newVersionCheck() if err != nil { log.Error("[update check] Failed: %v", err) uc.checkError = err return err } if CompareSemver(latestRemote, uc.latestVersion) == 1 { uc.latestVersion = latestRemote } return nil } // AreAvailable updates the cache if the frequency duration has passed // then returns if the latest release is newer than the current running version. func (uc updatesCache) AreAvailable() bool { if time.Since(uc.lastCheck) > uc.frequency { uc.CheckNow() } return CompareSemver(uc.latestVersion, uc.currentVersion) == 1 } // AreAvailableNoCheck returns if the latest release is newer than the current // running version. func (uc updatesCache) AreAvailableNoCheck() bool { return CompareSemver(uc.latestVersion, uc.currentVersion) == 1 } // LatestVersion returns the latest stored version available. func (uc updatesCache) LatestVersion() string { return uc.latestVersion } func (uc updatesCache) ReleaseURL() string { return "https://writefreely.org/releases/" + uc.latestVersion } // ReleaseNotesURL returns the full URL to the blog.writefreely.org release notes // for the latest version as stored in the cache. func (uc updatesCache) ReleaseNotesURL() string { return wfReleaseNotesURL(uc.latestVersion) } func wfReleaseNotesURL(v string) string { ver := strings.TrimPrefix(v, "v") ver = strings.TrimSuffix(ver, ".0") // hack until go 1.12 in build/travis seg := strings.Split(ver, ".") return "https://blog.writefreely.org/version-" + strings.Join(seg, "-") } // newUpdatesCache returns an initialized updates cache func newUpdatesCache(expiry time.Duration) *updatesCache { cache := updatesCache{ frequency: expiry, currentVersion: "v" + softwareVer, } - cache.CheckNow() + go cache.CheckNow() return &cache } // InitUpdates initializes the updates cache, if the config value is set // It uses the defaultUpdatesCacheTime for the cache expiry func (app *App) InitUpdates() { if app.cfg.App.UpdateChecks { app.updates = newUpdatesCache(defaultUpdatesCacheTime) } } func newVersionCheck() (string, error) { res, err := http.Get("https://version.writefreely.org") if debugging { log.Info("[update check] GET https://version.writefreely.org") } + // TODO: return error if statusCode != OK if err == nil && res.StatusCode == http.StatusOK { defer res.Body.Close() body, err := ioutil.ReadAll(res.Body) if err != nil { return "", err } return string(body), nil } return "", err }