1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-02 09:21:40 +02:00

add more submodule commands

This commit is contained in:
Jesse Duffield 2020-09-30 09:06:11 +10:00
parent 7b4a0f20b2
commit ea307c8d94
5 changed files with 131 additions and 57 deletions

View File

@ -3,6 +3,7 @@ package commands
import ( import (
"bufio" "bufio"
"os" "os"
"path/filepath"
"regexp" "regexp"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
@ -59,21 +60,36 @@ func (c *GitCommand) GetSubmoduleConfigs() ([]*models.SubmoduleConfig, error) {
return configs, nil return configs, nil
} }
func (c *GitCommand) SubmoduleStash(config *models.SubmoduleConfig) error { func (c *GitCommand) SubmoduleStash(submodule *models.SubmoduleConfig) error {
// if the path does not exist then it hasn't yet been initialized so we'll swallow the error // if the path does not exist then it hasn't yet been initialized so we'll swallow the error
// because the intention here is to have no dirty worktree state // because the intention here is to have no dirty worktree state
if _, err := os.Stat(config.Path); os.IsNotExist(err) { if _, err := os.Stat(submodule.Path); os.IsNotExist(err) {
c.Log.Infof("submodule path %s does not exist, returning", config.Path) c.Log.Infof("submodule path %s does not exist, returning", submodule.Path)
return nil return nil
} }
return c.OSCommand.RunCommand("git -C %s stash --include-untracked", config.Path) return c.OSCommand.RunCommand("git -C %s stash --include-untracked", submodule.Path)
} }
func (c *GitCommand) SubmoduleReset(config *models.SubmoduleConfig) error { func (c *GitCommand) SubmoduleReset(submodule *models.SubmoduleConfig) error {
return c.OSCommand.RunCommand("git submodule update --force %s", config.Name) return c.OSCommand.RunCommand("git submodule update --init --force %s", submodule.Name)
} }
func (c *GitCommand) SubmoduleUpdateAll() error { func (c *GitCommand) SubmoduleUpdateAll() error {
// not doing an --init here because the user probably doesn't want that
return c.OSCommand.RunCommand("git submodule update --force") return c.OSCommand.RunCommand("git submodule update --force")
} }
func (c *GitCommand) SubmoduleDelete(submodule *models.SubmoduleConfig) error {
// based on https://gist.github.com/myusuf3/7f645819ded92bda6677
if err := c.OSCommand.RunCommand("git submodule deinit %s", submodule.Name); err != nil {
return err
}
if err := c.OSCommand.RunCommand("git rm %s", submodule.Path); err != nil {
return err
}
return os.RemoveAll(filepath.Join(c.DotGitDir, "modules", submodule.Name))
}

View File

@ -23,24 +23,15 @@ func (gui *Gui) handleCreateDiscardMenu(g *gocui.Gui, v *gocui.View) error {
var menuItems []*menuItem var menuItems []*menuItem
submoduleConfigs := gui.State.Submodules submodules := gui.State.Submodules
if file.IsSubmodule(submoduleConfigs) { if file.IsSubmodule(submodules) {
submoduleConfig := file.SubmoduleConfig(submoduleConfigs) submodule := file.SubmoduleConfig(submodules)
menuItems = []*menuItem{ menuItems = []*menuItem{
{ {
displayString: gui.Tr.SLocalize("submoduleStashAndReset"), displayString: gui.Tr.SLocalize("submoduleStashAndReset"),
onPress: func() error { onPress: func() error {
if err := gui.GitCommand.UnStageFile(file.Name, file.Tracked); err != nil { return gui.resetSubmodule(submodule)
return gui.surfaceError(err)
}
if err := gui.GitCommand.SubmoduleStash(submoduleConfig); err != nil {
return gui.surfaceError(err)
}
if err := gui.GitCommand.SubmoduleReset(submoduleConfig); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{FILES}})
}, },
}, },
} }

View File

@ -1586,6 +1586,21 @@ 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.remove"),
Handler: gui.wrappedHandler(gui.handleRemoveSubmodule),
Description: gui.Tr.SLocalize("removeSubmodule"),
},
{
ViewName: "files",
Contexts: []string{SUBMODULES_CONTEXT_KEY},
Key: gui.getKey("u"),
Handler: gui.wrappedHandler(gui.handleResetSubmodule),
Description: gui.Tr.SLocalize("submoduleStashAndReset"),
},
} }
for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} { for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} {

View File

@ -25,6 +25,7 @@ func (gui *Gui) handleSubmoduleSelect() error {
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. // 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.
task = gui.createRenderStringTask( task = gui.createRenderStringTask(
fmt.Sprintf( fmt.Sprintf(
"Name: %s\nPath: %s\nUrl: %s\n", "Name: %s\nPath: %s\nUrl: %s\n",
@ -62,74 +63,113 @@ func (gui *Gui) enterSubmodule(submodule *models.SubmoduleConfig) error {
return gui.dispatchSwitchToRepo(submodule.Path) return gui.dispatchSwitchToRepo(submodule.Path)
} }
// func (gui *Gui) handleAddRemote(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleRemoveSubmodule() error {
// return gui.prompt(gui.Tr.SLocalize("newRemoteName"), "", func(remoteName string) error { submodule := gui.getSelectedSubmodule()
// return gui.prompt(gui.Tr.SLocalize("newRemoteUrl"), "", func(remoteUrl string) error { if submodule == nil {
// if err := gui.GitCommand.AddRemote(remoteName, remoteUrl); err != nil { return nil
}
return gui.ask(askOpts{
title: gui.Tr.SLocalize("RemoveSubmodule"),
prompt: gui.Tr.SLocalize("RemoveSubmodulePrompt") + " '" + submodule.Name + "'?",
handleConfirm: func() error {
if err := gui.GitCommand.SubmoduleDelete(submodule); err != nil {
return err
}
return gui.refreshSidePanels(refreshOptions{scope: []int{SUBMODULES, FILES}})
},
})
}
func (gui *Gui) handleResetSubmodule() error {
return gui.WithWaitingStatus(gui.Tr.SLocalize("resettingSubmoduleStatus"), func() error {
submodule := gui.getSelectedSubmodule()
if submodule == nil {
return nil
}
return gui.resetSubmodule(submodule)
})
}
func (gui *Gui) fileForSubmodule(submodule *models.SubmoduleConfig) *models.File {
for _, file := range gui.State.Files {
if file.IsSubmodule([]*models.SubmoduleConfig{submodule}) {
return file
}
}
return nil
}
func (gui *Gui) resetSubmodule(submodule *models.SubmoduleConfig) error {
file := gui.fileForSubmodule(submodule)
if file != nil {
if err := gui.GitCommand.UnStageFile(file.Name, file.Tracked); err != nil {
return gui.surfaceError(err)
}
}
if err := gui.GitCommand.SubmoduleStash(submodule); err != nil {
return gui.surfaceError(err)
}
if err := gui.GitCommand.SubmoduleReset(submodule); err != nil {
return gui.surfaceError(err)
}
return gui.refreshSidePanels(refreshOptions{mode: ASYNC, scope: []int{FILES, SUBMODULES}})
}
// func (gui *Gui) handleAddsubmodule(g *gocui.Gui, v *gocui.View) error {
// return gui.prompt(gui.Tr.SLocalize("newsubmoduleName"), "", func(submoduleName string) error {
// return gui.prompt(gui.Tr.SLocalize("newsubmoduleUrl"), "", func(submoduleUrl string) error {
// if err := gui.GitCommand.Addsubmodule(submoduleName, submoduleUrl); err != nil {
// return err // return err
// } // }
// return gui.refreshSidePanels(refreshOptions{scope: []int{REMOTES}}) // return gui.refreshSidePanels(refreshOptions{scope: []int{submoduleS}})
// }) // })
// }) // })
// } // }
// func (gui *Gui) handleRemoveRemote(g *gocui.Gui, v *gocui.View) error { // func (gui *Gui) handleEditsubmodule(g *gocui.Gui, v *gocui.View) error {
// remote := gui.getSelectedSubmodule() // submodule := gui.getSelectedSubmodule()
// if remote == nil { // if submodule == nil {
// return nil
// }
// return gui.ask(askOpts{
// title: gui.Tr.SLocalize("removeRemote"),
// prompt: gui.Tr.SLocalize("removeRemotePrompt") + " '" + remote.Name + "'?",
// handleConfirm: func() error {
// if err := gui.GitCommand.RemoveRemote(remote.Name); err != nil {
// return err
// }
// return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}})
// },
// })
// }
// func (gui *Gui) handleEditRemote(g *gocui.Gui, v *gocui.View) error {
// remote := gui.getSelectedSubmodule()
// if remote == nil {
// return nil // return nil
// } // }
// editNameMessage := gui.Tr.TemplateLocalize( // editNameMessage := gui.Tr.TemplateLocalize(
// "editRemoteName", // "editsubmoduleName",
// Teml{ // Teml{
// "remoteName": remote.Name, // "submoduleName": submodule.Name,
// }, // },
// ) // )
// return gui.prompt(editNameMessage, remote.Name, func(updatedRemoteName string) error { // return gui.prompt(editNameMessage, submodule.Name, func(updatedsubmoduleName string) error {
// if updatedRemoteName != remote.Name { // if updatedsubmoduleName != submodule.Name {
// if err := gui.GitCommand.RenameRemote(remote.Name, updatedRemoteName); err != nil { // if err := gui.GitCommand.Renamesubmodule(submodule.Name, updatedsubmoduleName); err != nil {
// return gui.surfaceError(err) // return gui.surfaceError(err)
// } // }
// } // }
// editUrlMessage := gui.Tr.TemplateLocalize( // editUrlMessage := gui.Tr.TemplateLocalize(
// "editRemoteUrl", // "editsubmoduleUrl",
// Teml{ // Teml{
// "remoteName": updatedRemoteName, // "submoduleName": updatedsubmoduleName,
// }, // },
// ) // )
// urls := remote.Urls // urls := submodule.Urls
// url := "" // url := ""
// if len(urls) > 0 { // if len(urls) > 0 {
// url = urls[0] // url = urls[0]
// } // }
// return gui.prompt(editUrlMessage, url, func(updatedRemoteUrl string) error { // return gui.prompt(editUrlMessage, url, func(updatedsubmoduleUrl string) error {
// if err := gui.GitCommand.UpdateRemoteUrl(updatedRemoteName, updatedRemoteUrl); err != nil { // if err := gui.GitCommand.UpdatesubmoduleUrl(updatedsubmoduleName, updatedsubmoduleUrl); err != nil {
// return gui.surfaceError(err) // return gui.surfaceError(err)
// } // }
// return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, REMOTES}}) // return gui.refreshSidePanels(refreshOptions{scope: []int{BRANCHES, submoduleS}})
// }) // })
// }) // })
// } // }

View File

@ -1203,6 +1203,18 @@ func addEnglish(i18nObject *i18n.Bundle) error {
}, &i18n.Message{ }, &i18n.Message{
ID: "copySubmoduleNameToClipboard", ID: "copySubmoduleNameToClipboard",
Other: "copy submodule name to clipboard", Other: "copy submodule name to clipboard",
}, &i18n.Message{
ID: "RemoveSubmodule",
Other: "Remove submodule",
}, &i18n.Message{
ID: "removeSubmodule",
Other: "remove submodule",
}, &i18n.Message{
ID: "RemoveSubmodulePrompt",
Other: "Are you sure you want to remove submodule",
}, &i18n.Message{
ID: "resettingSubmoduleStatus",
Other: "resetting submodule",
}, },
) )
} }