Added some status line info to the submodule list view

This commit is contained in:
Nick Lundin 2024-09-23 22:14:14 -05:00
parent a04ad24a60
commit 9b9e12b4b9
3 changed files with 105 additions and 4 deletions

View file

@ -54,6 +54,62 @@ func (self *SubmoduleCommands) GetConfigs(parentModule *models.SubmoduleConfig)
} }
} }
// TODO: unsure if this is the best way to go about this.
// TODO: might be better to do a single `git submodule foreach git status` and parse the Output
getSubmoduleHead := func(cmds *SubmoduleCommands, path string) (string, error) {
// git -C </path/to/submodule> symbolic-ref -q HEAD
// Output is empty in detached state
// Output if on a branch: refs/heads/main
cmdArgs := NewGitCmd("symbolic-ref").
Dir(path).
Arg("-q", "HEAD").
ToArgv()
return cmds.cmd.New(cmdArgs).RunWithOutput()
}
formatSubmoduleHead := func(head string, prefix string) string {
// refs/heads/main ---> main
if strings.HasPrefix(head, prefix) {
return head[len(prefix) : len(head)-1]
}
return head
}
getPorcelainStatus := func(cmds *SubmoduleCommands, path string) (int, int, int, error) {
cmdArgs := NewGitCmd("status").
Dir(path).
Arg("--porcelain").
ToArgv()
output, err := cmds.cmd.New(cmdArgs).RunWithOutput()
if err != nil {
return -1, -1, -1, err
}
lines := strings.Split(output, "\n")
stagedCount := 0
unstagedCount := 0
untrackedCount := 0
for _, line := range lines {
if len(line) == 0 {
continue
}
firstChar := line[0:1]
switch firstChar {
case " ":
unstagedCount++
case "?":
untrackedCount++
default:
stagedCount++
}
}
return stagedCount, unstagedCount, untrackedCount, nil
}
configs := []*models.SubmoduleConfig{} configs := []*models.SubmoduleConfig{}
lastConfigIdx := -1 lastConfigIdx := -1
for scanner.Scan() { for scanner.Scan() {
@ -70,6 +126,17 @@ func (self *SubmoduleCommands) GetConfigs(parentModule *models.SubmoduleConfig)
if lastConfigIdx != -1 { if lastConfigIdx != -1 {
if path, ok := firstMatch(line, `\s*path\s*=\s*(.*)\s*`); ok { if path, ok := firstMatch(line, `\s*path\s*=\s*(.*)\s*`); ok {
configs[lastConfigIdx].Path = path configs[lastConfigIdx].Path = path
head, err := getSubmoduleHead(self, path)
if err == nil {
formattedHead := formatSubmoduleHead(head, "refs/heads/")
configs[lastConfigIdx].Head = strings.TrimSpace(formattedHead)
}
stagedCount, unstagedCount, untrackedCount, err := getPorcelainStatus(self, path)
if err == nil {
configs[lastConfigIdx].NumStagedFiles = stagedCount
configs[lastConfigIdx].NumUnstagedChanges = unstagedCount
configs[lastConfigIdx].NumUntrackedChanges = untrackedCount
}
nestedConfigs, err := self.GetConfigs(configs[lastConfigIdx]) nestedConfigs, err := self.GetConfigs(configs[lastConfigIdx])
if err == nil { if err == nil {
configs = append(configs, nestedConfigs...) configs = append(configs, nestedConfigs...)

View file

@ -3,9 +3,13 @@ package models
import "path/filepath" import "path/filepath"
type SubmoduleConfig struct { type SubmoduleConfig struct {
Name string Name string
Path string Path string
Url string Url string
Head string
NumStagedFiles int
NumUnstagedChanges int
NumUntrackedChanges int
ParentModule *SubmoduleConfig // nil if top-level ParentModule *SubmoduleConfig // nil if top-level
} }

View file

@ -1,6 +1,8 @@
package presentation package presentation
import ( import (
"fmt"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo" "github.com/samber/lo"
@ -13,7 +15,11 @@ func GetSubmoduleListDisplayStrings(submodules []*models.SubmoduleConfig) [][]st
} }
func getSubmoduleDisplayStrings(s *models.SubmoduleConfig) []string { func getSubmoduleDisplayStrings(s *models.SubmoduleConfig) []string {
name := s.Name // Pad right with some spaces to the end of the HEAD so that it (hopefully) aligns well.
// Put the HEAD first because those are more likely to be similar lengths than the repo name.
name := fmt.Sprintf("%-20s %s", s.Head,
s.Name,
)
if s.ParentModule != nil { if s.ParentModule != nil {
indentation := "" indentation := ""
for p := s.ParentModule; p != nil; p = p.ParentModule { for p := s.ParentModule; p != nil; p = p.ParentModule {
@ -23,5 +29,29 @@ func getSubmoduleDisplayStrings(s *models.SubmoduleConfig) []string {
name = indentation + "- " + s.Name name = indentation + "- " + s.Name
} }
if s.NumStagedFiles != 0 {
name = fmt.Sprintf(
"%s +%d",
name,
s.NumStagedFiles,
)
}
if s.NumUnstagedChanges != 0 {
name = fmt.Sprintf(
"%s !%d",
name,
s.NumUnstagedChanges,
)
}
if s.NumUntrackedChanges != 0 {
name = fmt.Sprintf(
"%s ?%d ",
name,
s.NumUntrackedChanges,
)
}
return []string{theme.DefaultTextColor.Sprint(name)} return []string{theme.DefaultTextColor.Sprint(name)}
} }