feat: upgrade segment

This commit is contained in:
Jan De Dobbeleer 2023-05-18 19:42:57 +02:00 committed by Jan De Dobbeleer
parent e343ded54a
commit f938794ccd
12 changed files with 243 additions and 17 deletions

View file

@ -62,6 +62,7 @@ var printCmd = &cobra.Command{
Primary: args[0] == "primary",
Cleared: cleared,
NoExitCode: noExitCode,
Version: cliVersion,
}
eng := engine.New(flags)

View file

@ -231,6 +231,8 @@ const (
UI5TOOLING SegmentType = "ui5tooling"
// UNITY writes which Unity version is currently active
UNITY SegmentType = "unity"
// UPGRADE lets you know if you can upgrade Oh My Posh
UPGRADE SegmentType = "upgrade"
// VALA writes the active vala version
VALA SegmentType = "vala"
// WAKATIME writes tracked time spend in dev editors
@ -315,6 +317,7 @@ var Segments = map[SegmentType]func() SegmentWriter{
TIME: func() SegmentWriter { return &segments.Time{} },
UI5TOOLING: func() SegmentWriter { return &segments.UI5Tooling{} },
UNITY: func() SegmentWriter { return &segments.Unity{} },
UPGRADE: func() SegmentWriter { return &segments.Upgrade{} },
VALA: func() SegmentWriter { return &segments.Vala{} },
WAKATIME: func() SegmentWriter { return &segments.Wakatime{} },
WINREG: func() SegmentWriter { return &segments.WindowsRegistry{} },

View file

@ -54,8 +54,6 @@ const (
BFDayIcon properties.Property = "day_icon"
BFCacheTimeout properties.Property = "cache_timeout"
BFStatusPlanning string = "Planning"
BFStatusBrewing string = "Brewing"
BFStatusFermenting string = "Fermenting"
@ -247,7 +245,7 @@ func (bf *Brewfather) getResult() (*Batch, error) {
batchReadingsURL := fmt.Sprintf("https://api.brewfather.app/v1/batches/%s/readings", batchID)
httpTimeout := bf.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
cacheTimeout := bf.props.GetInt(BFCacheTimeout, 5)
cacheTimeout := bf.props.GetInt(properties.CacheTimeout, 5)
if cacheTimeout > 0 {
if data, err := getFromCache(batchURL); err == nil {

View file

@ -77,7 +77,7 @@ func TestGitversion(t *testing.T) {
env.On("Pwd").Return("test-dir")
env.On("Cache").Return(cache)
cache.On("Get", "test-dir").Return(tc.CacheResponse, len(tc.CacheResponse) != 0)
cache.On("Set", mock2.Anything, mock2.Anything, mock2.Anything).Return(tc.Response, true)
cache.On("Set", mock2.Anything, mock2.Anything, mock2.Anything)
env.On("RunCommand", "gitversion", []string{"-output", "json"}).Return(tc.Response, tc.CommandError)

View file

@ -29,8 +29,6 @@ const (
FortyFiveDownIcon properties.Property = "fortyfivedown_icon"
SingleDownIcon properties.Property = "singledown_icon"
DoubleDownIcon properties.Property = "doubledown_icon"
NSCacheTimeout properties.Property = "cache_timeout"
)
// NightscoutData struct contains the API data
@ -110,7 +108,7 @@ func (ns *Nightscout) getResult() (*NightscoutData, error) {
url := ns.props.GetString(URL, "")
httpTimeout := ns.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
// natural and understood NS timeout is 5, anything else is unusual
cacheTimeout := ns.props.GetInt(NSCacheTimeout, 5)
cacheTimeout := ns.props.GetInt(properties.CacheTimeout, 5)
if cacheTimeout > 0 {
if data, err := getCacheValue(url); err == nil {

86
src/segments/upgrade.go Normal file
View file

@ -0,0 +1,86 @@
package segments
import (
"encoding/json"
"errors"
"fmt"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
)
type UpgradeCache struct {
Latest string `json:"latest"`
Current string `json:"current"`
}
type Upgrade struct {
props properties.Properties
env platform.Environment
Version string
}
const UPGRADECACHEKEY = "upgrade_segment"
func (u *Upgrade) Template() string {
return " \uf019 "
}
func (u *Upgrade) Init(props properties.Properties, env platform.Environment) {
u.props = props
u.env = env
}
func (u *Upgrade) Enabled() bool {
version := fmt.Sprintf("v%s", u.env.Flags().Version)
if shouldDisplay, err := u.ShouldDisplay(version); err == nil {
return shouldDisplay
}
latest, err := upgrade.Latest(u.env)
if err != nil {
return false
}
if latest == version {
return false
}
cacheData := &UpgradeCache{
Latest: latest,
Current: version,
}
cacheJSON, err := json.Marshal(cacheData)
if err != nil {
return false
}
oneWeek := 10080
cacheTimeout := u.props.GetInt(properties.CacheTimeout, oneWeek)
u.env.Cache().Set(UPGRADECACHEKEY, string(cacheJSON), cacheTimeout)
u.Version = latest
return true
}
func (u *Upgrade) ShouldDisplay(version string) (bool, error) {
data, OK := u.env.Cache().Get(UPGRADECACHEKEY)
if !OK {
return false, errors.New("no cache")
}
var cacheJSON UpgradeCache
err := json.Unmarshal([]byte(data), &cacheJSON)
if err != nil {
return false, errors.New("invalid cache data")
}
if version == cacheJSON.Current {
return cacheJSON.Current != cacheJSON.Latest, nil
}
return false, errors.New("version changed, run the check again")
}

View file

@ -0,0 +1,93 @@
package segments
import (
"errors"
"fmt"
"testing"
"github.com/jandedobbeleer/oh-my-posh/src/mock"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
"github.com/alecthomas/assert"
mock2 "github.com/stretchr/testify/mock"
)
func TestUpgrade(t *testing.T) {
cases := []struct {
Case string
ExpectedEnabled bool
HasCache bool
CurrentVersion string
LatestVersion string
CacheVersion string
Error error
}{
{
Case: "Should upgrade",
CurrentVersion: "1.0.0",
LatestVersion: "1.0.1",
ExpectedEnabled: true,
},
{
Case: "On latest",
CurrentVersion: "1.0.1",
LatestVersion: "1.0.1",
},
{
Case: "Version error",
Error: errors.New("error"),
},
{
Case: "On previous, from cache",
HasCache: true,
CurrentVersion: "1.0.2",
LatestVersion: "1.0.3",
CacheVersion: "1.0.2",
ExpectedEnabled: true,
},
{
Case: "On latest, version changed",
HasCache: true,
CurrentVersion: "1.0.2",
LatestVersion: "1.0.2",
CacheVersion: "1.0.1",
},
{
Case: "On previous, version changed",
HasCache: true,
CurrentVersion: "1.0.2",
LatestVersion: "1.0.3",
CacheVersion: "1.0.1",
ExpectedEnabled: true,
},
}
for _, tc := range cases {
env := new(mock.MockedEnvironment)
cache := &mock.MockedCache{}
env.On("Cache").Return(cache)
if len(tc.CacheVersion) == 0 {
tc.CacheVersion = tc.CurrentVersion
}
cacheData := fmt.Sprintf(`{"latest":"v%s", "current": "v%s"}`, tc.LatestVersion, tc.CacheVersion)
cache.On("Get", UPGRADECACHEKEY).Return(cacheData, tc.HasCache)
cache.On("Set", mock2.Anything, mock2.Anything, mock2.Anything)
env.On("Flags").Return(&platform.Flags{Version: tc.CurrentVersion})
json := fmt.Sprintf(`{"tag_name":"v%s"}`, tc.LatestVersion)
env.On("HTTPRequest", upgrade.RELEASEURL).Return([]byte(json), tc.Error)
ug := &Upgrade{
env: env,
props: properties.Map{},
}
enabled := ug.Enabled()
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
}
}

View file

@ -29,7 +29,7 @@ type release struct {
}
const (
releaseURL = "https://api.github.com/repos/jandedobbeleer/oh-my-posh/releases/latest"
RELEASEURL = "https://api.github.com/repos/jandedobbeleer/oh-my-posh/releases/latest"
upgradeNotice = `
A new release of Oh My Posh is available: %s %s
%s
@ -42,8 +42,8 @@ https://ohmyposh.dev/docs/installation/windows#update`
CACHEKEY = "upgrade_check"
)
func getLatestVersion(env platform.Environment) (string, error) {
body, err := env.HTTPRequest(releaseURL, nil, 1000)
func Latest(env platform.Environment) (string, error) {
body, err := env.HTTPRequest(RELEASEURL, nil, 1000)
if err != nil {
return "", err
}
@ -67,7 +67,7 @@ func Notice(env platform.Environment) (string, bool) {
return "", false
}
latest, err := getLatestVersion(env)
latest, err := Latest(env)
if err != nil {
return "", false
}

View file

@ -44,7 +44,7 @@ func TestCanUpgrade(t *testing.T) {
env.On("Getenv", "POSH_INSTALLER").Return(tc.Installer)
json := fmt.Sprintf(`{"tag_name":"%s"}`, tc.LatestVersion)
env.On("HTTPRequest", releaseURL).Return([]byte(json), tc.Error)
env.On("HTTPRequest", RELEASEURL).Return([]byte(json), tc.Error)
// ignore the notice
_, canUpgrade := Notice(env)
assert.Equal(t, tc.Expected, canUpgrade, tc.Case)

View file

@ -15,8 +15,8 @@ You can use the following template as a guide.
package segments
import (
"oh-my-posh/platform"
"oh-my-posh/properties"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/jandedobbeleer/oh-my-posh/src/properties"
)
type New struct {
@ -31,15 +31,15 @@ const (
NewProp properties.Property = "newprop"
)
func (n *new) Enabled() bool {
func (n *New) Enabled() bool {
return true
}
func (n *new) Template() string {
func (n *New) Template() string {
return " {{.Text}} world "
}
func (n *new) Init(props properties.Properties, env platform.Environment) {
func (n *New) Init(props properties.Properties, env platform.Environment) {
n.props = props
n.env = env

View file

@ -0,0 +1,46 @@
---
id: upgrade
title: Upgrade notice
sidebar_label: Upgrade
---
## What
Displays when there's an update available for Oh My Posh.
## Sample Configuration
import Config from "@site/src/components/Config.js";
<Config
data={{
type: "upgrade",
style: "plain",
foreground: "#111111",
background: "#FFD664",
}}
/>
## Properties
| Name | Type | Description |
| --------------- | ----- | --------------------------------------------------------------------------------------------- |
| `cache_timeout` | `int` | in minutes - How long to wait before checking for a new version. Default is 10080 (one week). |
## Template ([info][templates])
:::note default template
```template
\uf019
```
:::
### Properties
| Name | Type | Description |
| ---------- | -------- | ---------------------- |
| `.Version` | `string` | the new version number |
[templates]: /docs/configuration/templates

View file

@ -118,6 +118,7 @@ module.exports = {
"segments/time",
"segments/ui5tooling",
"segments/unity",
"segments/upgrade",
"segments/vala",
"segments/wakatime",
"segments/withings",