mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 20:36:03 +02:00
Added some status line info to the submodule list view
This commit is contained in:
parent
a04ad24a60
commit
9b9e12b4b9
3 changed files with 105 additions and 4 deletions
|
@ -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...)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue