Skip to content

Commit be4cf98

Browse files
committed
feat: support quick fetch repo status info
1 parent 8fc79c0 commit be4cf98

6 files changed

Lines changed: 155 additions & 9 deletions

File tree

101 KB
Loading

info_branch.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ func (b *BranchInfo) ParseName() *BranchInfo {
5959
return b
6060
}
6161

62+
// branch types
63+
const (
64+
BranchLocal = "local"
65+
BranchRemote = "remote"
66+
)
67+
6268
// BranchInfos for a git repo
6369
type BranchInfos struct {
6470
parsed bool
@@ -68,9 +74,9 @@ type BranchInfos struct {
6874
brLines []string
6975

7076
current *BranchInfo
71-
// local branches. key is branch name
77+
// local branches. key is short branch name, eg: dev
7278
locales map[string]*BranchInfo
73-
// remote branches. key is full branch name
79+
// remote branches. key is full branch name, eg: origin/dev
7480
remotes map[string]*BranchInfo
7581
}
7682

@@ -160,12 +166,13 @@ const (
160166
// Search branches by name.
161167
//
162168
// Usage:
163-
// Search("fea", BrSearchLocal)
164-
// Search("fea", BrSearchAll)
165-
// // search on remotes
166-
// Search("fea", BrSearchRemote)
169+
//
170+
// Search("fea", BrSearchLocal)
171+
// Search("fea", BrSearchAll)
172+
// // search on remotes
173+
// Search("fea", BrSearchRemote)
167174
// // search on remotes and remote name must be equals "origin"
168-
// Search("origin fea", BrSearchRemote)
175+
// Search("origin fea", BrSearchRemote)
169176
func (bs *BranchInfos) Search(name string, flag int) []*BranchInfo {
170177
var list []*BranchInfo
171178

info_status.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package gitw
2+
3+
import (
4+
"regexp"
5+
"strings"
6+
7+
"github.com/gookit/goutil/strutil"
8+
)
9+
10+
// StatusPattern string. eg: master...origin/master
11+
const StatusPattern = `^([\w-]+)...([\w-]+)/(\w[\w/-]+)$`
12+
13+
var statusRegex = regexp.MustCompile(StatusPattern)
14+
15+
// StatusInfo struct
16+
//
17+
// by run: git status -bs -u
18+
type StatusInfo struct {
19+
// Branch current branch name.
20+
Branch string
21+
// UpRemote current upstream remote name.
22+
UpRemote string
23+
// UpBranch current upstream remote branch name.
24+
UpBranch string
25+
26+
fileNum int
27+
28+
// Deleted files
29+
Deleted []string
30+
// Renamed files, contains RM(rename and modify) files
31+
Renamed []string
32+
// Modified files
33+
Modified []string
34+
// Unstacked new created files.
35+
Unstacked []string
36+
}
37+
38+
// NewStatusInfo from string.
39+
func NewStatusInfo(str string) *StatusInfo {
40+
si := &StatusInfo{}
41+
return si.FromString(str)
42+
}
43+
44+
// FromString parse and load info
45+
func (si *StatusInfo) FromString(str string) *StatusInfo {
46+
return si.FromLines(strings.Split(str, "\n"))
47+
}
48+
49+
// FromLines parse and load info
50+
func (si *StatusInfo) FromLines(lines []string) *StatusInfo {
51+
for _, line := range lines {
52+
line = strings.Trim(line, " \t")
53+
if len(line) == 0 {
54+
continue
55+
}
56+
57+
// files
58+
mark, value := strutil.MustCut(line, " ")
59+
switch mark {
60+
case "##":
61+
ss := statusRegex.FindStringSubmatch(value)
62+
if len(ss) > 1 {
63+
si.Branch, si.UpRemote, si.UpBranch = ss[1], ss[2], ss[3]
64+
}
65+
case "D":
66+
si.fileNum++
67+
si.Deleted = append(si.Deleted, value)
68+
case "R":
69+
si.fileNum++
70+
si.Renamed = append(si.Renamed, value)
71+
case "M":
72+
si.fileNum++
73+
si.Modified = append(si.Modified, value)
74+
case "RM": // rename and modify
75+
si.fileNum++
76+
si.Renamed = append(si.Renamed, value)
77+
case "??":
78+
si.fileNum++
79+
si.Unstacked = append(si.Unstacked, value)
80+
}
81+
}
82+
return si
83+
}
84+
85+
// FileNum in git status
86+
func (si *StatusInfo) FileNum() int {
87+
return si.fileNum
88+
}
89+
90+
// IsCleaned status in workspace
91+
func (si *StatusInfo) IsCleaned() bool {
92+
return si.fileNum == 0
93+
}

info_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,21 @@ func TestBranchInfo_parse_verbose(t *testing.T) {
167167
assert.True(t, rets[0].IsRemoted())
168168
assert.Eq(t, "origin", rets[0].Remote)
169169
}
170+
171+
func TestStatusInfo_FromLines(t *testing.T) {
172+
text := `
173+
## master...origin/fea/master
174+
RM app/Common/GitLocal/GitFlow.php -> app/Common/GitLocal/GitFactory.php
175+
M app/Common/GitLocal/GitHub.php
176+
?? app/Common/GitLocal/GitConst.php
177+
D tmp/delete-some.file
178+
`
179+
si := gitw.NewStatusInfo(text)
180+
181+
dump.P(si)
182+
assert.Eq(t, "master", si.Branch)
183+
assert.Eq(t, "origin", si.UpRemote)
184+
assert.Eq(t, "fea/master", si.UpBranch)
185+
assert.False(t, si.IsCleaned())
186+
assert.Gt(t, si.FileNum(), 2)
187+
}

repo.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ type Repo struct {
4040
// config
4141
cfg *RepoConfig
4242

43+
// status info
44+
statusInfo *StatusInfo
45+
4346
// branch infos for the repo
4447
branchInfos *BranchInfos
4548

@@ -320,6 +323,25 @@ func (r *Repo) LastCommitID() string {
320323
return lastCID
321324
}
322325

326+
// -------------------------------------------------
327+
// repo status
328+
// -------------------------------------------------
329+
330+
// StatusInfo get status info of the repo
331+
func (r *Repo) StatusInfo() *StatusInfo {
332+
if r.statusInfo == nil {
333+
r.statusInfo = &StatusInfo{}
334+
lines, err := r.gw.Status("-bs", "-u").OutputLines()
335+
if err != nil {
336+
r.setErr(err)
337+
return nil
338+
}
339+
340+
r.statusInfo.FromLines(lines)
341+
}
342+
return r.statusInfo
343+
}
344+
323345
// -------------------------------------------------
324346
// repo branch
325347
// -------------------------------------------------
@@ -431,8 +453,9 @@ func (r *Repo) RandomRemoteInfo(typ ...string) *RemoteInfo {
431453
// if typ is empty, will return random type info.
432454
//
433455
// Usage:
434-
// ri := RemoteInfo("origin")
435-
// ri = RemoteInfo("origin", "push")
456+
//
457+
// ri := RemoteInfo("origin")
458+
// ri = RemoteInfo("origin", "push")
436459
func (r *Repo) RemoteInfo(remote string, typ ...string) *RemoteInfo {
437460
riMp := r.RemoteInfos(remote)
438461
if len(riMp) == 0 {

repo_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ func TestMain(m *testing.M) {
1919
m.Run()
2020
}
2121

22+
func TestRepo_StatusInfo(t *testing.T) {
23+
si := repo.StatusInfo()
24+
dump.P(si)
25+
}
26+
2227
func TestRepo_RemoteInfos(t *testing.T) {
2328
rs := repo.AllRemoteInfos()
2429
dump.P(rs)

0 commit comments

Comments
 (0)