diff --git a/pkg/commands/submodules.go b/pkg/commands/submodules.go index 5c369ab8e..659c2d2d8 100644 --- a/pkg/commands/submodules.go +++ b/pkg/commands/submodules.go @@ -83,13 +83,22 @@ func (c *GitCommand) SubmoduleUpdateAll() error { 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 { + if err := c.OSCommand.RunCommand("git submodule deinit --force %s", submodule.Path); err != nil { return err } - if err := c.OSCommand.RunCommand("git rm %s", submodule.Path); err != nil { + if err := c.OSCommand.RunCommand("git rm --force %s", submodule.Path); err != nil { return err } - return os.RemoveAll(filepath.Join(c.DotGitDir, "modules", submodule.Name)) + return os.RemoveAll(filepath.Join(c.DotGitDir, "modules", submodule.Path)) +} + +func (c *GitCommand) AddSubmodule(name string, path string, url string) error { + return c.OSCommand.RunCommand( + "git submodule add --force --name %s -- %s %s ", + c.OSCommand.Quote(name), + c.OSCommand.Quote(url), + c.OSCommand.Quote(path), + ) } diff --git a/pkg/gui/custom_commands.go b/pkg/gui/custom_commands.go index df148a7af..74a07e9d1 100644 --- a/pkg/gui/custom_commands.go +++ b/pkg/gui/custom_commands.go @@ -1,10 +1,8 @@ package gui import ( - "bytes" "log" "strings" - "text/template" "github.com/fatih/color" "github.com/jesseduffield/gocui" @@ -43,19 +41,7 @@ func (gui *Gui) resolveTemplate(templateStr string, promptResponses []string) (s PromptResponses: promptResponses, } - tmpl, err := template.New("template").Parse(templateStr) - if err != nil { - return "", err - } - - var buf bytes.Buffer - if err := tmpl.Execute(&buf, objects); err != nil { - return "", err - } - - cmdStr := buf.String() - - return cmdStr, nil + return utils.ResolveTemplate(templateStr, objects) } func (gui *Gui) handleCustomCommandKeybinding(customCommand CustomCommand) func() error { diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index fcdbbb2c1..7ee9cacee 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -1601,6 +1601,13 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Handler: gui.wrappedHandler(gui.handleResetSubmodule), Description: gui.Tr.SLocalize("submoduleStashAndReset"), }, + { + ViewName: "files", + Contexts: []string{SUBMODULES_CONTEXT_KEY}, + Key: gui.getKey("universal.new"), + Handler: gui.wrappedHandler(gui.handleAddSubmodule), + Description: gui.Tr.SLocalize("addSubmodule"), + }, } for _, viewName := range []string{"status", "branches", "files", "commits", "commitFiles", "stash", "menu"} { diff --git a/pkg/gui/submodules_panel.go b/pkg/gui/submodules_panel.go index 7089a9015..abc021123 100644 --- a/pkg/gui/submodules_panel.go +++ b/pkg/gui/submodules_panel.go @@ -3,6 +3,8 @@ package gui import ( "fmt" "os" + "path/filepath" + "strings" "github.com/fatih/color" "github.com/jesseduffield/lazygit/pkg/commands/models" @@ -71,10 +73,10 @@ func (gui *Gui) handleRemoveSubmodule() error { return gui.ask(askOpts{ title: gui.Tr.SLocalize("RemoveSubmodule"), - prompt: gui.Tr.SLocalize("RemoveSubmodulePrompt") + " '" + submodule.Name + "'?", + prompt: gui.Tr.SLocalizef("RemoveSubmodulePrompt", submodule.Name), handleConfirm: func() error { if err := gui.GitCommand.SubmoduleDelete(submodule); err != nil { - return err + return gui.surfaceError(err) } return gui.refreshSidePanels(refreshOptions{scope: []int{SUBMODULES, FILES}}) @@ -121,16 +123,30 @@ func (gui *Gui) resetSubmodule(submodule *models.SubmoduleConfig) error { 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 gui.refreshSidePanels(refreshOptions{scope: []int{submoduleS}}) -// }) -// }) -// } +func (gui *Gui) handleAddSubmodule() error { + return gui.prompt(gui.Tr.SLocalize("newSubmoduleUrl"), "", func(submoduleUrl string) error { + nameSuggestion := filepath.Base(strings.TrimSuffix(submoduleUrl, filepath.Ext(submoduleUrl))) + + return gui.prompt(gui.Tr.SLocalize("newSubmoduleName"), nameSuggestion, func(submoduleName string) error { + return gui.prompt(gui.Tr.SLocalize("newSubmodulePath"), submoduleName, func(submodulePath string) error { + return gui.WithWaitingStatus(gui.Tr.SLocalize("addingSubmoduleStatus"), func() error { + err := gui.GitCommand.AddSubmodule(submoduleName, submodulePath, submoduleUrl) + gui.handleCredentialsPopup(err) + + return gui.refreshSidePanels(refreshOptions{scope: []int{SUBMODULES}}) + }) + + // go func() { + // err := gui.GitCommand.AddSubmodule(submoduleName, submodulePath, submoduleUrl) + // gui.handleCredentialsPopup(err) + + // _ = gui.refreshSidePanels(refreshOptions{scope: []int{SUBMODULES}}) + // }() + return nil + }) + }) + }) +} // func (gui *Gui) handleEditsubmodule(g *gocui.Gui, v *gocui.View) error { // submodule := gui.getSelectedSubmodule() diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index b2282d5ca..25afb72b0 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -1211,10 +1211,25 @@ func addEnglish(i18nObject *i18n.Bundle) error { Other: "remove submodule", }, &i18n.Message{ ID: "RemoveSubmodulePrompt", - Other: "Are you sure you want to remove submodule", + Other: "Are you sure you want to remove submodule '%s' and its corresponding directory? This is irreversible.", }, &i18n.Message{ ID: "resettingSubmoduleStatus", Other: "resetting submodule", + }, &i18n.Message{ + ID: "newSubmoduleName", + Other: "new submodule name:", + }, &i18n.Message{ + ID: "newSubmoduleUrl", + Other: "new submodule URL:", + }, &i18n.Message{ + ID: "newSubmodulePath", + Other: "new submodule path:", + }, &i18n.Message{ + ID: "addSubmodule", + Other: "add new submodule", + }, &i18n.Message{ + ID: "addingSubmoduleStatus", + Other: "adding submodule", }, ) } diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index 77092dbe4..62240c3ea 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -1,6 +1,8 @@ package i18n import ( + "fmt" + "github.com/cloudfoundry/jibber_jabber" "github.com/nicksnyder/go-i18n/v2/i18n" "github.com/sirupsen/logrus" @@ -54,6 +56,16 @@ func (l *Localizer) TemplateLocalize(ID string, TemplateData map[string]interfac }) } +func (l *Localizer) SLocalizef(ID string, args ...interface{}) string { + str := l.Localize(&i18n.LocalizeConfig{ + DefaultMessage: &i18n.Message{ + ID: ID, + }, + }) + + return fmt.Sprintf(str, args...) +} + // GetLanguage returns the currently selected language, e.g 'en' func (l *Localizer) GetLanguage() string { return l.language diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 12c89e5da..b535431ee 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -1,6 +1,7 @@ package utils import ( + "bytes" "encoding/json" "fmt" "log" @@ -9,6 +10,7 @@ import ( "regexp" "strconv" "strings" + "text/template" "time" "github.com/fatih/color" @@ -343,3 +345,17 @@ func MustConvertToInt(s string) int { } return i } + +func ResolveTemplate(templateStr string, object interface{}) (string, error) { + tmpl, err := template.New("template").Parse(templateStr) + if err != nil { + return "", err + } + + var buf bytes.Buffer + if err := tmpl.Execute(&buf, object); err != nil { + return "", err + } + + return buf.String(), nil +}