diff --git a/src/go.mod b/src/go.mod index dc9fb55d..053f8b14 100644 --- a/src/go.mod +++ b/src/go.mod @@ -25,6 +25,7 @@ require ( github.com/mitchellh/mapstructure v1.4.1 github.com/sergi/go-diff v1.2.0 // indirect github.com/shirou/gopsutil v3.21.5+incompatible + github.com/smartystreets/goconvey v1.6.4 // indirect github.com/stretchr/objx v0.3.0 // indirect github.com/stretchr/testify v1.7.0 github.com/tklauser/go-sysconf v0.3.6 // indirect @@ -33,6 +34,7 @@ require ( golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 golang.org/x/text v0.3.6 + gopkg.in/ini.v1 v1.62.0 howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect ) diff --git a/src/go.sum b/src/go.sum index 29a849f7..13cae7ac 100644 --- a/src/go.sum +++ b/src/go.sum @@ -49,6 +49,8 @@ github.com/gookit/goutil v0.3.13/go.mod h1:DdrxLZc3yakbuElOtTH8F2SWu3XhaJohgvKHS github.com/gookit/goutil v0.3.14 h1:ZEdZR+Vkvcjz0SSC0MpjtD+Kwlg/uagpiddh6L2ko+0= github.com/gookit/goutil v0.3.14/go.mod h1:YdGV0ObqRUlRq4/RzAQBHcd1Wzl/jKw7cppDBtD3q+U= github.com/gookit/ini/v2 v2.0.9/go.mod h1:qYxT/pBi+32lc0tps2dxKcgitv8g+47peszZi4NOEkM= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= @@ -59,6 +61,8 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -90,6 +94,10 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc= github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= @@ -122,6 +130,7 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 h1:D0iM1dTCbD5Dg1CbuvLC/v/agLc79efSj/L35Q3Vqhs= golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -149,12 +158,15 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/src/segment_git.go b/src/segment_git.go index 8f0fc42b..d6d6bf9f 100644 --- a/src/segment_git.go +++ b/src/segment_git.go @@ -5,17 +5,21 @@ import ( "fmt" "strconv" "strings" + + "gopkg.in/ini.v1" ) type gitRepo struct { - working *gitStatus - staging *gitStatus - ahead int - behind int - HEAD string - upstream string - stashCount int - gitFolder string + working *gitStatus + staging *gitStatus + ahead int + behind int + HEAD string + upstream string + stashCount int + gitWorkingFolder string // .git working folder, can be different of root if using worktree + isWorkTree bool + gitRootFolder string // .git root folder } type gitStatus struct { @@ -128,15 +132,23 @@ func (g *git) enabled() bool { } g.repo = &gitRepo{} if gitdir.isDir { - g.repo.gitFolder = gitdir.path + g.repo.gitWorkingFolder = gitdir.path + g.repo.gitRootFolder = gitdir.path return true } // handle worktree + g.repo.gitRootFolder = gitdir.path dirPointer := g.env.getFileContent(gitdir.path) dirPointer = strings.Trim(dirPointer, " \r\n") matches := findNamedRegexMatch(`^gitdir: (?P.*)$`, dirPointer) if matches != nil && matches["dir"] != "" { - g.repo.gitFolder = matches["dir"] + g.repo.gitWorkingFolder = matches["dir"] + // in worktrees, the path looks like this: gitdir: path/.git/worktrees/branch + // strips the last .git/worktrees part + // :ind+5 = index + /.git + ind := strings.LastIndex(g.repo.gitWorkingFolder, "/.git/worktrees") + g.repo.gitRootFolder = g.repo.gitWorkingFolder[:ind+5] + g.repo.isWorkTree = true return true } return false @@ -225,7 +237,7 @@ func (g *git) colorStatusString(prefix, status, color string) string { func (g *git) getUpstreamSymbol() string { upstream := replaceAllString("/.*", g.repo.upstream, "") - url := g.getGitCommandOutput("remote", "get-url", upstream) + url := g.getOriginURL(upstream) if strings.Contains(url, "github") { return g.props.getString(GithubIcon, "\uF408 ") } @@ -374,16 +386,16 @@ func (g *git) truncateBranch(branch string) string { } func (g *git) hasGitFile(file string) bool { - return g.env.hasFilesInDir(g.repo.gitFolder, file) + return g.env.hasFilesInDir(g.repo.gitWorkingFolder, file) } func (g *git) hasGitFolder(folder string) bool { - path := g.repo.gitFolder + "/" + folder + path := g.repo.gitWorkingFolder + "/" + folder return g.env.hasFolder(path) } func (g *git) getGitFileContents(file string) string { - path := g.repo.gitFolder + "/" + file + path := g.repo.gitWorkingFolder + "/" + file content := g.env.getFileContent(path) return strings.Trim(content, " \r\n") } @@ -457,3 +469,15 @@ func (g *git) parseGitStatusInfo(branchInfo string) map[string]string { var branchRegex = `^## (?P\S+?)(\.{3}(?P\S+?)( \[(?P(ahead (?P\d+)(, )?)?(behind (?P\d+))?(gone)?)])?)?$` return findNamedRegexMatch(branchRegex, branchInfo) } + +func (g *git) getOriginURL(upstream string) string { + cfg, err := ini.Load(g.repo.gitRootFolder + "/config") + if err != nil { + return g.getGitCommandOutput("remote", "get-url", upstream) + } + keyVal := cfg.Section("remote \"" + upstream + "\"").Key("url").String() + if keyVal == "" { + return g.getGitCommandOutput("remote", "get-url", upstream) + } + return keyVal +} diff --git a/src/segment_git_test.go b/src/segment_git_test.go index 8a404515..489c114a 100644 --- a/src/segment_git_test.go +++ b/src/segment_git_test.go @@ -33,7 +33,7 @@ func TestEnabledInWorkingDirectory(t *testing.T) { env: env, } assert.True(t, g.enabled()) - assert.Equal(t, fileInfo.path, g.repo.gitFolder) + assert.Equal(t, fileInfo.path, g.repo.gitWorkingFolder) } func TestEnabledInWorkingTree(t *testing.T) { @@ -50,7 +50,7 @@ func TestEnabledInWorkingTree(t *testing.T) { env: env, } assert.True(t, g.enabled()) - assert.Equal(t, "/dir/hello/burp/burp", g.repo.gitFolder) + assert.Equal(t, "/dir/hello/burp/burp", g.repo.gitWorkingFolder) } func TestGetGitOutputForCommand(t *testing.T) { @@ -120,7 +120,7 @@ func setupHEADContextEnv(context *detachedContext) *git { g := &git{ env: env, repo: &gitRepo{ - gitFolder: "", + gitWorkingFolder: "", }, } return g @@ -335,7 +335,7 @@ func TestGetStashContextZeroEntries(t *testing.T) { env.On("getFileContent", "/logs/refs/stash").Return(tc.StashContent) g := &git{ repo: &gitRepo{ - gitFolder: "", + gitWorkingFolder: "", }, env: env, }