From ca437a65046d5af0c90c337b125af4538e625502 Mon Sep 17 00:00:00 2001 From: Jesse Duffield Date: Mon, 28 Sep 2020 08:21:53 +1000 Subject: [PATCH] support submodules --- pkg/commands/file.go | 1 + pkg/commands/git.go | 46 ++++++++++++++++++++++++--- pkg/gui/diffing.go | 2 +- pkg/gui/discard_changes_menu_panel.go | 5 +++ pkg/gui/presentation/files.go | 6 ++++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/pkg/commands/file.go b/pkg/commands/file.go index 774e47fd7..750b4e4f8 100644 --- a/pkg/commands/file.go +++ b/pkg/commands/file.go @@ -19,6 +19,7 @@ type File struct { DisplayString string Type string // one of 'file', 'directory', and 'other' ShortStatus string // e.g. 'AD', ' A', 'M ', '??' + IsSubmodule bool } const RENAME_SEPARATOR = " -> " diff --git a/pkg/commands/git.go b/pkg/commands/git.go index 1c27b8642..465552b48 100644 --- a/pkg/commands/git.go +++ b/pkg/commands/git.go @@ -1,6 +1,7 @@ package commands import ( + "bufio" "fmt" "io/ioutil" "os" @@ -271,6 +272,32 @@ func (c *GitCommand) GetConfigValue(key string) string { return strings.TrimSpace(output) } +func (c *GitCommand) GetSubmoduleNames() ([]string, error) { + file, err := os.Open(".gitmodules") + if err != nil { + if err == os.ErrNotExist { + return nil, nil + } + return nil, err + } + + submoduleNames := []string{} + + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + line := scanner.Text() + re := regexp.MustCompile(`\[submodule "(.*)"\]`) + matches := re.FindStringSubmatch(line) + + if len(matches) > 0 { + submoduleNames = append(submoduleNames, matches[1]) + } + } + + return submoduleNames, nil +} + func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*File { // check if config wants us ignoring untracked files untrackedFilesSetting := c.GetConfigValue("status.showUntrackedFiles") @@ -287,6 +314,11 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*File { statusStrings := utils.SplitLines(statusOutput) files := []*File{} + submoduleNames, err := c.GetSubmoduleNames() + if err != nil { + c.Log.Error(err) + } + for _, statusString := range statusStrings { if strings.HasPrefix(statusString, "warning") { c.Log.Warningf("warning when calling git status: %s", statusString) @@ -300,6 +332,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*File { hasNoStagedChanges := utils.IncludesString([]string{" ", "U", "?"}, stagedChange) hasMergeConflicts := utils.IncludesString([]string{"DD", "AA", "UU", "AU", "UA", "UD", "DU"}, change) hasInlineMergeConflicts := utils.IncludesString([]string{"UU", "AA"}, change) + isSubmodule := utils.IncludesString(submoduleNames, filename) file := &File{ Name: filename, @@ -312,6 +345,7 @@ func (c *GitCommand) GetStatusFiles(opts GetStatusFileOptions) []*File { HasInlineMergeConflicts: hasInlineMergeConflicts, Type: c.OSCommand.FileType(filename), ShortStatus: change, + IsSubmodule: isSubmodule, } files = append(files, file) } @@ -718,7 +752,11 @@ func (c *GitCommand) DiscardAllFileChanges(file *File) error { // if the file isn't tracked, we assume you want to delete it quotedFileName := c.OSCommand.Quote(file.Name) - if file.HasStagedChanges || file.HasMergeConflicts { + if file.IsSubmodule { + if err := c.OSCommand.RunCommand(fmt.Sprintf("git submodule update --checkout --force --init %s", quotedFileName)); err != nil { + return err + } + } else if file.HasStagedChanges || file.HasMergeConflicts { if err := c.OSCommand.RunCommand("git reset -- %s", quotedFileName); err != nil { return err } @@ -828,7 +866,7 @@ func (c *GitCommand) WorktreeFileDiffCmdStr(file *File, plain bool, cached bool) colorArg = "never" } - return fmt.Sprintf("git diff --no-ext-diff --color=%s %s %s %s", colorArg, cachedArg, trackedArg, fileName) + return fmt.Sprintf("git diff --submodule --no-ext-diff --color=%s %s %s %s", colorArg, cachedArg, trackedArg, fileName) } func (c *GitCommand) ApplyPatch(patch string, flags ...string) error { @@ -1108,7 +1146,7 @@ func (c *GitCommand) GetFilesInDiff(from string, to string, reverse bool, patchM reverseFlag = " -R " } - filenames, err := c.OSCommand.RunCommandWithOutput("git diff --no-ext-diff --name-status %s %s %s", reverseFlag, from, to) + filenames, err := c.OSCommand.RunCommandWithOutput("git diff --submodule --no-ext-diff --name-status %s %s %s", reverseFlag, from, to) if err != nil { return nil, err } @@ -1161,7 +1199,7 @@ func (c *GitCommand) ShowFileDiffCmdStr(from string, to string, reverse bool, fi reverseFlag = " -R " } - return fmt.Sprintf("git diff --no-ext-diff --no-renames --color=%s %s %s %s -- %s", colorArg, from, to, reverseFlag, fileName) + return fmt.Sprintf("git diff --submodule --no-ext-diff --no-renames --color=%s %s %s %s -- %s", colorArg, from, to, reverseFlag, fileName) } // CheckoutFile checks out the file for the given commit diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go index a02c3d337..7da33dee0 100644 --- a/pkg/gui/diffing.go +++ b/pkg/gui/diffing.go @@ -14,7 +14,7 @@ func (gui *Gui) exitDiffMode() error { func (gui *Gui) renderDiff() error { cmd := gui.OSCommand.ExecutableFromString( - fmt.Sprintf("git diff --no-ext-diff --color %s", gui.diffStr()), + fmt.Sprintf("git diff --submodule --no-ext-diff --color %s", gui.diffStr()), ) task := gui.createRunPtyTask(cmd) diff --git a/pkg/gui/discard_changes_menu_panel.go b/pkg/gui/discard_changes_menu_panel.go index fa06c804b..f8a0f1df2 100644 --- a/pkg/gui/discard_changes_menu_panel.go +++ b/pkg/gui/discard_changes_menu_panel.go @@ -10,6 +10,11 @@ func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error { return nil } + if file.IsSubmodule { + // git submodule foreach '[[ "$name" == "renderers/chartify" ]] && git stash --include-untracked' + // git submodule update --force renderers/chartify + } + menuItems := []*menuItem{ { displayString: gui.Tr.SLocalize("discardAllChanges"), diff --git a/pkg/gui/presentation/files.go b/pkg/gui/presentation/files.go index a16abdce6..6493e1024 100644 --- a/pkg/gui/presentation/files.go +++ b/pkg/gui/presentation/files.go @@ -4,6 +4,7 @@ import ( "github.com/fatih/color" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/theme" + "github.com/jesseduffield/lazygit/pkg/utils" ) func GetFileListDisplayStrings(files []*commands.File, diffName string) [][]string { @@ -53,5 +54,10 @@ func getFileDisplayStrings(f *commands.File, diffed bool) []string { output := firstCharCl.Sprint(firstChar) output += secondCharCl.Sprint(secondChar) output += restColor.Sprintf(" %s", f.Name) + + if f.IsSubmodule { + output += utils.ColoredString(" (submodule)", theme.DefaultTextColor) + } + return []string{output} }