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:
parent
7b4a0f20b2
commit
ea307c8d94
@ -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))
|
||||||
|
}
|
||||||
|
@ -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}})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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"} {
|
||||||
|
@ -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}})
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
|
@ -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",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user