1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-02-09 13:47:11 +02:00

allow submodule init and show submodule diff with a prefix

This commit is contained in:
Jesse Duffield 2020-10-01 08:18:16 +10:00
parent f3be2b3e68
commit da3e00823f
12 changed files with 101 additions and 102 deletions

View File

@ -164,6 +164,8 @@ Default path for the config file:
toggleDragSelect-alt: 'V' toggleDragSelect-alt: 'V'
toggleSelectHunk: 'a' toggleSelectHunk: 'a'
pickBothHunks: 'b' pickBothHunks: 'b'
submodules:
init: 'i'
``` ```
## Platform Defaults ## Platform Defaults

View File

@ -35,7 +35,7 @@ func (c *GitCommand) UnstageAll() error {
// UnStageFile unstages a file // UnStageFile unstages a file
func (c *GitCommand) UnStageFile(fileName string, tracked bool) error { func (c *GitCommand) UnStageFile(fileName string, tracked bool) error {
command := "git rm --cached %s" command := "git rm --cached --force %s"
if tracked { if tracked {
command = "git reset HEAD %s" command = "git reset HEAD %s"
} }

View File

@ -123,5 +123,8 @@ func (c *GitCommand) SubmoduleUpdateUrl(name string, path string, newUrl string)
} }
return c.OSCommand.RunCommand("git submodule sync %s", path) return c.OSCommand.RunCommand("git submodule sync %s", path)
}
func (c *GitCommand) SubmoduleInit(path string) error {
return c.OSCommand.RunCommand("git submodule init %s", path)
} }

View File

@ -393,6 +393,8 @@ keybinding:
toggleDragSelect-alt: 'V' toggleDragSelect-alt: 'V'
toggleSelectHunk: 'a' toggleSelectHunk: 'a'
pickBothHunks: 'b' pickBothHunks: 'b'
submodules:
init: 'i'
`) `)
} }

View File

@ -446,17 +446,6 @@ func (gui *Gui) refreshStateFiles() error {
return nil return nil
} }
func (gui *Gui) refreshStateSubmoduleConfigs() error {
configs, err := gui.GitCommand.GetSubmoduleConfigs()
if err != nil {
return err
}
gui.State.Submodules = configs
return nil
}
func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handlePullFiles(g *gocui.Gui, v *gocui.View) error {
if gui.popupPanelFocused() { if gui.popupPanelFocused() {
return nil return nil

View File

@ -1560,13 +1560,6 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Modifier: gocui.ModNone, Modifier: gocui.ModNone,
Handler: gui.wrappedHandler(gui.onMenuPress), Handler: gui.wrappedHandler(gui.onMenuPress),
}, },
{
ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("universal.goInto"),
Handler: gui.wrappedHandler(gui.handleSubmoduleEnter),
Description: gui.Tr.SLocalize("enterSubmodule"),
},
{ {
ViewName: "files", ViewName: "files",
Key: gui.getKey("universal.nextTab"), Key: gui.getKey("universal.nextTab"),
@ -1586,19 +1579,26 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
Handler: gui.wrappedHandler(gui.handleCopySelectedSideContextItemToClipboard), Handler: gui.wrappedHandler(gui.handleCopySelectedSideContextItemToClipboard),
Description: gui.Tr.SLocalize("copySubmoduleNameToClipboard"), Description: gui.Tr.SLocalize("copySubmoduleNameToClipboard"),
}, },
{
ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("universal.goInto"),
Handler: gui.forSubmodule(gui.handleSubmoduleEnter),
Description: gui.Tr.SLocalize("enterSubmodule"),
},
{ {
ViewName: "files", ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY}, Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("universal.remove"), Key: gui.getKey("universal.remove"),
Handler: gui.wrappedHandler(gui.handleRemoveSubmodule), Handler: gui.forSubmodule(gui.handleRemoveSubmodule),
Description: gui.Tr.SLocalize("removeSubmodule"), Description: gui.Tr.SLocalize("removeSubmodule"),
}, },
{ {
ViewName: "files", ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY}, Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("u"), Key: gui.getKey("u"),
Handler: gui.wrappedHandler(gui.handleResetSubmodule), Handler: gui.forSubmodule(gui.handleResetSubmodule),
Description: gui.Tr.SLocalize("submoduleStashAndReset"), Description: gui.Tr.SLocalize("submoduleStashAndReset"),
}, },
{ {
@ -1612,9 +1612,16 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
ViewName: "files", ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY}, Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("universal.edit"), Key: gui.getKey("universal.edit"),
Handler: gui.wrappedHandler(gui.handleEditSubmoduleUrl), Handler: gui.forSubmodule(gui.handleEditSubmoduleUrl),
Description: gui.Tr.SLocalize("editSubmoduleUrl"), Description: gui.Tr.SLocalize("editSubmoduleUrl"),
}, },
{
ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("submodules.init"),
Handler: gui.forSubmodule(gui.handleSubmoduleInit),
Description: gui.Tr.SLocalize("initSubmodule"),
},
} }
for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} { for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} {

View File

@ -62,7 +62,8 @@ func (gui *Gui) createRenderStringWithoutScrollTask(str string) *renderStringWit
} }
type runCommandTask struct { type runCommandTask struct {
cmd *exec.Cmd cmd *exec.Cmd
prefix string
} }
func (t *runCommandTask) GetKind() int { func (t *runCommandTask) GetKind() int {
@ -73,8 +74,13 @@ func (gui *Gui) createRunCommandTask(cmd *exec.Cmd) *runCommandTask {
return &runCommandTask{cmd: cmd} return &runCommandTask{cmd: cmd}
} }
func (gui *Gui) createRunCommandTaskWithPrefix(cmd *exec.Cmd, prefix string) *runCommandTask {
return &runCommandTask{cmd: cmd, prefix: prefix}
}
type runPtyTask struct { type runPtyTask struct {
cmd *exec.Cmd cmd *exec.Cmd
prefix string
} }
func (t *runPtyTask) GetKind() int { func (t *runPtyTask) GetKind() int {
@ -85,6 +91,10 @@ func (gui *Gui) createRunPtyTask(cmd *exec.Cmd) *runPtyTask {
return &runPtyTask{cmd: cmd} return &runPtyTask{cmd: cmd}
} }
func (gui *Gui) createRunPtyTaskWithPrefix(cmd *exec.Cmd, prefix string) *runPtyTask {
return &runPtyTask{cmd: cmd, prefix: prefix}
}
type runFunctionTask struct { type runFunctionTask struct {
f func(chan struct{}) error f func(chan struct{}) error
} }
@ -113,11 +123,11 @@ func (gui *Gui) runTaskForView(viewName string, task updateTask) error {
case RUN_COMMAND: case RUN_COMMAND:
specificTask := task.(*runCommandTask) specificTask := task.(*runCommandTask)
return gui.newCmdTask(viewName, specificTask.cmd) return gui.newCmdTask(viewName, specificTask.cmd, specificTask.prefix)
case RUN_PTY: case RUN_PTY:
specificTask := task.(*runPtyTask) specificTask := task.(*runPtyTask)
return gui.newPtyTask(viewName, specificTask.cmd) return gui.newPtyTask(viewName, specificTask.cmd, specificTask.prefix)
} }
return nil return nil

View File

@ -30,13 +30,13 @@ func (gui *Gui) onResize() error {
// which is just an io.Reader. the pty package lets us wrap a command in a // which is just an io.Reader. the pty package lets us wrap a command in a
// pseudo-terminal meaning we'll get the behaviour we want from the underlying // pseudo-terminal meaning we'll get the behaviour we want from the underlying
// command. // command.
func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd) error { func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd, prefix string) error {
width, _ := gui.getMainView().Size() width, _ := gui.getMainView().Size()
pager := gui.GitCommand.GetPager(width) pager := gui.GitCommand.GetPager(width)
if pager == "" { if pager == "" {
// if we're not using a custom pager we don't need to use a pty // if we're not using a custom pager we don't need to use a pty
return gui.newCmdTask(viewName, cmd) return gui.newCmdTask(viewName, cmd, prefix)
} }
cmd.Env = append(cmd.Env, "GIT_PAGER="+pager) cmd.Env = append(cmd.Env, "GIT_PAGER="+pager)
@ -66,7 +66,7 @@ func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd) error {
return err return err
} }
if err := manager.NewTask(manager.NewCmdTask(ptmx, cmd, height+oy+10, onClose)); err != nil { if err := manager.NewTask(manager.NewCmdTask(ptmx, cmd, prefix, height+oy+10, onClose)); err != nil {
return err return err
} }

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
) )
@ -26,16 +27,21 @@ func (gui *Gui) handleSubmoduleSelect() error {
if submodule == nil { if submodule == nil {
task = gui.createRenderStringTask("No submodules") task = gui.createRenderStringTask("No submodules")
} else { } else {
// TODO: we want to display the path, name, url, and a diff. We really need to be able to pipe commands together. We can always pipe commands together and just not do it asynchronously, but what if it's an expensive diff to obtain? I think that makes the most sense now though. prefix := fmt.Sprintf(
"Name: %s\nPath: %s\nUrl: %s\n\n",
task = gui.createRenderStringTask( utils.ColoredString(submodule.Name, color.FgGreen),
fmt.Sprintf( utils.ColoredString(submodule.Path, color.FgYellow),
"Name: %s\nPath: %s\nUrl: %s\n", utils.ColoredString(submodule.Url, color.FgCyan),
utils.ColoredString(submodule.Name, color.FgGreen),
utils.ColoredString(submodule.Path, color.FgYellow),
utils.ColoredString(submodule.Url, color.FgCyan),
),
) )
file := gui.fileForSubmodule(submodule)
if file == nil {
task = gui.createRenderStringTask(prefix)
} else {
cmdStr := gui.GitCommand.WorktreeFileDiffCmdStr(file, false, !file.HasUnstagedChanges && file.HasStagedChanges)
cmd := gui.OSCommand.ExecutableFromString(cmdStr)
task = gui.createRunCommandTaskWithPrefix(cmd, prefix)
}
} }
return gui.refreshMainViews(refreshMainOpts{ return gui.refreshMainViews(refreshMainOpts{
@ -46,12 +52,18 @@ func (gui *Gui) handleSubmoduleSelect() error {
}) })
} }
func (gui *Gui) handleSubmoduleEnter() error { func (gui *Gui) refreshStateSubmoduleConfigs() error {
submodule := gui.getSelectedSubmodule() configs, err := gui.GitCommand.GetSubmoduleConfigs()
if submodule == nil { if err != nil {
return nil return err
} }
gui.State.Submodules = configs
return nil
}
func (gui *Gui) handleSubmoduleEnter(submodule *models.SubmoduleConfig) error {
return gui.enterSubmodule(submodule) return gui.enterSubmodule(submodule)
} }
@ -65,12 +77,7 @@ func (gui *Gui) enterSubmodule(submodule *models.SubmoduleConfig) error {
return gui.dispatchSwitchToRepo(submodule.Path) return gui.dispatchSwitchToRepo(submodule.Path)
} }
func (gui *Gui) handleRemoveSubmodule() error { func (gui *Gui) handleRemoveSubmodule(submodule *models.SubmoduleConfig) error {
submodule := gui.getSelectedSubmodule()
if submodule == nil {
return nil
}
return gui.ask(askOpts{ return gui.ask(askOpts{
title: gui.Tr.SLocalize("RemoveSubmodule"), title: gui.Tr.SLocalize("RemoveSubmodule"),
prompt: gui.Tr.SLocalizef("RemoveSubmodulePrompt", submodule.Name), prompt: gui.Tr.SLocalizef("RemoveSubmodulePrompt", submodule.Name),
@ -84,13 +91,8 @@ func (gui *Gui) handleRemoveSubmodule() error {
}) })
} }
func (gui *Gui) handleResetSubmodule() error { func (gui *Gui) handleResetSubmodule(submodule *models.SubmoduleConfig) error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("resettingSubmoduleStatus"), func() error { return gui.WithWaitingStatus(gui.Tr.SLocalize("resettingSubmoduleStatus"), func() error {
submodule := gui.getSelectedSubmodule()
if submodule == nil {
return nil
}
return gui.resetSubmodule(submodule) return gui.resetSubmodule(submodule)
}) })
} }
@ -140,12 +142,7 @@ func (gui *Gui) handleAddSubmodule() error {
}) })
} }
func (gui *Gui) handleEditSubmoduleUrl() error { func (gui *Gui) handleEditSubmoduleUrl(submodule *models.SubmoduleConfig) error {
submodule := gui.getSelectedSubmodule()
if submodule == nil {
return nil
}
return gui.prompt(gui.Tr.SLocalizef("updateSubmoduleUrl", submodule.Name), submodule.Url, func(newUrl string) error { return gui.prompt(gui.Tr.SLocalizef("updateSubmoduleUrl", submodule.Name), submodule.Url, func(newUrl string) error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("updatingSubmoduleUrlStatus"), func() error { return gui.WithWaitingStatus(gui.Tr.SLocalize("updatingSubmoduleUrlStatus"), func() error {
err := gui.GitCommand.SubmoduleUpdateUrl(submodule.Name, submodule.Path, newUrl) err := gui.GitCommand.SubmoduleUpdateUrl(submodule.Name, submodule.Path, newUrl)
@ -156,44 +153,24 @@ func (gui *Gui) handleEditSubmoduleUrl() error {
}) })
} }
// func (gui *Gui) handleEditsubmodule(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSubmoduleInit(submodule *models.SubmoduleConfig) error {
// submodule := gui.getSelectedSubmodule() return gui.WithWaitingStatus(gui.Tr.SLocalize("initializingSubmoduleStatus"), func() error {
// if submodule == nil { err := gui.GitCommand.SubmoduleInit(submodule.Path)
// return nil gui.handleCredentialsPopup(err)
// }
// editNameMessage := gui.Tr.TemplateLocalize( return gui.refreshSidePanels(refreshOptions{scope: []int{SUBMODULES}})
// "editsubmoduleName", })
// Teml{ }
// "submoduleName": submodule.Name,
// },
// )
// return gui.prompt(editNameMessage, submodule.Name, func(updatedsubmoduleName string) error { func (gui *Gui) forSubmodule(callback func(*models.SubmoduleConfig) error) func(g *gocui.Gui, v *gocui.View) error {
// if updatedsubmoduleName != submodule.Name { return gui.wrappedHandler(
// if err := gui.GitCommand.Renamesubmodule(submodule.Name, updatedsubmoduleName); err != nil { func() error {
// return gui.surfaceError(err) submodule := gui.getSelectedSubmodule()
// } if submodule == nil {
// } return nil
}
// editUrlMessage := gui.Tr.TemplateLocalize( return callback(submodule)
// "editsubmoduleUrl", },
// Teml{ )
// "submoduleName": updatedsubmoduleName, }
// },
// )
// urls := submodule.Urls
// url := ""
// if len(urls) > 0 {
// url = urls[0]
// }
// return gui.prompt(editUrlMessage, url, func(updatedsubmoduleUrl string) error {
// if err := gui.GitCommand.UpdatesubmoduleUrl(updatedsubmoduleName, updatedsubmoduleUrl); err != nil {
// return gui.surfaceError(err)
// }
// return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, submoduleS}})
// })
// })
// }

View File

@ -8,7 +8,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/tasks"
) )
func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd) error { func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd, prefix string) error {
gui.Log.WithField( gui.Log.WithField(
"command", "command",
strings.Join(cmd.Args, " "), strings.Join(cmd.Args, " "),
@ -34,7 +34,7 @@ func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd) error {
return err return err
} }
if err := manager.NewTask(manager.NewCmdTask(r, cmd, height+oy+10, nil)); err != nil { if err := manager.NewTask(manager.NewCmdTask(r, cmd, prefix, height+oy+10, nil)); err != nil {
return err return err
} }

View File

@ -1239,6 +1239,12 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{ }, &i18n.Message{
ID: "editSubmoduleUrl", ID: "editSubmoduleUrl",
Other: "update submodule URL", Other: "update submodule URL",
}, &i18n.Message{
ID: "initializingSubmoduleStatus",
Other: "initializing submodule",
}, &i18n.Message{
ID: "initSubmodule",
Other: "initialize submodule",
}, },
) )
} }

View File

@ -46,7 +46,7 @@ func (m *ViewBufferManager) ReadLines(n int) {
}() }()
} }
func (m *ViewBufferManager) NewCmdTask(r io.Reader, cmd *exec.Cmd, linesToRead int, onDone func()) func(chan struct{}) error { func (m *ViewBufferManager) NewCmdTask(r io.Reader, cmd *exec.Cmd, prefix string, linesToRead int, onDone func()) func(chan struct{}) error {
return func(stop chan struct{}) error { return func(stop chan struct{}) error {
go func() { go func() {
<-stop <-stop
@ -99,6 +99,9 @@ func (m *ViewBufferManager) NewCmdTask(r io.Reader, cmd *exec.Cmd, linesToRead i
loadingMutex.Lock() loadingMutex.Lock()
if !loaded { if !loaded {
m.beforeStart() m.beforeStart()
if prefix != "" {
_, _ = m.writer.Write([]byte(prefix))
}
loaded = true loaded = true
} }
loadingMutex.Unlock() loadingMutex.Unlock()