|
| 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 | +} |
0 commit comments