mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-14 23:14:05 -08:00
feat(cache): remove segment specific caching
This commit is contained in:
parent
a45fb3991e
commit
4fe6efc94a
13
src/cache/cache.go
vendored
13
src/cache/cache.go
vendored
|
@ -14,11 +14,11 @@ type Cache interface {
|
||||||
Close()
|
Close()
|
||||||
// Gets the value for a given key.
|
// Gets the value for a given key.
|
||||||
// Returns the value and a boolean indicating if the key was found.
|
// Returns the value and a boolean indicating if the key was found.
|
||||||
// In case the ttl expired, the function returns false.
|
// In case the duration expired, the function returns false.
|
||||||
Get(key string) (string, bool)
|
Get(key string) (string, bool)
|
||||||
// Sets a value for a given key.
|
// Sets a value for a given key.
|
||||||
// The ttl indicates how many minutes to cache the value.
|
// The duration indicates how many minutes to cache the value.
|
||||||
Set(key, value string, ttl int)
|
Set(key, value string, duration Duration)
|
||||||
// Deletes a key from the cache.
|
// Deletes a key from the cache.
|
||||||
Delete(key string)
|
Delete(key string)
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,6 @@ const (
|
||||||
PROMPTCOUNTCACHE = "prompt_count_cache"
|
PROMPTCOUNTCACHE = "prompt_count_cache"
|
||||||
ENGINECACHE = "engine_cache"
|
ENGINECACHE = "engine_cache"
|
||||||
FONTLISTCACHE = "font_list_cache"
|
FONTLISTCACHE = "font_list_cache"
|
||||||
|
|
||||||
ONEDAY = 1440
|
|
||||||
ONEWEEK = 10080
|
|
||||||
ONEMONTH = 43200
|
|
||||||
INFINITE = -1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
|
@ -63,5 +58,5 @@ func (c *Entry) Expired() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return time.Now().Unix() >= (c.Timestamp + int64(c.TTL)*60)
|
return time.Now().Unix() >= (c.Timestamp + int64(c.TTL))
|
||||||
}
|
}
|
||||||
|
|
86
src/cache/duration.go
vendored
Normal file
86
src/cache/duration.go
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/regex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Duration string
|
||||||
|
|
||||||
|
const INFINITE = Duration("infinite")
|
||||||
|
|
||||||
|
func (d Duration) Seconds() int {
|
||||||
|
if d == INFINITE {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
re := `(?P<AMOUNT>[0-9]*)(?P<UNIT>.*)`
|
||||||
|
match := regex.FindNamedRegexMatch(re, string(d))
|
||||||
|
if len(match) < 2 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
amount := match["AMOUNT"]
|
||||||
|
unit := match["UNIT"]
|
||||||
|
|
||||||
|
if len(amount) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
amountInt, err := strconv.Atoi(amount)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var multiplier int
|
||||||
|
|
||||||
|
switch unit {
|
||||||
|
case "second", "seconds":
|
||||||
|
multiplier = 1
|
||||||
|
case "minute", "minutes":
|
||||||
|
multiplier = 60
|
||||||
|
case "hour", "hours":
|
||||||
|
multiplier = 3600
|
||||||
|
case "day", "days":
|
||||||
|
multiplier = 86400
|
||||||
|
case "week", "weeks":
|
||||||
|
multiplier = 604800
|
||||||
|
case "month", "months":
|
||||||
|
multiplier = 2592000
|
||||||
|
}
|
||||||
|
|
||||||
|
return amountInt * multiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Duration) IsEmpty() bool {
|
||||||
|
return len(d) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToDuration(seconds int) Duration {
|
||||||
|
if seconds == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if seconds == -1 {
|
||||||
|
return "infinite"
|
||||||
|
}
|
||||||
|
|
||||||
|
if seconds%604800 == 0 {
|
||||||
|
return Duration(strconv.Itoa(seconds/604800) + "weeks")
|
||||||
|
}
|
||||||
|
|
||||||
|
if seconds%86400 == 0 {
|
||||||
|
return Duration(strconv.Itoa(seconds/86400) + "days")
|
||||||
|
}
|
||||||
|
|
||||||
|
if seconds%3600 == 0 {
|
||||||
|
return Duration(strconv.Itoa(seconds/3600) + "hours")
|
||||||
|
}
|
||||||
|
|
||||||
|
if seconds%60 == 0 {
|
||||||
|
return Duration(strconv.Itoa(seconds/60) + "minutes")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Duration(strconv.Itoa(seconds) + "seconds")
|
||||||
|
}
|
95
src/cache/duration_test.go
vendored
Normal file
95
src/cache/duration_test.go
vendored
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSeconds(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
Case string
|
||||||
|
Duration Duration
|
||||||
|
Expected int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Case: "1 second",
|
||||||
|
Duration: "1second",
|
||||||
|
Expected: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 seconds",
|
||||||
|
Duration: "2seconds",
|
||||||
|
Expected: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 minute",
|
||||||
|
Duration: "1minute",
|
||||||
|
Expected: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 minutes",
|
||||||
|
Duration: "2minutes",
|
||||||
|
Expected: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 hour",
|
||||||
|
Duration: "1hour",
|
||||||
|
Expected: 3600,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 hours",
|
||||||
|
Duration: "2hours",
|
||||||
|
Expected: 7200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 day",
|
||||||
|
Duration: "1day",
|
||||||
|
Expected: 86400,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 days",
|
||||||
|
Duration: "2days",
|
||||||
|
Expected: 172800,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 week",
|
||||||
|
Duration: "1week",
|
||||||
|
Expected: 604800,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 weeks",
|
||||||
|
Duration: "2weeks",
|
||||||
|
Expected: 1209600,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 month",
|
||||||
|
Duration: "1month",
|
||||||
|
Expected: 2592000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "2 months",
|
||||||
|
Duration: "2month",
|
||||||
|
Expected: 5184000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "invalid",
|
||||||
|
Duration: "foo",
|
||||||
|
Expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "1 fortnight",
|
||||||
|
Duration: "1fortnight",
|
||||||
|
Expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Case: "infinite",
|
||||||
|
Duration: "infinite",
|
||||||
|
Expected: -1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
got := tc.Duration.Seconds()
|
||||||
|
assert.Equal(t, tc.Expected, got, tc.Case)
|
||||||
|
}
|
||||||
|
}
|
8
src/cache/file.go
vendored
8
src/cache/file.go
vendored
|
@ -61,7 +61,7 @@ func (fc *File) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the value for the given key as long as
|
// returns the value for the given key as long as
|
||||||
// the TTL (minutes) is not expired
|
// the duration is not expired
|
||||||
func (fc *File) Get(key string) (string, bool) {
|
func (fc *File) Get(key string) (string, bool) {
|
||||||
val, found := fc.cache.Get(key)
|
val, found := fc.cache.Get(key)
|
||||||
if !found {
|
if !found {
|
||||||
|
@ -73,12 +73,12 @@ func (fc *File) Get(key string) (string, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the value for the given key with a TTL (minutes)
|
// sets the value for the given key with a duration
|
||||||
func (fc *File) Set(key, value string, ttl int) {
|
func (fc *File) Set(key, value string, duration Duration) {
|
||||||
fc.cache.Set(key, &Entry{
|
fc.cache.Set(key, &Entry{
|
||||||
Value: value,
|
Value: value,
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
TTL: ttl,
|
TTL: duration.Seconds(),
|
||||||
})
|
})
|
||||||
|
|
||||||
fc.dirty = true
|
fc.dirty = true
|
||||||
|
|
10
src/cache/mock/cache.go
vendored
10
src/cache/mock/cache.go
vendored
|
@ -1,6 +1,9 @@
|
||||||
package mock
|
package mock
|
||||||
|
|
||||||
import mock "github.com/stretchr/testify/mock"
|
import (
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
|
@ -34,8 +37,9 @@ func (_m *Cache) Get(key string) (string, bool) {
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *Cache) Set(key, value string, ttl int) {
|
// set provides a mock function with given fields: key, value, ttl
|
||||||
_m.Called(key, value, ttl)
|
func (_m *Cache) Set(key, value string, duration cache.Duration) {
|
||||||
|
_m.Called(key, value, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_m *Cache) Delete(key string) {
|
func (_m *Cache) Delete(key string) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ var toggleCmd = &cobra.Command{
|
||||||
newToggles = append(newToggles, segment)
|
newToggles = append(newToggles, segment)
|
||||||
}
|
}
|
||||||
|
|
||||||
env.Session().Set(cache.TOGGLECACHE, strings.Join(newToggles, ","), 1440)
|
env.Session().Set(cache.TOGGLECACHE, strings.Join(newToggles, ","), "1day")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ type Segment struct {
|
||||||
Background color.Ansi `json:"background,omitempty" toml:"background,omitempty"`
|
Background color.Ansi `json:"background,omitempty" toml:"background,omitempty"`
|
||||||
Foreground color.Ansi `json:"foreground,omitempty" toml:"foreground,omitempty"`
|
Foreground color.Ansi `json:"foreground,omitempty" toml:"foreground,omitempty"`
|
||||||
Newline bool `json:"newline,omitempty" toml:"newline,omitempty"`
|
Newline bool `json:"newline,omitempty" toml:"newline,omitempty"`
|
||||||
CacheDuration int `json:"cache_duration,omitempty" toml:"cache_duration,omitempty"`
|
CacheDuration cache.Duration `json:"cache_duration,omitempty" toml:"cache_duration,omitempty"`
|
||||||
|
|
||||||
Enabled bool `json:"-" toml:"-"`
|
Enabled bool `json:"-" toml:"-"`
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ func (segment *Segment) isToggled() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (segment *Segment) restoreCache() bool {
|
func (segment *Segment) restoreCache() bool {
|
||||||
if segment.CacheDuration <= 0 {
|
if segment.CacheDuration.IsEmpty() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ func (segment *Segment) restoreCache() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (segment *Segment) setCache() {
|
func (segment *Segment) setCache() {
|
||||||
if segment.CacheDuration <= 0 {
|
if segment.CacheDuration.IsEmpty() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,11 +198,11 @@ func (segment *Segment) setCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (segment *Segment) cacheKey() string {
|
func (segment *Segment) cacheKey() string {
|
||||||
return fmt.Sprintf("segment_cache_%s", segment.Name())
|
return fmt.Sprintf("segment_cache_%s_%s", segment.Name(), segment.env.Pwd())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (segment *Segment) writerCacheKey() string {
|
func (segment *Segment) writerCacheKey() string {
|
||||||
return fmt.Sprintf("segment_cache_writer_%s", segment.Name())
|
return fmt.Sprintf("segment_cache_writer_%s_%s", segment.Name(), segment.env.Pwd())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (segment *Segment) setText() {
|
func (segment *Segment) setText() {
|
||||||
|
|
|
@ -78,7 +78,7 @@ func setCachedFontData(assets []*Asset) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
environment.Cache().Set(cache.FONTLISTCACHE, string(data), cache.ONEDAY)
|
environment.Cache().Set(cache.FONTLISTCACHE, string(data), "1day")
|
||||||
}
|
}
|
||||||
|
|
||||||
func CascadiaCode() ([]*Asset, error) {
|
func CascadiaCode() ([]*Asset, error) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
httplib "net/http"
|
httplib "net/http"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -80,6 +82,7 @@ func (o *OAuthRequest) refreshToken(refreshToken string) (string, error) {
|
||||||
message: Timeout,
|
message: Timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens := &tokenExchange{}
|
tokens := &tokenExchange{}
|
||||||
err = json.Unmarshal(body, &tokens)
|
err = json.Unmarshal(body, &tokens)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -87,17 +90,14 @@ func (o *OAuthRequest) refreshToken(refreshToken string) (string, error) {
|
||||||
message: TokenRefreshFailed,
|
message: TokenRefreshFailed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add tokens to cache
|
// add tokens to cache
|
||||||
o.Env.Cache().Set(o.AccessTokenKey, tokens.AccessToken, tokens.ExpiresIn/60)
|
o.Env.Cache().Set(o.AccessTokenKey, tokens.AccessToken, cache.ToDuration(tokens.ExpiresIn))
|
||||||
o.Env.Cache().Set(o.RefreshTokenKey, tokens.RefreshToken, 2*525960) // it should never expire unless revoked, default to 2 year
|
o.Env.Cache().Set(o.RefreshTokenKey, tokens.RefreshToken, "2years")
|
||||||
return tokens.AccessToken, nil
|
return tokens.AccessToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func OauthResult[a any](o *OAuthRequest, url string, body io.Reader, requestModifiers ...RequestModifier) (a, error) {
|
func OauthResult[a any](o *OAuthRequest, url string, body io.Reader, requestModifiers ...RequestModifier) (a, error) {
|
||||||
if data, err := getCacheValue[a](&o.Request, url); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
accessToken, err := o.getAccessToken()
|
accessToken, err := o.getAccessToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var data a
|
var data a
|
||||||
|
@ -115,5 +115,5 @@ func OauthResult[a any](o *OAuthRequest, url string, body io.Reader, requestModi
|
||||||
|
|
||||||
requestModifiers = append(requestModifiers, addAuthHeader)
|
requestModifiers = append(requestModifiers, addAuthHeader)
|
||||||
|
|
||||||
return do[a](&o.Request, url, body, requestModifiers...)
|
return Do[a](&o.Request, url, body, requestModifiers...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,8 @@ func TestOauthResult(t *testing.T) {
|
||||||
// API response
|
// API response
|
||||||
JSONResponse string
|
JSONResponse string
|
||||||
// Cache
|
// Cache
|
||||||
CacheJSONResponse string
|
|
||||||
CacheTimeout int
|
|
||||||
RefreshTokenFromCache bool
|
RefreshTokenFromCache bool
|
||||||
AccessTokenFromCache bool
|
AccessTokenFromCache bool
|
||||||
ResponseCacheMiss bool
|
|
||||||
// Errors
|
// Errors
|
||||||
Error error
|
Error error
|
||||||
// Validations
|
// Validations
|
||||||
|
@ -94,26 +91,16 @@ func TestOauthResult(t *testing.T) {
|
||||||
RefreshToken: DefaultRefreshToken,
|
RefreshToken: DefaultRefreshToken,
|
||||||
ExpectedErrorMessage: InvalidRefreshToken,
|
ExpectedErrorMessage: InvalidRefreshToken,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "Cache data",
|
|
||||||
CacheTimeout: 60,
|
|
||||||
CacheJSONResponse: jsonResponse,
|
|
||||||
ExpectedData: successData,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "Cache data, invalid data",
|
Case: "Cache data, invalid data",
|
||||||
CacheTimeout: 60,
|
|
||||||
RefreshToken: "REFRESH_TOKEN",
|
RefreshToken: "REFRESH_TOKEN",
|
||||||
CacheJSONResponse: "ERR",
|
|
||||||
TokenResponse: tokenResponse,
|
TokenResponse: tokenResponse,
|
||||||
JSONResponse: jsonResponse,
|
JSONResponse: jsonResponse,
|
||||||
ExpectedData: successData,
|
ExpectedData: successData,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Cache data, no cache",
|
Case: "Cache data, no cache",
|
||||||
CacheTimeout: 60,
|
|
||||||
RefreshToken: "REFRESH_TOKEN",
|
RefreshToken: "REFRESH_TOKEN",
|
||||||
ResponseCacheMiss: true,
|
|
||||||
TokenResponse: tokenResponse,
|
TokenResponse: tokenResponse,
|
||||||
JSONResponse: jsonResponse,
|
JSONResponse: jsonResponse,
|
||||||
ExpectedData: successData,
|
ExpectedData: successData,
|
||||||
|
@ -122,7 +109,6 @@ func TestOauthResult(t *testing.T) {
|
||||||
Case: "API body failure",
|
Case: "API body failure",
|
||||||
AccessToken: "ACCESSTOKEN",
|
AccessToken: "ACCESSTOKEN",
|
||||||
AccessTokenFromCache: true,
|
AccessTokenFromCache: true,
|
||||||
ResponseCacheMiss: true,
|
|
||||||
JSONResponse: "ERR",
|
JSONResponse: "ERR",
|
||||||
ExpectedErrorMessage: "invalid character 'E' looking for beginning of value",
|
ExpectedErrorMessage: "invalid character 'E' looking for beginning of value",
|
||||||
},
|
},
|
||||||
|
@ -130,7 +116,6 @@ func TestOauthResult(t *testing.T) {
|
||||||
Case: "API request failure",
|
Case: "API request failure",
|
||||||
AccessToken: "ACCESSTOKEN",
|
AccessToken: "ACCESSTOKEN",
|
||||||
AccessTokenFromCache: true,
|
AccessTokenFromCache: true,
|
||||||
ResponseCacheMiss: true,
|
|
||||||
JSONResponse: "ERR",
|
JSONResponse: "ERR",
|
||||||
Error: fmt.Errorf("no response"),
|
Error: fmt.Errorf("no response"),
|
||||||
ExpectedErrorMessage: "no response",
|
ExpectedErrorMessage: "no response",
|
||||||
|
@ -143,7 +128,6 @@ func TestOauthResult(t *testing.T) {
|
||||||
|
|
||||||
cache := &mock.Cache{}
|
cache := &mock.Cache{}
|
||||||
|
|
||||||
cache.On("Get", url).Return(tc.CacheJSONResponse, !tc.ResponseCacheMiss)
|
|
||||||
cache.On("Get", accessTokenKey).Return(tc.AccessToken, tc.AccessTokenFromCache)
|
cache.On("Get", accessTokenKey).Return(tc.AccessToken, tc.AccessTokenFromCache)
|
||||||
cache.On("Get", refreshTokenKey).Return(tc.RefreshToken, tc.RefreshTokenFromCache)
|
cache.On("Get", refreshTokenKey).Return(tc.RefreshToken, tc.RefreshTokenFromCache)
|
||||||
cache.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
cache.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
||||||
|
@ -163,13 +147,13 @@ func TestOauthResult(t *testing.T) {
|
||||||
RefreshToken: tc.RefreshToken,
|
RefreshToken: tc.RefreshToken,
|
||||||
Request: Request{
|
Request: Request{
|
||||||
Env: env,
|
Env: env,
|
||||||
CacheTimeout: tc.CacheTimeout,
|
|
||||||
HTTPTimeout: 20,
|
HTTPTimeout: 20,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := OauthResult[*data](oauth, url, nil)
|
got, err := OauthResult[*data](oauth, url, nil)
|
||||||
assert.Equal(t, tc.ExpectedData, got, tc.Case)
|
assert.Equal(t, tc.ExpectedData, got, tc.Case)
|
||||||
|
|
||||||
if len(tc.ExpectedErrorMessage) == 0 {
|
if len(tc.ExpectedErrorMessage) == 0 {
|
||||||
assert.Nil(t, err, tc.Case)
|
assert.Nil(t, err, tc.Case)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -14,7 +13,6 @@ type RequestModifier func(request *http.Request)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Env Environment
|
Env Environment
|
||||||
CacheTimeout int
|
|
||||||
HTTPTimeout int
|
HTTPTimeout int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,37 +21,7 @@ type Environment interface {
|
||||||
Cache() cache.Cache
|
Cache() cache.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func Do[a any](r *Request, url string, requestModifiers ...RequestModifier) (a, error) {
|
func Do[a any](r *Request, url string, body io.Reader, requestModifiers ...RequestModifier) (a, error) {
|
||||||
if data, err := getCacheValue[a](r, url); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
return do[a](r, url, nil, requestModifiers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCacheValue[a any](r *Request, key string) (a, error) {
|
|
||||||
var data a
|
|
||||||
cacheTimeout := r.CacheTimeout // r.props.GetInt(properties.CacheTimeout, 30)
|
|
||||||
if cacheTimeout <= 0 {
|
|
||||||
return data, errors.New("no cache needed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if val, found := r.Env.Cache().Get(key); found {
|
|
||||||
err := json.Unmarshal([]byte(val), &data)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
return data, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
err := errors.New("no data in cache")
|
|
||||||
log.Error(err)
|
|
||||||
|
|
||||||
return data, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func do[a any](r *Request, url string, body io.Reader, requestModifiers ...RequestModifier) (a, error) {
|
|
||||||
var data a
|
var data a
|
||||||
httpTimeout := r.HTTPTimeout // r.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := r.HTTPTimeout // r.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
|
|
||||||
|
@ -69,10 +37,5 @@ func do[a any](r *Request, url string, body io.Reader, requestModifiers ...Reque
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheTimeout := r.CacheTimeout // r.props.GetInt(properties.CacheTimeout, 30)
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
r.Env.Cache().Set(url, string(responseBody), cacheTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
testify_ "github.com/stretchr/testify/mock"
|
||||||
|
@ -35,10 +34,6 @@ func TestRequestResult(t *testing.T) {
|
||||||
Case string
|
Case string
|
||||||
// API response
|
// API response
|
||||||
JSONResponse string
|
JSONResponse string
|
||||||
// Cache
|
|
||||||
CacheJSONResponse string
|
|
||||||
CacheTimeout int
|
|
||||||
ResponseCacheMiss bool
|
|
||||||
// Errors
|
// Errors
|
||||||
Error error
|
Error error
|
||||||
// Validations
|
// Validations
|
||||||
|
@ -50,20 +45,6 @@ func TestRequestResult(t *testing.T) {
|
||||||
JSONResponse: jsonResponse,
|
JSONResponse: jsonResponse,
|
||||||
ExpectedData: successData,
|
ExpectedData: successData,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "Cache",
|
|
||||||
CacheJSONResponse: `{ "hello":"mom" }`,
|
|
||||||
ExpectedData: &data{Hello: "mom"},
|
|
||||||
CacheTimeout: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "Cache miss",
|
|
||||||
ResponseCacheMiss: true,
|
|
||||||
JSONResponse: jsonResponse,
|
|
||||||
CacheJSONResponse: `{ "hello":"mom" }`,
|
|
||||||
ExpectedData: successData,
|
|
||||||
CacheTimeout: 10,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "DNS error",
|
Case: "DNS error",
|
||||||
Error: &net.DNSError{IsNotFound: true},
|
Error: &net.DNSError{IsNotFound: true},
|
||||||
|
@ -77,19 +58,11 @@ func TestRequestResult(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
c := &mock.Cache{}
|
|
||||||
|
|
||||||
c.On("Get", url).Return(tc.CacheJSONResponse, !tc.ResponseCacheMiss)
|
|
||||||
c.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
|
|
||||||
env := &MockedEnvironment{}
|
env := &MockedEnvironment{}
|
||||||
|
|
||||||
env.On("Cache").Return(c)
|
|
||||||
env.On("HTTPRequest", url).Return([]byte(tc.JSONResponse), tc.Error)
|
env.On("HTTPRequest", url).Return([]byte(tc.JSONResponse), tc.Error)
|
||||||
|
|
||||||
request := &Request{
|
request := &Request{
|
||||||
Env: env,
|
Env: env,
|
||||||
CacheTimeout: tc.CacheTimeout,
|
|
||||||
HTTPTimeout: 0,
|
HTTPTimeout: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -589,7 +589,7 @@ func (term *Terminal) saveTemplateCache() {
|
||||||
|
|
||||||
templateCache, err := json.Marshal(tmplCache)
|
templateCache, err := json.Marshal(tmplCache)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
term.sessionCache.Set(cache.TEMPLATECACHE, string(templateCache), 1440)
|
term.sessionCache.Set(cache.TEMPLATECACHE, string(templateCache), "1day")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -769,7 +769,7 @@ func (term *Terminal) setPromptCount() {
|
||||||
// Only update the count if we're generating a primary prompt.
|
// Only update the count if we're generating a primary prompt.
|
||||||
if term.CmdFlags.Primary {
|
if term.CmdFlags.Primary {
|
||||||
count++
|
count++
|
||||||
term.Session().Set(cache.PROMPTCOUNTCACHE, strconv.Itoa(count), 1440)
|
term.Session().Set(cache.PROMPTCOUNTCACHE, strconv.Itoa(count), "1day")
|
||||||
}
|
}
|
||||||
|
|
||||||
term.CmdFlags.PromptCount = count
|
term.CmdFlags.PromptCount = count
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
"github.com/shirou/gopsutil/v3/host"
|
"github.com/shirou/gopsutil/v3/host"
|
||||||
mem "github.com/shirou/gopsutil/v3/mem"
|
mem "github.com/shirou/gopsutil/v3/mem"
|
||||||
terminal "github.com/wayneashleyberry/terminal-dimensions"
|
terminal "github.com/wayneashleyberry/terminal-dimensions"
|
||||||
|
@ -35,12 +36,15 @@ func (term *Terminal) IsWsl() bool {
|
||||||
term.Debug(val)
|
term.Debug(val)
|
||||||
return val == "true"
|
return val == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
var val bool
|
var val bool
|
||||||
defer func() {
|
defer func() {
|
||||||
term.Cache().Set(key, strconv.FormatBool(val), -1)
|
term.Cache().Set(key, strconv.FormatBool(val), cache.INFINITE)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
val = term.HasCommand("wslpath")
|
val = term.HasCommand("wslpath")
|
||||||
term.Debug(strconv.FormatBool(val))
|
term.Debug(strconv.FormatBool(val))
|
||||||
|
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,15 +96,18 @@ func (term *Terminal) Platform() string {
|
||||||
term.Debug(val)
|
term.Debug(val)
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
var platform string
|
var platform string
|
||||||
defer func() {
|
defer func() {
|
||||||
term.Cache().Set(key, platform, -1)
|
term.Cache().Set(key, platform, cache.INFINITE)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if wsl := term.Getenv("WSL_DISTRO_NAME"); len(wsl) != 0 {
|
if wsl := term.Getenv("WSL_DISTRO_NAME"); len(wsl) != 0 {
|
||||||
platform = strings.Split(strings.ToLower(wsl), "-")[0]
|
platform = strings.Split(strings.ToLower(wsl), "-")[0]
|
||||||
term.Debug(platform)
|
term.Debug(platform)
|
||||||
return platform
|
return platform
|
||||||
}
|
}
|
||||||
|
|
||||||
platform, _, _, _ = host.PlatformInformation()
|
platform, _, _, _ = host.PlatformInformation()
|
||||||
if platform == "arch" {
|
if platform == "arch" {
|
||||||
// validate for Manjaro
|
// validate for Manjaro
|
||||||
|
@ -109,6 +116,7 @@ func (term *Terminal) Platform() string {
|
||||||
platform = "manjaro"
|
platform = "manjaro"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
term.Debug(platform)
|
term.Debug(platform)
|
||||||
return platform
|
return platform
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,30 +198,6 @@ func (bf *Brewfather) getBatchStatusIcon(batchStatus string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bf *Brewfather) getResult() (*Batch, error) {
|
func (bf *Brewfather) getResult() (*Batch, error) {
|
||||||
getFromCache := func(key string) (*Batch, error) {
|
|
||||||
val, found := bf.env.Cache().Get(key)
|
|
||||||
// we got something from the cache
|
|
||||||
if found {
|
|
||||||
var result Batch
|
|
||||||
err := json.Unmarshal([]byte(val), &result)
|
|
||||||
if err == nil {
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
putToCache := func(key string, batch *Batch, cacheTimeout int) error {
|
|
||||||
cacheJSON, err := json.Marshal(batch)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
bf.env.Cache().Set(key, string(cacheJSON), cacheTimeout)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
userID := bf.props.GetString(BFUserID, "")
|
userID := bf.props.GetString(BFUserID, "")
|
||||||
if len(userID) == 0 {
|
if len(userID) == 0 {
|
||||||
return nil, errors.New("missing Brewfather user id (user_id)")
|
return nil, errors.New("missing Brewfather user id (user_id)")
|
||||||
|
@ -244,18 +220,12 @@ func (bf *Brewfather) getResult() (*Batch, error) {
|
||||||
batchReadingsURL := fmt.Sprintf("https://api.brewfather.app/v1/batches/%s/readings", batchID)
|
batchReadingsURL := fmt.Sprintf("https://api.brewfather.app/v1/batches/%s/readings", batchID)
|
||||||
|
|
||||||
httpTimeout := bf.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := bf.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
cacheTimeout := bf.props.GetInt(properties.CacheTimeout, 5)
|
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
if data, err := getFromCache(batchURL); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// batch
|
// batch
|
||||||
addAuthHeader := func(request *http.Request) {
|
addAuthHeader := func(request *http.Request) {
|
||||||
request.Header.Add("authorization", authHeader)
|
request.Header.Add("authorization", authHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := bf.env.HTTPRequest(batchURL, nil, httpTimeout, addAuthHeader)
|
body, err := bf.env.HTTPRequest(batchURL, nil, httpTimeout, addAuthHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -294,10 +264,6 @@ func (bf *Brewfather) getResult() (*Batch, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
_ = putToCache(batchURL, &batch, cacheTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &batch, nil
|
return &batch, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
@ -58,8 +57,6 @@ func TestBrewfatherSegment(t *testing.T) {
|
||||||
BatchReadingsJSONResponse string
|
BatchReadingsJSONResponse string
|
||||||
ExpectedString string
|
ExpectedString string
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
CacheTimeout int
|
|
||||||
CacheFoundFail bool
|
|
||||||
Template string
|
Template string
|
||||||
Error error
|
Error error
|
||||||
}{
|
}{
|
||||||
|
@ -148,19 +145,13 @@ func TestBrewfatherSegment(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
properties.CacheTimeout: tc.CacheTimeout,
|
|
||||||
BFBatchID: BFFakeBatchID,
|
BFBatchID: BFFakeBatchID,
|
||||||
APIKey: "FAKE",
|
APIKey: "FAKE",
|
||||||
BFUserID: "FAKE",
|
BFUserID: "FAKE",
|
||||||
}
|
}
|
||||||
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
cache.On("Get", BFCacheKey).Return(nil, false) // cache testing later because cache is a little more complicated than just the single response.
|
|
||||||
// cache.On("Set", BFCacheKey, tc.JSONResponse, tc.CacheTimeout).Return()
|
|
||||||
|
|
||||||
env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error)
|
env.On("HTTPRequest", BFBatchURL).Return([]byte(tc.BatchJSONResponse), tc.Error)
|
||||||
env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error)
|
env.On("HTTPRequest", BFBatchReadingsURL).Return([]byte(tc.BatchReadingsJSONResponse), tc.Error)
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Flags").Return(&runtime.Flags{})
|
||||||
|
|
||||||
ns := &Brewfather{
|
ns := &Brewfather{
|
||||||
|
|
|
@ -77,41 +77,19 @@ func (d *CarbonIntensity) Template() string {
|
||||||
return " CO₂ {{ .Index.Icon }}{{ .Actual.String }} {{ .TrendIcon }} {{ .Forecast.String }} "
|
return " CO₂ {{ .Index.Icon }}{{ .Actual.String }} {{ .TrendIcon }} {{ .Forecast.String }} "
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *CarbonIntensity) updateCache(responseBody []byte, url string, cacheTimeoutInMinutes int) {
|
|
||||||
if cacheTimeoutInMinutes > 0 {
|
|
||||||
d.env.Cache().Set(url, string(responseBody), cacheTimeoutInMinutes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *CarbonIntensity) getResult() (*CarbonIntensityResponse, error) {
|
func (d *CarbonIntensity) getResult() (*CarbonIntensityResponse, error) {
|
||||||
cacheTimeoutInMinutes := d.props.GetInt(properties.CacheTimeout, properties.DefaultCacheTimeout)
|
|
||||||
|
|
||||||
response := new(CarbonIntensityResponse)
|
response := new(CarbonIntensityResponse)
|
||||||
url := "https://api.carbonintensity.org.uk/intensity"
|
url := "https://api.carbonintensity.org.uk/intensity"
|
||||||
|
|
||||||
if cacheTimeoutInMinutes > 0 {
|
|
||||||
cachedValue, foundInCache := d.env.Cache().Get(url)
|
|
||||||
|
|
||||||
if foundInCache {
|
|
||||||
err := json.Unmarshal([]byte(cachedValue), response)
|
|
||||||
if err == nil {
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
// If there was an error, just fall through to refetching
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
httpTimeout := d.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := d.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
|
|
||||||
body, err := d.env.HTTPRequest(url, nil, httpTimeout)
|
body, err := d.env.HTTPRequest(url, nil, httpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.updateCache(body, url, cacheTimeoutInMinutes)
|
|
||||||
return new(CarbonIntensityResponse), err
|
return new(CarbonIntensityResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(body, &response)
|
err = json.Unmarshal(body, &response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.updateCache(body, url, cacheTimeoutInMinutes)
|
|
||||||
return new(CarbonIntensityResponse), err
|
return new(CarbonIntensityResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
@ -248,25 +247,3 @@ func TestCarbonIntensitySegmentSingle(t *testing.T) {
|
||||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, d), tc.Case)
|
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, d), tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCarbonIntensitySegmentFromCache(t *testing.T) {
|
|
||||||
response := `{ "data": [ { "from": "2023-10-27T12:30Z", "to": "2023-10-27T13:00Z", "intensity": { "forecast": 199, "actual": 193, "index": "moderate" } } ] }`
|
|
||||||
expectedString := "CO₂ •193 ↗ 199"
|
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
|
|
||||||
d := &CarbonIntensity{
|
|
||||||
props: properties.Map{},
|
|
||||||
env: env,
|
|
||||||
}
|
|
||||||
|
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
|
||||||
|
|
||||||
cache.On("Get", CARBONINTENSITYURL).Return(response, true)
|
|
||||||
cache.On("Set").Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
assert.Nil(t, d.setStatus())
|
|
||||||
assert.Equal(t, expectedString, renderTemplate(env, d.Template(), d), "should return the cached response")
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package segments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
|
@ -61,14 +60,6 @@ func (n *GitVersion) Enabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := n.env.Pwd()
|
|
||||||
version, err := n.getCacheValue(dir)
|
|
||||||
// only return on valid cache value
|
|
||||||
if err == nil && len(version.FullSemVer) != 0 {
|
|
||||||
n.gitVersion = *version
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
response, err := n.env.RunCommand(gitversion, "-output", "json")
|
response, err := n.env.RunCommand(gitversion, "-output", "json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
|
@ -76,35 +67,8 @@ func (n *GitVersion) Enabled() bool {
|
||||||
|
|
||||||
n.gitVersion = gitVersion{}
|
n.gitVersion = gitVersion{}
|
||||||
err = json.Unmarshal([]byte(response), &n.gitVersion)
|
err = json.Unmarshal([]byte(response), &n.gitVersion)
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheTimeout := n.props.GetInt(properties.CacheTimeout, 30)
|
return err == nil
|
||||||
if cacheTimeout > 0 {
|
|
||||||
n.env.Cache().Set(dir, response, cacheTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *GitVersion) getCacheValue(key string) (*gitVersion, error) {
|
|
||||||
var semVer = &gitVersion{}
|
|
||||||
cacheTimeout := n.props.GetInt(properties.CacheTimeout, 30)
|
|
||||||
|
|
||||||
if cacheTimeout <= 0 {
|
|
||||||
return semVer, errors.New("no cache needed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if val, found := n.env.Cache().Get(key); found {
|
|
||||||
err := json.Unmarshal([]byte(val), &semVer)
|
|
||||||
if err != nil {
|
|
||||||
return semVer, err
|
|
||||||
}
|
|
||||||
return semVer, nil
|
|
||||||
}
|
|
||||||
err := errors.New("no data in cache")
|
|
||||||
return semVer, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *GitVersion) Init(props properties.Properties, env runtime.Environment) {
|
func (n *GitVersion) Init(props properties.Properties, env runtime.Environment) {
|
||||||
|
|
|
@ -4,12 +4,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
"github.com/alecthomas/assert"
|
"github.com/alecthomas/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGitversion(t *testing.T) {
|
func TestGitversion(t *testing.T) {
|
||||||
|
@ -18,12 +16,9 @@ func TestGitversion(t *testing.T) {
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
ExpectedString string
|
ExpectedString string
|
||||||
Response string
|
Response string
|
||||||
CacheResponse string
|
|
||||||
CacheError error
|
|
||||||
HasGitversion bool
|
HasGitversion bool
|
||||||
Template string
|
Template string
|
||||||
CommandError error
|
CommandError error
|
||||||
CacheTimeout int
|
|
||||||
}{
|
}{
|
||||||
{Case: "GitVersion not installed"},
|
{Case: "GitVersion not installed"},
|
||||||
{Case: "GitVersion installed, no GitVersion.yml file", HasGitversion: true, Response: "Cannot find the .git directory"},
|
{Case: "GitVersion installed, no GitVersion.yml file", HasGitversion: true, Response: "Cannot find the .git directory"},
|
||||||
|
@ -35,61 +30,23 @@ func TestGitversion(t *testing.T) {
|
||||||
Response: "{ \"FullSemVer\": \"0.1.0\", \"SemVer\": \"number\" }",
|
Response: "{ \"FullSemVer\": \"0.1.0\", \"SemVer\": \"number\" }",
|
||||||
Template: "{{ .SemVer }}",
|
Template: "{{ .SemVer }}",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "Cache Version",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
ExpectedString: "number2",
|
|
||||||
HasGitversion: true,
|
|
||||||
CacheResponse: "{ \"FullSemVer\": \"0.1.2\", \"SemVer\": \"number2\" }",
|
|
||||||
Response: "{ \"FullSemVer\": \"0.1.0\", \"SemVer\": \"number\" }",
|
|
||||||
Template: "{{ .SemVer }}",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "No Cache enabled",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
CacheTimeout: -1,
|
|
||||||
ExpectedString: "number",
|
|
||||||
HasGitversion: true,
|
|
||||||
CacheResponse: "{ \"FullSemVer\": \"0.1.2\", \"SemVer\": \"number2\" }",
|
|
||||||
Response: "{ \"FullSemVer\": \"0.1.0\", \"SemVer\": \"number\" }",
|
|
||||||
Template: "{{ .SemVer }}",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "Command Error",
|
Case: "Command Error",
|
||||||
HasGitversion: true,
|
HasGitversion: true,
|
||||||
CommandError: errors.New("error"),
|
CommandError: errors.New("error"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "Bad cache",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
ExpectedString: "number",
|
|
||||||
HasGitversion: true,
|
|
||||||
CacheResponse: "{{",
|
|
||||||
Response: "{ \"FullSemVer\": \"0.1.0\", \"SemVer\": \"number\" }",
|
|
||||||
Template: "{{ .SemVer }}",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(mock.Environment)
|
env := new(mock.Environment)
|
||||||
cache := &cache_.Cache{}
|
|
||||||
|
|
||||||
env.On("HasCommand", "gitversion").Return(tc.HasGitversion)
|
env.On("HasCommand", "gitversion").Return(tc.HasGitversion)
|
||||||
env.On("Pwd").Return("test-dir")
|
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", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
|
|
||||||
env.On("RunCommand", "gitversion", []string{"-output", "json"}).Return(tc.Response, tc.CommandError)
|
env.On("RunCommand", "gitversion", []string{"-output", "json"}).Return(tc.Response, tc.CommandError)
|
||||||
|
|
||||||
if tc.CacheTimeout == 0 {
|
|
||||||
tc.CacheTimeout = 30
|
|
||||||
}
|
|
||||||
gitversion := &GitVersion{
|
gitversion := &GitVersion{
|
||||||
env: env,
|
env: env,
|
||||||
props: properties.Map{
|
props: properties.Map{},
|
||||||
properties.CacheTimeout: tc.CacheTimeout,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if len(tc.Template) == 0 {
|
if len(tc.Template) == 0 {
|
||||||
tc.Template = gitversion.Template()
|
tc.Template = gitversion.Template()
|
||||||
|
|
|
@ -22,7 +22,7 @@ type ipAPI struct {
|
||||||
|
|
||||||
func (i *ipAPI) Get() (*ipData, error) {
|
func (i *ipAPI) Get() (*ipData, error) {
|
||||||
url := "https://api.ipify.org?format=json"
|
url := "https://api.ipify.org?format=json"
|
||||||
return http.Do[*ipData](&i.Request, url)
|
return http.Do[*ipData](&i.Request, url, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPify struct {
|
type IPify struct {
|
||||||
|
@ -65,7 +65,6 @@ func (i *IPify) getResult() (string, error) {
|
||||||
func (i *IPify) Init(props properties.Properties, env runtime.Environment) {
|
func (i *IPify) Init(props properties.Properties, env runtime.Environment) {
|
||||||
request := &http.Request{
|
request := &http.Request{
|
||||||
Env: env,
|
Env: env,
|
||||||
CacheTimeout: props.GetInt(properties.CacheTimeout, 30),
|
|
||||||
HTTPTimeout: props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
HTTPTimeout: props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package segments
|
package segments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
|
@ -52,44 +50,7 @@ func (k *Kubectl) Init(props properties.Properties, env runtime.Environment) {
|
||||||
k.env = env
|
k.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubectl) setCacheValue(timeout int) {
|
|
||||||
if !k.dirty {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cachedData, _ := json.Marshal(k)
|
|
||||||
k.env.Cache().Set(kubectlCacheKey, string(cachedData), timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Kubectl) restoreCacheValue() error {
|
|
||||||
if val, found := k.env.Cache().Get(kubectlCacheKey); found {
|
|
||||||
err := json.Unmarshal([]byte(val), k)
|
|
||||||
if err != nil {
|
|
||||||
k.env.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Kubectl) Enabled() bool {
|
func (k *Kubectl) Enabled() bool {
|
||||||
cacheTimeout := k.props.GetInt(properties.CacheTimeout, 0)
|
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
if err := k.restoreCacheValue(); err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
k.setCacheValue(cacheTimeout)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
parseKubeConfig := k.props.GetBool(ParseKubeConfig, true)
|
parseKubeConfig := k.props.GetBool(ParseKubeConfig, true)
|
||||||
|
|
||||||
if parseKubeConfig {
|
if parseKubeConfig {
|
||||||
|
|
|
@ -197,23 +197,11 @@ func (l *language) hasLanguageFolders() bool {
|
||||||
// setVersion parses the version string returned by the command
|
// setVersion parses the version string returned by the command
|
||||||
func (l *language) setVersion() error {
|
func (l *language) setVersion() error {
|
||||||
var lastError error
|
var lastError error
|
||||||
cacheVersion := l.props.GetBool(CacheVersion, false)
|
|
||||||
|
|
||||||
for _, command := range l.commands {
|
for _, command := range l.commands {
|
||||||
var versionStr string
|
var versionStr string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
versionKey := fmt.Sprintf("%s_version", command.executable)
|
|
||||||
versionURL := fmt.Sprintf("%s_version_url", command.executable)
|
|
||||||
|
|
||||||
if versionStr, OK := l.env.Cache().Get(versionKey); OK {
|
|
||||||
version, _ := command.parse(versionStr)
|
|
||||||
l.version = *version
|
|
||||||
l.version.Executable = command.executable
|
|
||||||
l.version.URL, _ = l.env.Cache().Get(versionURL)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if command.getVersion == nil {
|
if command.getVersion == nil {
|
||||||
if !l.env.HasCommand(command.executable) {
|
if !l.env.HasCommand(command.executable) {
|
||||||
lastError = errors.New(noVersion)
|
lastError = errors.New(noVersion)
|
||||||
|
@ -248,12 +236,6 @@ func (l *language) setVersion() error {
|
||||||
l.buildVersionURL()
|
l.buildVersionURL()
|
||||||
l.version.Executable = command.executable
|
l.version.Executable = command.executable
|
||||||
|
|
||||||
if cacheVersion {
|
|
||||||
timeout := l.props.GetInt(properties.CacheTimeout, 1440)
|
|
||||||
l.env.Cache().Set(versionKey, versionStr, timeout)
|
|
||||||
l.env.Cache().Set(versionURL, l.version.URL, timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
@ -30,7 +29,6 @@ type languageArgs struct {
|
||||||
properties properties.Properties
|
properties properties.Properties
|
||||||
matchesVersionFile matchesVersionFile
|
matchesVersionFile matchesVersionFile
|
||||||
inHome bool
|
inHome bool
|
||||||
cachedVersion string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *languageArgs) hasvalue(value string, list []string) bool {
|
func (l *languageArgs) hasvalue(value string, list []string) bool {
|
||||||
|
@ -69,11 +67,6 @@ func bootStrapLanguageTest(args *languageArgs) *language {
|
||||||
Env: make(map[string]string),
|
Env: make(map[string]string),
|
||||||
})
|
})
|
||||||
|
|
||||||
c := &cache_.Cache{}
|
|
||||||
c.On("Get", testify_.Anything).Return(args.cachedVersion, len(args.cachedVersion) > 0)
|
|
||||||
c.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
env.On("Cache").Return(c)
|
|
||||||
|
|
||||||
if args.properties == nil {
|
if args.properties == nil {
|
||||||
args.properties = properties.Map{}
|
args.properties = properties.Map{}
|
||||||
}
|
}
|
||||||
|
@ -542,31 +535,6 @@ func TestLanguageHyperlinkTemplatePropertyTakesPriority(t *testing.T) {
|
||||||
assert.Equal(t, "https://custom/url/template/1.3", lang.version.URL)
|
assert.Equal(t, "https://custom/url/template/1.3", lang.version.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLanguageEnabledCachedVersion(t *testing.T) {
|
|
||||||
props := properties.Map{
|
|
||||||
properties.FetchVersion: true,
|
|
||||||
}
|
|
||||||
args := &languageArgs{
|
|
||||||
commands: []*cmd{
|
|
||||||
{
|
|
||||||
executable: "unicorn",
|
|
||||||
args: []string{"--version"},
|
|
||||||
regex: "(?P<version>.*)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extensions: []string{uni, corn},
|
|
||||||
enabledExtensions: []string{uni, corn},
|
|
||||||
enabledCommands: []string{"unicorn"},
|
|
||||||
version: universion,
|
|
||||||
cachedVersion: "1.3.37",
|
|
||||||
properties: props,
|
|
||||||
}
|
|
||||||
lang := bootStrapLanguageTest(args)
|
|
||||||
assert.True(t, lang.Enabled())
|
|
||||||
assert.Equal(t, "1.3.37", lang.Full, "cached unicorn version is available")
|
|
||||||
assert.Equal(t, "unicorn", lang.Executable, "cached version was found")
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockedLanguageParams struct {
|
type mockedLanguageParams struct {
|
||||||
cmd string
|
cmd string
|
||||||
versionParam string
|
versionParam string
|
||||||
|
@ -586,14 +554,10 @@ func getMockedLanguageEnv(params *mockedLanguageParams) (*mock.Environment, prop
|
||||||
})
|
})
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Flags").Return(&runtime.Flags{})
|
||||||
|
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
properties.FetchVersion: true,
|
properties.FetchVersion: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &cache_.Cache{}
|
|
||||||
c.On("Get", testify_.Anything).Return("", false)
|
|
||||||
c.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
env.On("Cache").Return(c)
|
|
||||||
|
|
||||||
return env, props
|
return env, props
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,6 @@ func (d *LastFM) Template() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LastFM) getResult() (*lfmDataResponse, error) {
|
func (d *LastFM) getResult() (*lfmDataResponse, error) {
|
||||||
cacheTimeout := d.props.GetInt(properties.CacheTimeout, 0)
|
|
||||||
response := new(lfmDataResponse)
|
response := new(lfmDataResponse)
|
||||||
|
|
||||||
apikey := d.props.GetString(APIKey, ".")
|
apikey := d.props.GetString(APIKey, ".")
|
||||||
|
@ -77,30 +76,16 @@ func (d *LastFM) getResult() (*lfmDataResponse, error) {
|
||||||
|
|
||||||
url := fmt.Sprintf("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&api_key=%s&user=%s&format=json&limit=1", apikey, username)
|
url := fmt.Sprintf("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&api_key=%s&user=%s&format=json&limit=1", apikey, username)
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
val, found := d.env.Cache().Get(url)
|
|
||||||
|
|
||||||
if found {
|
|
||||||
err := json.Unmarshal([]byte(val), response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := d.env.HTTPRequest(url, nil, httpTimeout)
|
body, err := d.env.HTTPRequest(url, nil, httpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return new(lfmDataResponse), err
|
return new(lfmDataResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(body, &response)
|
err = json.Unmarshal(body, &response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return new(lfmDataResponse), err
|
return new(lfmDataResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
d.env.Cache().Set(url, string(body), cacheTimeout)
|
|
||||||
}
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
|
@ -82,25 +81,3 @@ func TestLFMSegmentSingle(t *testing.T) {
|
||||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, o), tc.Case)
|
assert.Equal(t, tc.ExpectedString, renderTemplate(env, tc.Template, o), tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLFMSegmentFromCache(t *testing.T) {
|
|
||||||
response := `{"recenttracks":{"track":[{"artist":{"mbid":"","#text":"C.Gambino"},"streamable":"0","name":"Automatic","date":{"uts":"1699350223","#text":"07 Nov 2023, 09:43"}}]}}`
|
|
||||||
expectedString := "\uF04D"
|
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
o := &LastFM{
|
|
||||||
props: properties.Map{
|
|
||||||
APIKey: "key",
|
|
||||||
Username: "KibbeWater",
|
|
||||||
properties.CacheTimeout: 1,
|
|
||||||
},
|
|
||||||
env: env,
|
|
||||||
}
|
|
||||||
cache.On("Get", LFMAPIURL).Return(response, true)
|
|
||||||
cache.On("Set").Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
assert.Nil(t, o.setStatus())
|
|
||||||
assert.Equal(t, expectedString, renderTemplate(env, o.Template(), o), "should return the cached response")
|
|
||||||
}
|
|
||||||
|
|
|
@ -152,25 +152,6 @@ func (nba *Nba) Enabled() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an empty Game Data struct with the GameStatus set to NotFound
|
|
||||||
// Helpful for caching the fact that a game was not found for a team
|
|
||||||
func (nba *Nba) getGameNotFoundData() string {
|
|
||||||
return `{
|
|
||||||
"HomeTeam":"",
|
|
||||||
"AwayTeam":"",
|
|
||||||
"Time":"",
|
|
||||||
"GameDate":"",
|
|
||||||
"StartTimeUTC":"",
|
|
||||||
"GameStatus":4,
|
|
||||||
"HomeScore":0,
|
|
||||||
"AwayScore":0,
|
|
||||||
"HomeTeamWins":0,
|
|
||||||
"HomeTeamLosses":0,
|
|
||||||
"AwayTeamWins":0,
|
|
||||||
"AwayTeamLosses":0
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parses through a set of games from the score endpoint and looks for props.team in away or home team
|
// parses through a set of games from the score endpoint and looks for props.team in away or home team
|
||||||
func (nba *Nba) findGameScoreByTeamTricode(games []Game, teamTricode string) (*Game, error) {
|
func (nba *Nba) findGameScoreByTeamTricode(games []Game, teamTricode string) (*Game, error) {
|
||||||
for _, game := range games {
|
for _, game := range games {
|
||||||
|
@ -308,86 +289,15 @@ func (nba *Nba) getAvailableGameData(teamName string, httpTimeout int) (*NBAData
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the data from the cache if it exists
|
|
||||||
func (nba *Nba) getCacheValue(key string) (*NBAData, error) {
|
|
||||||
if val, found := nba.env.Cache().Get(key); found {
|
|
||||||
var nbaData *NBAData
|
|
||||||
err := json.Unmarshal([]byte(val), &nbaData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return nbaData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the data from the cache for a scheduled game if it exists
|
|
||||||
// Checks whether the game should have started and if so, removes the cache entry
|
|
||||||
func (nba *Nba) getCachedScheduleValue(key string) (*NBAData, error) {
|
|
||||||
data, err := nba.getCacheValue(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the game was previously not found and we should wait to check again
|
|
||||||
if data.GameStatus == NotFound {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the current time is after the start time of the game
|
|
||||||
// if so, we need to refresh the data
|
|
||||||
startTime, err := time.Parse("2006-01-02T15:04:05Z", data.StartTimeUTC)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Now().UTC().After(startTime) {
|
|
||||||
// remove the cache entry
|
|
||||||
nba.env.Cache().Delete(key)
|
|
||||||
return nil, errors.New("game has already started")
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nba *Nba) getResult() (*NBAData, error) {
|
func (nba *Nba) getResult() (*NBAData, error) {
|
||||||
teamName := nba.props.GetString(TeamName, "")
|
teamName := nba.props.GetString(TeamName, "")
|
||||||
|
|
||||||
cachedScheduleKey := fmt.Sprintf("%s%s", teamName, "schedule")
|
|
||||||
cachedScoreKey := fmt.Sprintf("%s%s", teamName, "score")
|
|
||||||
|
|
||||||
httpTimeout := nba.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := nba.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
|
|
||||||
// How often you want to query the API to get live score information, defaults to 2 minutes
|
|
||||||
cacheScoreTimeout := nba.props.GetInt(properties.CacheTimeout, 2)
|
|
||||||
|
|
||||||
// Cache the schedule information for a day so we don't call the API too often
|
|
||||||
cacheScheduleTimeout := nba.props.GetInt(properties.CacheTimeout, 1440)
|
|
||||||
|
|
||||||
// Cache the fact a game was not found for 30 minutes so we don't call the API too often
|
|
||||||
cacheNotFoundTimeout := nba.props.GetInt(properties.CacheTimeout, 30)
|
|
||||||
|
|
||||||
nba.env.Debug("validating cache data for " + teamName)
|
|
||||||
|
|
||||||
if cacheScheduleTimeout > 0 {
|
|
||||||
if data, err := nba.getCachedScheduleValue(cachedScheduleKey); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cacheScoreTimeout > 0 {
|
|
||||||
if data, err := nba.getCacheValue(cachedScoreKey); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nba.env.Debug("fetching available data for " + teamName)
|
nba.env.Debug("fetching available data for " + teamName)
|
||||||
|
|
||||||
data, err := nba.getAvailableGameData(teamName, httpTimeout)
|
data, err := nba.getAvailableGameData(teamName, httpTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// cache the fact that we didn't find a game yet for the day for 30m so we don't continuously ping the endpoints
|
|
||||||
nba.env.Cache().Set(cachedScheduleKey, nba.getGameNotFoundData(), cacheNotFoundTimeout)
|
|
||||||
nba.env.Error(errors.Join(err, fmt.Errorf("unable to get data for team %s", teamName)))
|
nba.env.Error(errors.Join(err, fmt.Errorf("unable to get data for team %s", teamName)))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -398,19 +308,6 @@ func (nba *Nba) getResult() (*NBAData, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheScheduleTimeout > 0 && data.GameStatus == Scheduled {
|
|
||||||
// persist data for team in cache
|
|
||||||
cachedData, _ := json.Marshal(data)
|
|
||||||
nba.env.Cache().Set(cachedScheduleKey, string(cachedData), cacheScheduleTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the game is in progress or finished, we can cache the score
|
|
||||||
if cacheScoreTimeout > 0 && data.GameStatus == InProgress || data.GameStatus == Finished {
|
|
||||||
// persist data for team in cache
|
|
||||||
cachedData, _ := json.Marshal(data)
|
|
||||||
nba.env.Cache().Set(cachedScoreKey, string(cachedData), cacheScoreTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
|
@ -29,8 +28,6 @@ func TestNBASegment(t *testing.T) {
|
||||||
JSONResponse string
|
JSONResponse string
|
||||||
ExpectedString string
|
ExpectedString string
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
CacheTimeout int
|
|
||||||
CacheFoundFail bool
|
|
||||||
TeamName string
|
TeamName string
|
||||||
DaysOffset int
|
DaysOffset int
|
||||||
Error error
|
Error error
|
||||||
|
@ -77,7 +74,6 @@ func TestNBASegment(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
properties.CacheTimeout: tc.CacheTimeout,
|
|
||||||
TeamName: tc.TeamName,
|
TeamName: tc.TeamName,
|
||||||
DaysOffset: tc.DaysOffset,
|
DaysOffset: tc.DaysOffset,
|
||||||
}
|
}
|
||||||
|
@ -101,16 +97,6 @@ func TestNBASegment(t *testing.T) {
|
||||||
env: env,
|
env: env,
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedScheduleKey := fmt.Sprintf("%s%s", tc.TeamName, "schedule")
|
|
||||||
cachedScoreKey := fmt.Sprintf("%s%s", tc.TeamName, "score")
|
|
||||||
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
cache.On("Get", cachedScheduleKey).Return(nba.getGameNotFoundData(), tc.CacheFoundFail)
|
|
||||||
cache.On("Get", cachedScoreKey).Return(nba.getGameNotFoundData(), tc.CacheFoundFail)
|
|
||||||
cache.On("Set", cachedScheduleKey, nba.getGameNotFoundData(), tc.CacheTimeout).Return()
|
|
||||||
cache.On("Set", cachedScoreKey, nba.getGameNotFoundData(), tc.CacheTimeout).Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
enabled := nba.Enabled()
|
enabled := nba.Enabled()
|
||||||
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
|
assert.Equal(t, tc.ExpectedEnabled, enabled, tc.Case)
|
||||||
if !enabled {
|
if !enabled {
|
||||||
|
|
|
@ -96,27 +96,9 @@ func (ns *Nightscout) getResult() (*NightscoutData, error) {
|
||||||
}
|
}
|
||||||
return result[0], nil
|
return result[0], nil
|
||||||
}
|
}
|
||||||
getCacheValue := func(key string) (*NightscoutData, error) {
|
|
||||||
val, found := ns.env.Cache().Get(key)
|
|
||||||
// we got something from the cache
|
|
||||||
if found {
|
|
||||||
if data, err := parseSingleElement([]byte(val)); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
url := ns.props.GetString(URL, "")
|
url := ns.props.GetString(URL, "")
|
||||||
httpTimeout := ns.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := ns.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
// natural and understood NS timeout is 5, anything else is unusual
|
|
||||||
cacheTimeout := ns.props.GetInt(properties.CacheTimeout, 5)
|
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
if data, err := getCacheValue(url); err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
headers := ns.props.GetKeyValueMap(Headers, map[string]string{})
|
headers := ns.props.GetKeyValueMap(Headers, map[string]string{})
|
||||||
modifiers := func(request *http2.Request) {
|
modifiers := func(request *http2.Request) {
|
||||||
|
@ -129,6 +111,7 @@ func (ns *Nightscout) getResult() (*NightscoutData, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var arr []*NightscoutData
|
var arr []*NightscoutData
|
||||||
err = json.Unmarshal(body, &arr)
|
err = json.Unmarshal(body, &arr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -140,10 +123,6 @@ func (ns *Nightscout) getResult() (*NightscoutData, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
// persist new sugars in cache
|
|
||||||
ns.env.Cache().Set(url, string(body), cacheTimeout)
|
|
||||||
}
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
|
@ -21,8 +20,6 @@ func TestNSSegment(t *testing.T) {
|
||||||
JSONResponse string
|
JSONResponse string
|
||||||
ExpectedString string
|
ExpectedString string
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
CacheTimeout int
|
|
||||||
CacheFoundFail bool
|
|
||||||
Template string
|
Template string
|
||||||
Error error
|
Error error
|
||||||
}{
|
}{
|
||||||
|
@ -93,25 +90,6 @@ func TestNSSegment(t *testing.T) {
|
||||||
JSONResponse: "[]",
|
JSONResponse: "[]",
|
||||||
ExpectedEnabled: false,
|
ExpectedEnabled: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "DoubleDown 50 from cache",
|
|
||||||
JSONResponse: `
|
|
||||||
[{"_id":"619d6fa819696e8ded5b2206","sgv":50,"date":1637707537000,"dateString":"2021-11-23T22:45:37.000Z","trend":4,"direction":"DoubleDown","device":"share2","type":"sgv","utcOffset":0,"sysTime":"2021-11-23T22:45:37.000Z","mills":1637707537000}]`, //nolint:lll
|
|
||||||
Template: "\ue2a1 {{.Sgv}}{{.TrendIcon}}",
|
|
||||||
ExpectedString: "\ue2a1 50↓↓",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
CacheTimeout: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "DoubleDown 50 from cache not found",
|
|
||||||
JSONResponse: `
|
|
||||||
[{"_id":"619d6fa819696e8ded5b2206","sgv":50,"date":1637707537000,"dateString":"2021-11-23T22:45:37.000Z","trend":4,"direction":"DoubleDown","device":"share2","type":"sgv","utcOffset":0,"sysTime":"2021-11-23T22:45:37.000Z","mills":1637707537000}]`, //nolint:lll
|
|
||||||
Template: "\ue2a1 {{.Sgv}}{{.TrendIcon}}",
|
|
||||||
ExpectedString: "\ue2a1 50↓↓",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
CacheTimeout: 10,
|
|
||||||
CacheFoundFail: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "Error parsing response",
|
Case: "Error parsing response",
|
||||||
JSONResponse: `
|
JSONResponse: `
|
||||||
|
@ -119,7 +97,6 @@ func TestNSSegment(t *testing.T) {
|
||||||
Template: "\ue2a1 {{.Sgv}}{{.TrendIcon}}",
|
Template: "\ue2a1 {{.Sgv}}{{.TrendIcon}}",
|
||||||
ExpectedString: "\ue2a1 50↓↓",
|
ExpectedString: "\ue2a1 50↓↓",
|
||||||
ExpectedEnabled: false,
|
ExpectedEnabled: false,
|
||||||
CacheTimeout: 10,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "Faulty template",
|
Case: "Faulty template",
|
||||||
|
@ -128,24 +105,17 @@ func TestNSSegment(t *testing.T) {
|
||||||
Template: "\ue2a1 {{.Sgv}}{{.Burp}}",
|
Template: "\ue2a1 {{.Sgv}}{{.Burp}}",
|
||||||
ExpectedString: "<.Data.Burp>: can't evaluate field Burp in type template.Data",
|
ExpectedString: "<.Data.Burp>: can't evaluate field Burp in type template.Data",
|
||||||
ExpectedEnabled: true,
|
ExpectedEnabled: true,
|
||||||
CacheTimeout: 10,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := &mock.Environment{}
|
env := &mock.Environment{}
|
||||||
props := properties.Map{
|
props := properties.Map{
|
||||||
properties.CacheTimeout: tc.CacheTimeout,
|
|
||||||
URL: "FAKE",
|
URL: "FAKE",
|
||||||
Headers: map[string]string{"Fake-Header": "xxxxx"},
|
Headers: map[string]string{"Fake-Header": "xxxxx"},
|
||||||
}
|
}
|
||||||
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
cache.On("Get", FAKEAPIURL).Return(tc.JSONResponse, !tc.CacheFoundFail)
|
|
||||||
cache.On("Set", FAKEAPIURL, tc.JSONResponse, tc.CacheTimeout).Return()
|
|
||||||
|
|
||||||
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
|
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(tc.JSONResponse), tc.Error)
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
ns := &Nightscout{
|
ns := &Nightscout{
|
||||||
props: props,
|
props: props,
|
||||||
|
|
|
@ -67,29 +67,14 @@ func (d *Owm) Template() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Owm) getResult() (*owmDataResponse, error) {
|
func (d *Owm) getResult() (*owmDataResponse, error) {
|
||||||
cacheTimeout := d.props.GetInt(properties.CacheTimeout, properties.DefaultCacheTimeout)
|
|
||||||
response := new(owmDataResponse)
|
response := new(owmDataResponse)
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
val, found := d.env.Cache().Get(CacheKeyResponse)
|
|
||||||
if found {
|
|
||||||
err := json.Unmarshal([]byte(val), response)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d.URL, _ = d.env.Cache().Get(CacheKeyURL)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apikey := properties.OneOf(d.props, ".", APIKey, "apiKey")
|
apikey := properties.OneOf(d.props, ".", APIKey, "apiKey")
|
||||||
if len(apikey) == 0 {
|
if len(apikey) == 0 {
|
||||||
apikey = d.env.Getenv(PoshOWMAPIKey)
|
apikey = d.env.Getenv(PoshOWMAPIKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
location := d.props.GetString(Location, "De Bilt,NL")
|
location := d.props.GetString(Location, "De Bilt,NL")
|
||||||
|
|
||||||
location = url.QueryEscape(location)
|
location = url.QueryEscape(location)
|
||||||
|
|
||||||
if len(apikey) == 0 || len(location) == 0 {
|
if len(apikey) == 0 || len(location) == 0 {
|
||||||
|
@ -105,16 +90,12 @@ func (d *Owm) getResult() (*owmDataResponse, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return new(owmDataResponse), err
|
return new(owmDataResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(body, &response)
|
err = json.Unmarshal(body, &response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return new(owmDataResponse), err
|
return new(owmDataResponse), err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
// persist new forecasts in cache
|
|
||||||
d.env.Cache().Set(CacheKeyResponse, string(body), cacheTimeout)
|
|
||||||
d.env.Cache().Set(CacheKeyURL, d.URL, cacheTimeout)
|
|
||||||
}
|
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
|
||||||
|
@ -251,50 +250,3 @@ func TestOWMSegmentIcons(t *testing.T) {
|
||||||
assert.Equal(t, expectedString, renderTemplate(env, "«{{.Weather}} ({{.Temperature}}{{.UnitIcon}})»({{.URL}})", o), tc.Case)
|
assert.Equal(t, expectedString, renderTemplate(env, "«{{.Weather}} ({{.Temperature}}{{.UnitIcon}})»({{.URL}})", o), tc.Case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOWMSegmentFromCacheByGeoName(t *testing.T) {
|
|
||||||
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, "01d")
|
|
||||||
expectedString := fmt.Sprintf("%s (20°C)", "\ue30d")
|
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
o := &Owm{
|
|
||||||
props: properties.Map{
|
|
||||||
APIKey: "key",
|
|
||||||
Location: "AMSTERDAM,NL",
|
|
||||||
Units: "metric",
|
|
||||||
},
|
|
||||||
env: env,
|
|
||||||
}
|
|
||||||
cache.On("Get", "owm_response").Return(response, true)
|
|
||||||
cache.On("Get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true)
|
|
||||||
cache.On("Set").Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
assert.Nil(t, o.setStatus())
|
|
||||||
assert.Equal(t, expectedString, renderTemplate(env, o.Template(), o), "should return the cached response")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOWMSegmentFromCacheWithHyperlinkByGeoName(t *testing.T) {
|
|
||||||
response := fmt.Sprintf(`{"weather":[{"icon":"%s"}],"main":{"temp":20}}`, "01d")
|
|
||||||
expectedString := fmt.Sprintf("«%s (20°C)»(http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key)", "\ue30d")
|
|
||||||
|
|
||||||
env := &mock.Environment{}
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
|
|
||||||
o := &Owm{
|
|
||||||
props: properties.Map{
|
|
||||||
APIKey: "key",
|
|
||||||
Location: "AMSTERDAM,NL",
|
|
||||||
Units: "metric",
|
|
||||||
},
|
|
||||||
env: env,
|
|
||||||
}
|
|
||||||
cache.On("Get", "owm_response").Return(response, true)
|
|
||||||
cache.On("Get", "owm_url").Return("http://api.openweathermap.org/data/2.5/weather?q=AMSTERDAM,NL&units=metric&appid=key", true)
|
|
||||||
cache.On("Set").Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
assert.Nil(t, o.setStatus())
|
|
||||||
assert.Equal(t, expectedString, renderTemplate(env, "«{{.Weather}} ({{.Temperature}}{{.UnitIcon}})»({{.URL}})", o))
|
|
||||||
}
|
|
||||||
|
|
|
@ -165,31 +165,6 @@ func (p *Pulumi) getPulumiAbout() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheKey := "pulumi-" + p.Name + "-" + p.Stack + "-" + p.workspaceSHA1 + "-about"
|
|
||||||
|
|
||||||
getAboutCache := func(key string) (*backend, error) {
|
|
||||||
aboutBackend, OK := p.env.Cache().Get(key)
|
|
||||||
if (!OK || len(aboutBackend) == 0) || (OK && len(aboutBackend) == 0) {
|
|
||||||
return nil, fmt.Errorf("no data in cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
var backend *backend
|
|
||||||
err := json.Unmarshal([]byte(aboutBackend), &backend)
|
|
||||||
if err != nil {
|
|
||||||
p.env.DebugF("unable to decode about cache: %s", aboutBackend)
|
|
||||||
p.env.Error(fmt.Errorf("pulling about cache decode error"))
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
aboutBackend, err := getAboutCache(cacheKey)
|
|
||||||
if err == nil {
|
|
||||||
p.backend = *aboutBackend
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
aboutOutput, err := p.env.RunCommand("pulumi", "about", "--json")
|
aboutOutput, err := p.env.RunCommand("pulumi", "about", "--json")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -213,8 +188,4 @@ func (p *Pulumi) getPulumiAbout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.backend = *about.Backend
|
p.backend = *about.Backend
|
||||||
|
|
||||||
cacheTimeout := p.props.GetInt(properties.CacheTimeout, 43800)
|
|
||||||
jso, _ := json.Marshal(about.Backend)
|
|
||||||
p.env.Cache().Set(cacheKey, string(jso), cacheTimeout)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -95,18 +94,6 @@ description: A Console App
|
||||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
WorkSpaceFile: `{ "stack": "1337" }`,
|
||||||
About: `{ "backend": { "url": "s3://test-pulumi-state-test", "user":"posh-user" } }`,
|
About: `{ "backend": { "url": "s3://test-pulumi-state-test", "user":"posh-user" } }`,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "pulumi URL - cache",
|
|
||||||
ExpectedString: "\U000f0d46 1337 :: posh-user@s3://test-pulumi-state-test",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
HasCommand: true,
|
|
||||||
HasWorkspaceFolder: true,
|
|
||||||
FetchStack: true,
|
|
||||||
FetchAbout: true,
|
|
||||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
|
||||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
|
||||||
AboutCache: `{ "url": "s3://test-pulumi-state-test", "user":"posh-user" }`,
|
|
||||||
},
|
|
||||||
// Error flows
|
// Error flows
|
||||||
{
|
{
|
||||||
Case: "pulumi file JSON error",
|
Case: "pulumi file JSON error",
|
||||||
|
@ -134,19 +121,6 @@ description: A Console App
|
||||||
FetchAbout: true,
|
FetchAbout: true,
|
||||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
JSONConfig: `{ "name": "oh-my-posh" }`,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "pulumi URL - cache error",
|
|
||||||
ExpectedString: "\U000f0d46 1337 :: posh-user@s3://test-pulumi-state-test-output",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
HasCommand: true,
|
|
||||||
HasWorkspaceFolder: true,
|
|
||||||
FetchStack: true,
|
|
||||||
FetchAbout: true,
|
|
||||||
JSONConfig: `{ "name": "oh-my-posh" }`,
|
|
||||||
WorkSpaceFile: `{ "stack": "1337" }`,
|
|
||||||
AboutCache: `{`,
|
|
||||||
About: `{ "backend": { "url": "s3://test-pulumi-state-test-output", "user":"posh-user" } }`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "pulumi URL - about error",
|
Case: "pulumi URL - about error",
|
||||||
ExpectedString: "\U000f0d46 1337",
|
ExpectedString: "\U000f0d46 1337",
|
||||||
|
@ -211,12 +185,6 @@ description: A Console App
|
||||||
env.On("HasFilesInDir", filepath.Clean("/home/foobar/.pulumi/workspaces"), workspaceFile).Return(len(tc.WorkSpaceFile) > 0)
|
env.On("HasFilesInDir", filepath.Clean("/home/foobar/.pulumi/workspaces"), workspaceFile).Return(len(tc.WorkSpaceFile) > 0)
|
||||||
env.On("FileContent", filepath.Clean("/home/foobar/.pulumi/workspaces/"+workspaceFile)).Return(tc.WorkSpaceFile, nil)
|
env.On("FileContent", filepath.Clean("/home/foobar/.pulumi/workspaces/"+workspaceFile)).Return(tc.WorkSpaceFile, nil)
|
||||||
|
|
||||||
cache := &cache_.Cache{}
|
|
||||||
cache.On("Get", "pulumi-oh-my-posh-1337-c62b7b6786c5c5a85896576e46a25d7c9f888e92-about").Return(tc.AboutCache, len(tc.AboutCache) > 0)
|
|
||||||
cache.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
pulumi := &Pulumi{
|
pulumi := &Pulumi{
|
||||||
env: env,
|
env: env,
|
||||||
props: properties.Map{
|
props: properties.Map{
|
||||||
|
|
|
@ -2,20 +2,9 @@
|
||||||
|
|
||||||
package segments
|
package segments
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
|
||||||
)
|
|
||||||
|
|
||||||
const spotifyCacheKey = "spotify_music_player"
|
const spotifyCacheKey = "spotify_music_player"
|
||||||
|
|
||||||
func (s *Spotify) Enabled() bool {
|
func (s *Spotify) Enabled() bool {
|
||||||
cacheTimeout := s.props.GetInt(properties.CacheTimeout, 0)
|
|
||||||
if cacheTimeout > 0 && s.getFromCache() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if running
|
// Check if running
|
||||||
running := s.runAppleScriptCommand("application \"Spotify\" is running")
|
running := s.runAppleScriptCommand("application \"Spotify\" is running")
|
||||||
if running == "false" || running == "" {
|
if running == "false" || running == "" {
|
||||||
|
@ -39,10 +28,6 @@ func (s *Spotify) Enabled() bool {
|
||||||
|
|
||||||
s.resolveIcon()
|
s.resolveIcon()
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
s.setCache(cacheTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,28 +35,3 @@ func (s *Spotify) runAppleScriptCommand(command string) string {
|
||||||
val, _ := s.env.RunCommand("osascript", "-e", command)
|
val, _ := s.env.RunCommand("osascript", "-e", command)
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Spotify) getFromCache() bool {
|
|
||||||
str, found := s.env.Cache().Get(spotifyCacheKey)
|
|
||||||
if !found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var cachedMusicPlayer MusicPlayer
|
|
||||||
err := json.Unmarshal([]byte(str), &cachedMusicPlayer)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
s.MusicPlayer = cachedMusicPlayer
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Spotify) setCache(cacheTimeout int) {
|
|
||||||
cache, err := json.Marshal(s.MusicPlayer)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.env.Cache().Set(spotifyCacheKey, string(cache), cacheTimeout)
|
|
||||||
}
|
|
||||||
|
|
|
@ -137,7 +137,6 @@ func (s *Strava) Init(props properties.Properties, env runtime.Environment) {
|
||||||
RefreshToken: s.props.GetString(properties.RefreshToken, ""),
|
RefreshToken: s.props.GetString(properties.RefreshToken, ""),
|
||||||
Request: http.Request{
|
Request: http.Request{
|
||||||
Env: env,
|
Env: env,
|
||||||
CacheTimeout: s.props.GetInt(properties.CacheTimeout, 30),
|
|
||||||
HTTPTimeout: s.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
HTTPTimeout: s.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,10 +117,6 @@ func (u *Unity) GetCSharpVersion() (version string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Unity) GetCSharpVersionFromWeb(shortUnityVersion string) (version string, err error) {
|
func (u *Unity) GetCSharpVersionFromWeb(shortUnityVersion string) (version string, err error) {
|
||||||
if csharpVersion, found := u.env.Cache().Get(shortUnityVersion); found {
|
|
||||||
return csharpVersion, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
url := fmt.Sprintf("https://docs.unity3d.com/%s/Documentation/Manual/CSharpCompiler.html", shortUnityVersion)
|
url := fmt.Sprintf("https://docs.unity3d.com/%s/Documentation/Manual/CSharpCompiler.html", shortUnityVersion)
|
||||||
httpTimeout := u.props.GetInt(properties.HTTPTimeout, 2000)
|
httpTimeout := u.props.GetInt(properties.HTTPTimeout, 2000)
|
||||||
|
|
||||||
|
@ -135,11 +131,9 @@ func (u *Unity) GetCSharpVersionFromWeb(shortUnityVersion string) (version strin
|
||||||
matches := regex.FindNamedRegexMatch(pattern, pageContent)
|
matches := regex.FindNamedRegexMatch(pattern, pageContent)
|
||||||
if matches != nil && matches["csharpVersion"] != "" {
|
if matches != nil && matches["csharpVersion"] != "" {
|
||||||
csharpVersion := strings.TrimSuffix(matches["csharpVersion"], ".0")
|
csharpVersion := strings.TrimSuffix(matches["csharpVersion"], ".0")
|
||||||
u.env.Cache().Set(shortUnityVersion, csharpVersion, -1)
|
|
||||||
return csharpVersion, nil
|
return csharpVersion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
u.env.Cache().Set(shortUnityVersion, "", -1)
|
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,11 @@ package segments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
testify_ "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
@ -16,17 +14,6 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CacheGet struct {
|
|
||||||
key string
|
|
||||||
val string
|
|
||||||
found bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type CacheSet struct {
|
|
||||||
key string
|
|
||||||
val string
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPResponse struct {
|
type HTTPResponse struct {
|
||||||
body string
|
body string
|
||||||
err error
|
err error
|
||||||
|
@ -119,39 +106,16 @@ func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||||
Case string
|
Case string
|
||||||
ExpectedOutput string
|
ExpectedOutput string
|
||||||
VersionFileText string
|
VersionFileText string
|
||||||
CacheGet CacheGet
|
|
||||||
CacheSet CacheSet
|
|
||||||
ExpectedToBeEnabled bool
|
ExpectedToBeEnabled bool
|
||||||
VersionFileExists bool
|
VersionFileExists bool
|
||||||
HTTPResponse HTTPResponse
|
HTTPResponse HTTPResponse
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Case: "C# version cached",
|
Case: "C# version",
|
||||||
ExpectedOutput: "\ue721 2021.9.20 C# 10",
|
ExpectedOutput: "\ue721 2021.9.20 C# 10",
|
||||||
ExpectedToBeEnabled: true,
|
ExpectedToBeEnabled: true,
|
||||||
VersionFileExists: true,
|
VersionFileExists: true,
|
||||||
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
||||||
CacheGet: CacheGet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "C# 10",
|
|
||||||
found: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Case: "C# version not cached",
|
|
||||||
ExpectedOutput: "\ue721 2021.9.20 C# 10",
|
|
||||||
ExpectedToBeEnabled: true,
|
|
||||||
VersionFileExists: true,
|
|
||||||
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
|
||||||
CacheGet: CacheGet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "",
|
|
||||||
found: false,
|
|
||||||
},
|
|
||||||
CacheSet: CacheSet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "C# 10",
|
|
||||||
},
|
|
||||||
HTTPResponse: HTTPResponse{
|
HTTPResponse: HTTPResponse{
|
||||||
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10">C# 10.0</a>`,
|
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10">C# 10.0</a>`,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -163,15 +127,6 @@ func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||||
ExpectedToBeEnabled: true,
|
ExpectedToBeEnabled: true,
|
||||||
VersionFileExists: true,
|
VersionFileExists: true,
|
||||||
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
||||||
CacheGet: CacheGet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "",
|
|
||||||
found: false,
|
|
||||||
},
|
|
||||||
CacheSet: CacheSet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "C# 10.1",
|
|
||||||
},
|
|
||||||
HTTPResponse: HTTPResponse{
|
HTTPResponse: HTTPResponse{
|
||||||
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10-1">C# 10.1</a>`,
|
body: `<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10-1">C# 10.1</a>`,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -183,15 +138,6 @@ func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||||
ExpectedToBeEnabled: true,
|
ExpectedToBeEnabled: true,
|
||||||
VersionFileExists: true,
|
VersionFileExists: true,
|
||||||
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
||||||
CacheGet: CacheGet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "",
|
|
||||||
found: false,
|
|
||||||
},
|
|
||||||
CacheSet: CacheSet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "",
|
|
||||||
},
|
|
||||||
HTTPResponse: HTTPResponse{
|
HTTPResponse: HTTPResponse{
|
||||||
body: `<h1>Sorry... that page seems to be missing!</h1>`,
|
body: `<h1>Sorry... that page seems to be missing!</h1>`,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -203,11 +149,6 @@ func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||||
ExpectedToBeEnabled: true,
|
ExpectedToBeEnabled: true,
|
||||||
VersionFileExists: true,
|
VersionFileExists: true,
|
||||||
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
VersionFileText: "m_EditorVersion: 2021.9.20f1\nm_EditorVersionWithRevision: 2021.9.20f1 (4016570cf34f)",
|
||||||
CacheGet: CacheGet{
|
|
||||||
key: "2021.9",
|
|
||||||
val: "",
|
|
||||||
found: false,
|
|
||||||
},
|
|
||||||
HTTPResponse: HTTPResponse{
|
HTTPResponse: HTTPResponse{
|
||||||
body: "",
|
body: "",
|
||||||
err: errors.New("FAIL"),
|
err: errors.New("FAIL"),
|
||||||
|
@ -235,12 +176,7 @@ func TestUnitySegmentCSharpWebRequest(t *testing.T) {
|
||||||
}
|
}
|
||||||
env.On("HasParentFilePath", "ProjectSettings", false).Return(projectDir, err)
|
env.On("HasParentFilePath", "ProjectSettings", false).Return(projectDir, err)
|
||||||
|
|
||||||
cache := &cache_.Cache{}
|
url := "https://docs.unity3d.com/2021.9/Documentation/Manual/CSharpCompiler.html"
|
||||||
cache.On("Get", tc.CacheGet.key).Return(tc.CacheGet.val, tc.CacheGet.found)
|
|
||||||
cache.On("Set", tc.CacheSet.key, tc.CacheSet.val, -1).Return()
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
|
|
||||||
url := fmt.Sprintf("https://docs.unity3d.com/%s/Documentation/Manual/CSharpCompiler.html", tc.CacheGet.key)
|
|
||||||
env.On("HTTPRequest", url).Return([]byte(tc.HTTPResponse.body), tc.HTTPResponse.err)
|
env.On("HTTPRequest", url).Return([]byte(tc.HTTPResponse.body), tc.HTTPResponse.err)
|
||||||
|
|
||||||
props := properties.Map{}
|
props := properties.Map{}
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package segments
|
package segments
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/build"
|
"github.com/jandedobbeleer/oh-my-posh/src/build"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
|
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UpgradeCache struct {
|
type upgradeData struct {
|
||||||
Latest string `json:"latest"`
|
Latest string `json:"latest"`
|
||||||
Current string `json:"current"`
|
Current string `json:"current"`
|
||||||
}
|
}
|
||||||
|
@ -22,11 +19,9 @@ type Upgrade struct {
|
||||||
// deprecated
|
// deprecated
|
||||||
Version string
|
Version string
|
||||||
|
|
||||||
UpgradeCache
|
upgradeData
|
||||||
}
|
}
|
||||||
|
|
||||||
const UPGRADECACHEKEY = "upgrade_segment"
|
|
||||||
|
|
||||||
func (u *Upgrade) Template() string {
|
func (u *Upgrade) Template() string {
|
||||||
return " \uf019 "
|
return " \uf019 "
|
||||||
}
|
}
|
||||||
|
@ -38,59 +33,27 @@ func (u *Upgrade) Init(props properties.Properties, env runtime.Environment) {
|
||||||
|
|
||||||
func (u *Upgrade) Enabled() bool {
|
func (u *Upgrade) Enabled() bool {
|
||||||
u.Current = build.Version
|
u.Current = build.Version
|
||||||
latest, err := u.cachedLatest(u.Current)
|
|
||||||
if err != nil {
|
latest, err := u.checkUpdate(u.Current)
|
||||||
latest, err = u.checkUpdate(u.Current)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil || u.Current == latest.Latest {
|
if err != nil || u.Current == latest.Latest {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
u.UpgradeCache = *latest
|
u.upgradeData = *latest
|
||||||
u.Version = u.Latest
|
u.Version = u.Latest
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Upgrade) cachedLatest(current string) (*UpgradeCache, error) {
|
func (u *Upgrade) checkUpdate(current string) (*upgradeData, error) {
|
||||||
data, ok := u.env.Cache().Get(UPGRADECACHEKEY)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("no cache data")
|
|
||||||
}
|
|
||||||
|
|
||||||
var cacheJSON UpgradeCache
|
|
||||||
err := json.Unmarshal([]byte(data), &cacheJSON)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err // invalid cache data
|
|
||||||
}
|
|
||||||
|
|
||||||
if current != cacheJSON.Current {
|
|
||||||
return nil, errors.New("version changed, run the check again")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cacheJSON, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Upgrade) checkUpdate(current string) (*UpgradeCache, error) {
|
|
||||||
tag, err := upgrade.Latest(u.env)
|
tag, err := upgrade.Latest(u.env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
latest := tag[1:]
|
return &upgradeData{
|
||||||
cacheData := &UpgradeCache{
|
// strip leading v
|
||||||
Latest: latest,
|
Latest: tag[1:],
|
||||||
Current: current,
|
Current: current,
|
||||||
}
|
}, nil
|
||||||
cacheJSON, err := json.Marshal(cacheData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
oneWeek := 10080
|
|
||||||
cacheTimeout := u.props.GetInt(properties.CacheTimeout, oneWeek)
|
|
||||||
// update cache
|
|
||||||
u.env.Cache().Set(UPGRADECACHEKEY, string(cacheJSON), cacheTimeout)
|
|
||||||
|
|
||||||
return cacheData, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,19 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/build"
|
"github.com/jandedobbeleer/oh-my-posh/src/build"
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
|
"github.com/jandedobbeleer/oh-my-posh/src/upgrade"
|
||||||
|
|
||||||
"github.com/alecthomas/assert"
|
"github.com/alecthomas/assert"
|
||||||
testify_ "github.com/stretchr/testify/mock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUpgrade(t *testing.T) {
|
func TestUpgrade(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
Case string
|
Case string
|
||||||
ExpectedEnabled bool
|
ExpectedEnabled bool
|
||||||
HasCache bool
|
|
||||||
CurrentVersion string
|
CurrentVersion string
|
||||||
LatestVersion string
|
LatestVersion string
|
||||||
CachedVersion string
|
|
||||||
Error error
|
Error error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -40,42 +36,21 @@ func TestUpgrade(t *testing.T) {
|
||||||
Case: "Error on update check",
|
Case: "Error on update check",
|
||||||
Error: errors.New("error"),
|
Error: errors.New("error"),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "On previous, from cache",
|
|
||||||
HasCache: true,
|
|
||||||
CurrentVersion: "1.0.2",
|
|
||||||
LatestVersion: "1.0.3",
|
|
||||||
CachedVersion: "1.0.2",
|
|
||||||
ExpectedEnabled: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "On latest, version changed",
|
Case: "On latest, version changed",
|
||||||
HasCache: true,
|
|
||||||
CurrentVersion: "1.0.2",
|
CurrentVersion: "1.0.2",
|
||||||
LatestVersion: "1.0.2",
|
LatestVersion: "1.0.2",
|
||||||
CachedVersion: "1.0.1",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "On previous, version changed",
|
Case: "On previous, version changed",
|
||||||
HasCache: true,
|
|
||||||
CurrentVersion: "1.0.2",
|
CurrentVersion: "1.0.2",
|
||||||
LatestVersion: "1.0.3",
|
LatestVersion: "1.0.3",
|
||||||
CachedVersion: "1.0.1",
|
|
||||||
ExpectedEnabled: true,
|
ExpectedEnabled: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
env := new(mock.Environment)
|
env := new(mock.Environment)
|
||||||
cache := &cache_.Cache{}
|
|
||||||
|
|
||||||
env.On("Cache").Return(cache)
|
|
||||||
if len(tc.CachedVersion) == 0 {
|
|
||||||
tc.CachedVersion = tc.CurrentVersion
|
|
||||||
}
|
|
||||||
cacheData := fmt.Sprintf(`{"latest":"%s", "current": "%s"}`, tc.LatestVersion, tc.CachedVersion)
|
|
||||||
cache.On("Get", UPGRADECACHEKEY).Return(cacheData, tc.HasCache)
|
|
||||||
cache.On("Set", testify_.Anything, testify_.Anything, testify_.Anything)
|
|
||||||
|
|
||||||
build.Version = tc.CurrentVersion
|
build.Version = tc.CurrentVersion
|
||||||
|
|
||||||
|
|
|
@ -40,17 +40,6 @@ func (w *Wakatime) setAPIData() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cacheTimeout := w.props.GetInt(properties.CacheTimeout, properties.DefaultCacheTimeout)
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
// check if data stored in cache
|
|
||||||
if val, found := w.env.Cache().Get(url); found {
|
|
||||||
err := json.Unmarshal([]byte(val), &w.wtData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
httpTimeout := w.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
httpTimeout := w.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout)
|
||||||
|
|
||||||
|
@ -58,14 +47,12 @@ func (w *Wakatime) setAPIData() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(body, &w.wtData)
|
err = json.Unmarshal(body, &w.wtData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cacheTimeout > 0 {
|
|
||||||
w.env.Cache().Set(url, string(body), cacheTimeout)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
"github.com/jandedobbeleer/oh-my-posh/src/cache"
|
||||||
cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock"
|
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
"github.com/jandedobbeleer/oh-my-posh/src/runtime/mock"
|
||||||
|
@ -21,8 +20,6 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
Seconds int
|
Seconds int
|
||||||
Expected string
|
Expected string
|
||||||
Template string
|
Template string
|
||||||
CacheTimeout int
|
|
||||||
CacheFoundFail bool
|
|
||||||
Error error
|
Error error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
@ -50,25 +47,15 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
Seconds: -9900,
|
Seconds: -9900,
|
||||||
Expected: "2h 45m",
|
Expected: "2h 45m",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Case: "cache 2h 45m",
|
|
||||||
Seconds: 9900,
|
|
||||||
Expected: "2h 45m",
|
|
||||||
CacheTimeout: 20,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Case: "no cache 2h 45m",
|
Case: "no cache 2h 45m",
|
||||||
Seconds: 9900,
|
Seconds: 9900,
|
||||||
Expected: "2h 45m",
|
Expected: "2h 45m",
|
||||||
CacheTimeout: 20,
|
|
||||||
CacheFoundFail: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Case: "api error",
|
Case: "api error",
|
||||||
Seconds: 2,
|
Seconds: 2,
|
||||||
Expected: "0s",
|
Expected: "0s",
|
||||||
CacheTimeout: 20,
|
|
||||||
CacheFoundFail: true,
|
|
||||||
Error: errors.New("api error"),
|
Error: errors.New("api error"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -79,10 +66,6 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
|
|
||||||
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(response), tc.Error)
|
env.On("HTTPRequest", FAKEAPIURL).Return([]byte(response), tc.Error)
|
||||||
|
|
||||||
mockedCache := &cache_.Cache{}
|
|
||||||
mockedCache.On("Get", FAKEAPIURL).Return(response, !tc.CacheFoundFail)
|
|
||||||
mockedCache.On("Set", FAKEAPIURL, response, tc.CacheTimeout).Return()
|
|
||||||
env.On("Cache").Return(mockedCache)
|
|
||||||
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
env.On("DebugF", testify_.Anything, testify_.Anything).Return(nil)
|
||||||
env.On("Flags").Return(&runtime.Flags{})
|
env.On("Flags").Return(&runtime.Flags{})
|
||||||
|
|
||||||
|
@ -92,7 +75,6 @@ func TestWTTrackedTime(t *testing.T) {
|
||||||
|
|
||||||
w := &Wakatime{
|
w := &Wakatime{
|
||||||
props: properties.Map{
|
props: properties.Map{
|
||||||
properties.CacheTimeout: tc.CacheTimeout,
|
|
||||||
URL: FAKEAPIURL,
|
URL: FAKEAPIURL,
|
||||||
},
|
},
|
||||||
env: env,
|
env: env,
|
||||||
|
|
|
@ -234,7 +234,6 @@ func (w *Withings) Init(props properties.Properties, env runtime.Environment) {
|
||||||
RefreshToken: w.props.GetString(properties.RefreshToken, ""),
|
RefreshToken: w.props.GetString(properties.RefreshToken, ""),
|
||||||
Request: http.Request{
|
Request: http.Request{
|
||||||
Env: env,
|
Env: env,
|
||||||
CacheTimeout: w.props.GetInt(properties.CacheTimeout, 30),
|
|
||||||
HTTPTimeout: w.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
HTTPTimeout: w.props.GetInt(properties.HTTPTimeout, properties.DefaultHTTPTimeout),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,8 +83,7 @@ func Notice(env runtime.Environment, force bool) (string, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
oneWeek := 10080
|
env.Cache().Set(CACHEKEY, latest, "1week")
|
||||||
env.Cache().Set(CACHEKEY, latest, oneWeek)
|
|
||||||
|
|
||||||
version := fmt.Sprintf("v%s", build.Version)
|
version := fmt.Sprintf("v%s", build.Version)
|
||||||
if latest == version {
|
if latest == version {
|
||||||
|
|
Loading…
Reference in a new issue