From b830ae662a71cba6f0dd4e6b480d93b79029e2d1 Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Thu, 11 Feb 2021 13:19:47 +0100 Subject: [PATCH] revert: use concurrent map for command caching This reverts commit 509309c412ee643000febe4bced1280c6f0fb885. resolves #394 --- src/environment.go | 51 +++++++++++++++++++++++++++---------- src/go.mod | 1 - src/go.sum | 8 ------ src/main.go | 5 ++-- src/segment_command_test.go | 8 ++++++ src/segment_git_test.go | 15 ----------- 6 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/environment.go b/src/environment.go index 7037864d..cad34f47 100644 --- a/src/environment.go +++ b/src/environment.go @@ -10,12 +10,12 @@ import ( "path/filepath" "runtime" "strings" + "sync" "time" "github.com/distatus/battery" "github.com/shirou/gopsutil/host" "github.com/shirou/gopsutil/process" - "github.com/xaionaro-go/atomicmap" ) const ( @@ -65,14 +65,41 @@ type environmentInfo interface { hasParentFilePath(path string) (fileInfo *fileInfo, err error) } -type environment struct { - args *args - cwd string +type commandCache struct { + commands map[string]string + lock sync.Mutex } -var ( - commands atomicmap.Map = atomicmap.New() -) +func (c *commandCache) set(command, path string) { + c.lock.Lock() + defer c.lock.Unlock() + c.commands[command] = path +} + +func (c *commandCache) get(command string) (string, bool) { + c.lock.Lock() + defer c.lock.Unlock() + if cmd, ok := c.commands[command]; ok { + command = cmd + return command, true + } + return "", false +} + +type environment struct { + args *args + cwd string + cmdCache *commandCache +} + +func (env *environment) init(args *args) { + env.args = args + cmdCache := &commandCache{ + commands: make(map[string]string), + lock: sync.Mutex{}, + } + env.cmdCache = cmdCache +} func (env *environment) getenv(key string) string { return os.Getenv(key) @@ -164,8 +191,8 @@ func (env *environment) getPlatform() string { } func (env *environment) runCommand(command string, args ...string) (string, error) { - if cmd, err := commands.Get(command); err == nil { - command = cmd.(string) + if cmd, ok := env.cmdCache.get(command); ok { + command = cmd } out, err := exec.Command(command, args...).Output() if err != nil { @@ -185,14 +212,12 @@ func (env *environment) runShellCommand(shell, command string) string { } func (env *environment) hasCommand(command string) bool { - if _, err := commands.Get(command); err == nil { + if _, ok := env.cmdCache.get(command); ok { return true } path, err := exec.LookPath(command) if err == nil { - // the error implies we failed to cache the path - // ignoring it only affects the path caching, not the functionality - _ = commands.Set(command, path) + env.cmdCache.set(command, path) return true } return false diff --git a/src/go.mod b/src/go.mod index eab54af7..eea959a1 100644 --- a/src/go.mod +++ b/src/go.mod @@ -15,7 +15,6 @@ require ( github.com/shirou/gopsutil v2.20.9+incompatible github.com/stretchr/objx v0.3.0 // indirect github.com/stretchr/testify v1.6.1 - github.com/xaionaro-go/atomicmap v0.0.0-20200307233044-c040bc137895 golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 golang.org/x/text v0.3.3 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect diff --git a/src/go.sum b/src/go.sum index a63f35f5..7b02d059 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,8 +2,6 @@ github.com/JanDeDobbeleer/battery v0.10.0-1 h1:3N3i3xgvrrb3eCuX4kJnmbKzOiqkH1Ly1 github.com/JanDeDobbeleer/battery v0.10.0-1/go.mod h1:STnSvFLX//eEpkaN7qWRxCWxrWOcssTDgnG4yqq9BRE= github.com/JanDeDobbeleer/color v1.3.5-1 h1:joTGC9ShPgXUVWJW4sBv4q9M2rdpTopCysc8fRRAgkY= github.com/JanDeDobbeleer/color v1.3.5-1/go.mod h1:GqqLKF1le3EfrbHbYsYa5WdLqfc/PHMdMRbt6tMnqIc= -github.com/OneOfOne/xxhash v1.2.7 h1:fzrmmkskv067ZQbd9wERNGuxckWw67dyzoMG62p7LMo= -github.com/OneOfOne/xxhash v1.2.7/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= @@ -12,11 +10,9 @@ github.com/alecthomas/colour v0.1.0 h1:nOE9rJm6dsZ66RGWYSFrXw461ZIt9A6+nHgL7FRrD github.com/alecthomas/colour v0.1.0/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/repr v0.0.0-20201103221029-55c485bd663f h1:jXPaiovuWmnCXfJ8UYiiLtI/LAJPnaZnoV+LfIDEJRc= github.com/alecthomas/repr v0.0.0-20201103221029-55c485bd663f/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= -github.com/cornelk/hashmap v1.0.1/go.mod h1:8wbysTUDnwJGrPZ1Iwsou3m+An6sldFrJItjRhfegCw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dchest/siphash v1.1.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -40,10 +36,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/xaionaro-go/atomicmap v0.0.0-20200307233044-c040bc137895 h1:PFzS0ykP4VVJmqv94Khyp6U5QavIdcrQZw9E13G+Go8= -github.com/xaionaro-go/atomicmap v0.0.0-20200307233044-c040bc137895/go.mod h1:WgfDl7x9++CVnKSu63ThFhBF3nvgj60Ft1nCgrOSgWM= -github.com/xaionaro-go/spinlock v0.0.0-20190309154744-55278e21e817 h1:0ikx4JlTx9uNiHGGC4o0k93GhcWOtONYdhk2H8RUnZU= -github.com/xaionaro-go/spinlock v0.0.0-20190309154744-55278e21e817/go.mod h1:Nb/15eS0BMty6TMuWgRQM8WCDIUlyPZagcpchHT6c9Y= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= diff --git a/src/main.go b/src/main.go index 58728e6e..f09f4897 100644 --- a/src/main.go +++ b/src/main.go @@ -100,9 +100,8 @@ func main() { "Print the shell initialization script"), } flag.Parse() - env := &environment{ - args: args, - } + env := &environment{} + env.init(args) if *args.Millis { fmt.Print(time.Now().UnixNano() / 1000000) return diff --git a/src/segment_command_test.go b/src/segment_command_test.go index 09c2bf11..fd5f3a62 100644 --- a/src/segment_command_test.go +++ b/src/segment_command_test.go @@ -8,6 +8,7 @@ import ( func TestExecuteCommand(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "echo hello", @@ -24,6 +25,7 @@ func TestExecuteCommand(t *testing.T) { func TestExecuteMultipleCommandsOrFirst(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "exit 1 || echo hello", @@ -40,6 +42,7 @@ func TestExecuteMultipleCommandsOrFirst(t *testing.T) { func TestExecuteMultipleCommandsOrSecond(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "echo hello || echo world", @@ -56,6 +59,7 @@ func TestExecuteMultipleCommandsOrSecond(t *testing.T) { func TestExecuteMultipleCommandsAnd(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "echo hello && echo world", @@ -72,6 +76,7 @@ func TestExecuteMultipleCommandsAnd(t *testing.T) { func TestExecuteSingleCommandEmpty(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "", @@ -87,6 +92,7 @@ func TestExecuteSingleCommandEmpty(t *testing.T) { func TestExecuteSingleCommandNoCommandProperty(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{} c := &command{ props: props, @@ -99,6 +105,7 @@ func TestExecuteSingleCommandNoCommandProperty(t *testing.T) { func TestExecuteMultipleCommandsAndDisabled(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "echo && echo", @@ -114,6 +121,7 @@ func TestExecuteMultipleCommandsAndDisabled(t *testing.T) { func TestExecuteMultipleCommandsOrDisabled(t *testing.T) { env := &environment{} + env.init(nil) props := &properties{ values: map[Property]interface{}{ Command: "echo|| echo", diff --git a/src/segment_git_test.go b/src/segment_git_test.go index 7c952098..4c6662c3 100644 --- a/src/segment_git_test.go +++ b/src/segment_git_test.go @@ -701,18 +701,3 @@ func TestGetStatusDetailStringNoStatusColorOverride(t *testing.T) { } assert.Equal(t, expected, g.getStatusDetailString(status, WorkingColor, LocalWorkingIcon, "icon")) } - -func TestGitOutPut(t *testing.T) { - g := &git{ - env: &environment{}, - props: &properties{ - values: map[Property]interface{}{ - LocalWorkingIcon: "<#88C0D0>\u21e1 ", - }, - foreground: "#111111", - }, - } - assert.True(t, g.enabled()) - value := g.string() - assert.NotEmpty(t, value) -}