mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-21 02:55:37 -08:00
fix(shell): lock template cache correctly
This commit is contained in:
parent
3cdb3bfc1d
commit
dee040c719
|
@ -25,13 +25,13 @@ func (c *cacheObject) expired() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileCache struct {
|
type fileCache struct {
|
||||||
cache *concurrentMap
|
cache *ConcurrentMap
|
||||||
cachePath string
|
cachePath string
|
||||||
dirty bool
|
dirty bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *fileCache) Init(cachePath string) {
|
func (fc *fileCache) Init(cachePath string) {
|
||||||
fc.cache = newConcurrentMap()
|
fc.cache = NewConcurrentMap()
|
||||||
fc.cachePath = cachePath
|
fc.cachePath = cachePath
|
||||||
cacheFilePath := filepath.Join(fc.cachePath, CacheFile)
|
cacheFilePath := filepath.Join(fc.cachePath, CacheFile)
|
||||||
content, err := os.ReadFile(cacheFilePath)
|
content, err := os.ReadFile(cacheFilePath)
|
||||||
|
@ -48,7 +48,7 @@ func (fc *fileCache) Init(cachePath string) {
|
||||||
if co.expired() {
|
if co.expired() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fc.cache.set(key, co)
|
fc.cache.Set(key, co)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ func (fc *fileCache) Close() {
|
||||||
if !fc.dirty {
|
if !fc.dirty {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache := fc.cache.list()
|
cache := fc.cache.List()
|
||||||
if dump, err := json.MarshalIndent(cache, "", " "); err == nil {
|
if dump, err := json.MarshalIndent(cache, "", " "); err == nil {
|
||||||
cacheFilePath := filepath.Join(fc.cachePath, CacheFile)
|
cacheFilePath := filepath.Join(fc.cachePath, CacheFile)
|
||||||
_ = os.WriteFile(cacheFilePath, dump, 0644)
|
_ = os.WriteFile(cacheFilePath, dump, 0644)
|
||||||
|
@ -66,7 +66,7 @@ func (fc *fileCache) 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 TTL (minutes) is not expired
|
||||||
func (fc *fileCache) Get(key string) (string, bool) {
|
func (fc *fileCache) Get(key string) (string, bool) {
|
||||||
val, found := fc.cache.get(key)
|
val, found := fc.cache.Get(key)
|
||||||
if !found {
|
if !found {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func (fc *fileCache) Get(key string) (string, bool) {
|
||||||
|
|
||||||
// sets the value for the given key with a TTL (minutes)
|
// sets the value for the given key with a TTL (minutes)
|
||||||
func (fc *fileCache) Set(key, value string, ttl int) {
|
func (fc *fileCache) Set(key, value string, ttl int) {
|
||||||
fc.cache.set(key, &cacheObject{
|
fc.cache.Set(key, &cacheObject{
|
||||||
Value: value,
|
Value: value,
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
TTL: ttl,
|
TTL: ttl,
|
||||||
|
|
|
@ -1,30 +1,33 @@
|
||||||
package platform
|
package platform
|
||||||
|
|
||||||
type concurrentMap struct {
|
import "sync"
|
||||||
|
|
||||||
|
type ConcurrentMap struct {
|
||||||
values map[string]interface{}
|
values map[string]interface{}
|
||||||
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func newConcurrentMap() *concurrentMap {
|
func NewConcurrentMap() *ConcurrentMap {
|
||||||
return &concurrentMap{
|
return &ConcurrentMap{
|
||||||
values: make(map[string]interface{}),
|
values: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentMap) set(key string, value interface{}) {
|
func (c *ConcurrentMap) Set(key string, value interface{}) {
|
||||||
lock.Lock()
|
c.Lock()
|
||||||
defer lock.Unlock()
|
defer c.Unlock()
|
||||||
c.values[key] = value
|
c.values[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentMap) get(key string) (interface{}, bool) {
|
func (c *ConcurrentMap) Get(key string) (interface{}, bool) {
|
||||||
lock.RLock()
|
c.RLock()
|
||||||
defer lock.RUnlock()
|
defer c.RUnlock()
|
||||||
if val, ok := c.values[key]; ok {
|
if val, ok := c.values[key]; ok {
|
||||||
return val, true
|
return val, true
|
||||||
}
|
}
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *concurrentMap) list() map[string]interface{} {
|
func (c *ConcurrentMap) List() map[string]interface{} {
|
||||||
return c.values
|
return c.values
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@ func getPID() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lock = sync.RWMutex{}
|
|
||||||
TEMPLATECACHE = fmt.Sprintf("template_cache_%s", getPID())
|
TEMPLATECACHE = fmt.Sprintf("template_cache_%s", getPID())
|
||||||
TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", getPID())
|
TOGGLECACHE = fmt.Sprintf("toggle_cache_%s", getPID())
|
||||||
)
|
)
|
||||||
|
@ -131,8 +130,8 @@ type Connection struct {
|
||||||
|
|
||||||
type SegmentsCache map[string]interface{}
|
type SegmentsCache map[string]interface{}
|
||||||
|
|
||||||
func (c *SegmentsCache) Contains(key string) bool {
|
func (s *SegmentsCache) Contains(key string) bool {
|
||||||
_, ok := (*c)[key]
|
_, ok := (*s)[key]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,15 +148,14 @@ type TemplateCache struct {
|
||||||
OS string
|
OS string
|
||||||
WSL bool
|
WSL bool
|
||||||
Segments SegmentsCache
|
Segments SegmentsCache
|
||||||
|
|
||||||
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TemplateCache) AddSegmentData(key string, value interface{}) {
|
func (t *TemplateCache) AddSegmentData(key string, value interface{}) {
|
||||||
lock.Lock()
|
t.Lock()
|
||||||
defer lock.Unlock()
|
|
||||||
if t.Segments == nil {
|
|
||||||
t.Segments = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
t.Segments[key] = value
|
t.Segments[key] = value
|
||||||
|
t.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Environment interface {
|
type Environment interface {
|
||||||
|
@ -212,15 +210,15 @@ type Environment interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandCache struct {
|
type commandCache struct {
|
||||||
commands *concurrentMap
|
commands *ConcurrentMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandCache) set(command, path string) {
|
func (c *commandCache) set(command, path string) {
|
||||||
c.commands.set(command, path)
|
c.commands.Set(command, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *commandCache) get(command string) (string, bool) {
|
func (c *commandCache) get(command string) (string, bool) {
|
||||||
cacheCommand, found := c.commands.get(command)
|
cacheCommand, found := c.commands.Get(command)
|
||||||
if !found {
|
if !found {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
@ -237,6 +235,8 @@ type Shell struct {
|
||||||
fileCache *fileCache
|
fileCache *fileCache
|
||||||
tmplCache *TemplateCache
|
tmplCache *TemplateCache
|
||||||
networks []*Connection
|
networks []*Connection
|
||||||
|
|
||||||
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *Shell) Init() {
|
func (env *Shell) Init() {
|
||||||
|
@ -251,7 +251,7 @@ func (env *Shell) Init() {
|
||||||
env.fileCache.Init(env.CachePath())
|
env.fileCache.Init(env.CachePath())
|
||||||
env.resolveConfigPath()
|
env.resolveConfigPath()
|
||||||
env.cmdCache = &commandCache{
|
env.cmdCache = &commandCache{
|
||||||
commands: newConcurrentMap(),
|
commands: NewConcurrentMap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,9 +331,7 @@ func (env *Shell) Getenv(key string) string {
|
||||||
|
|
||||||
func (env *Shell) Pwd() string {
|
func (env *Shell) Pwd() string {
|
||||||
defer env.Trace(time.Now(), "Pwd")
|
defer env.Trace(time.Now(), "Pwd")
|
||||||
lock.Lock()
|
|
||||||
defer func() {
|
defer func() {
|
||||||
lock.Unlock()
|
|
||||||
env.Debug("Pwd", env.cwd)
|
env.Debug("Pwd", env.cwd)
|
||||||
}()
|
}()
|
||||||
if env.cwd != "" {
|
if env.cwd != "" {
|
||||||
|
@ -708,7 +706,11 @@ func (env *Shell) Logs() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *Shell) TemplateCache() *TemplateCache {
|
func (env *Shell) TemplateCache() *TemplateCache {
|
||||||
defer env.Trace(time.Now(), "TemplateCache")
|
env.Lock()
|
||||||
|
defer func() {
|
||||||
|
env.Trace(time.Now(), "TemplateCache")
|
||||||
|
env.Unlock()
|
||||||
|
}()
|
||||||
if env.tmplCache != nil {
|
if env.tmplCache != nil {
|
||||||
return env.tmplCache
|
return env.tmplCache
|
||||||
}
|
}
|
||||||
|
@ -718,6 +720,7 @@ func (env *Shell) TemplateCache() *TemplateCache {
|
||||||
ShellVersion: env.CmdFlags.ShellVersion,
|
ShellVersion: env.CmdFlags.ShellVersion,
|
||||||
Code: env.ErrorCode(),
|
Code: env.ErrorCode(),
|
||||||
WSL: env.IsWsl(),
|
WSL: env.IsWsl(),
|
||||||
|
Segments: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
tmplCache.Env = make(map[string]string)
|
tmplCache.Env = make(map[string]string)
|
||||||
const separator = "="
|
const separator = "="
|
||||||
|
@ -751,8 +754,6 @@ func (env *Shell) TemplateCache() *TemplateCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (env *Shell) DirMatchesOneOf(dir string, regexes []string) (match bool) {
|
func (env *Shell) DirMatchesOneOf(dir string, regexes []string) (match bool) {
|
||||||
lock.Lock()
|
|
||||||
defer lock.Unlock()
|
|
||||||
// sometimes the function panics inside golang, we want to silence that error
|
// sometimes the function panics inside golang, we want to silence that error
|
||||||
// and assume that there's no match. Not perfect, but better than crashing
|
// and assume that there's no match. Not perfect, but better than crashing
|
||||||
// for the time being until we figure out what the actual root cause is
|
// for the time being until we figure out what the actual root cause is
|
||||||
|
|
Loading…
Reference in a new issue