1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-12 11:15:00 +02:00
lazygit/pkg/commands/submodules.go

187 lines
5.2 KiB
Go
Raw Normal View History

2020-09-28 01:14:32 +02:00
package commands
import (
"bufio"
2021-12-07 12:59:36 +02:00
"fmt"
2020-09-28 01:14:32 +02:00
"os"
2020-09-30 01:06:11 +02:00
"path/filepath"
2020-09-28 01:14:32 +02:00
"regexp"
"strings"
2020-09-29 10:45:00 +02:00
"github.com/jesseduffield/lazygit/pkg/commands/models"
2021-12-07 12:59:36 +02:00
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
2022-01-02 01:34:33 +02:00
"github.com/jesseduffield/lazygit/pkg/common"
2020-09-28 01:14:32 +02:00
)
// .gitmodules looks like this:
// [submodule "mysubmodule"]
// path = blah/mysubmodule
// url = git@github.com:subbo.git
2022-01-02 01:34:33 +02:00
type SubmoduleCommands struct {
*common.Common
cmd oscommands.ICmdObjBuilder
dotGitDir string
}
func NewSubmoduleCommands(common *common.Common, cmd oscommands.ICmdObjBuilder, dotGitDir string) *SubmoduleCommands {
return &SubmoduleCommands{
Common: common,
cmd: cmd,
dotGitDir: dotGitDir,
}
}
func (self *SubmoduleCommands) GetConfigs() ([]*models.SubmoduleConfig, error) {
2020-09-28 01:14:32 +02:00
file, err := os.Open(".gitmodules")
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
firstMatch := func(str string, regex string) (string, bool) {
re := regexp.MustCompile(regex)
matches := re.FindStringSubmatch(str)
if len(matches) > 0 {
return matches[1], true
} else {
return "", false
}
}
2020-09-29 10:45:00 +02:00
configs := []*models.SubmoduleConfig{}
2020-09-28 01:14:32 +02:00
for scanner.Scan() {
line := scanner.Text()
if name, ok := firstMatch(line, `\[submodule "(.*)"\]`); ok {
2020-09-29 10:45:00 +02:00
configs = append(configs, &models.SubmoduleConfig{Name: name})
2020-09-28 01:14:32 +02:00
continue
}
if len(configs) > 0 {
lastConfig := configs[len(configs)-1]
if path, ok := firstMatch(line, `\s*path\s*=\s*(.*)\s*`); ok {
lastConfig.Path = path
} else if url, ok := firstMatch(line, `\s*url\s*=\s*(.*)\s*`); ok {
lastConfig.Url = url
}
}
}
return configs, nil
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Stash(submodule *models.SubmoduleConfig) error {
2020-09-29 00:47:14 +02:00
// 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
2020-09-30 01:06:11 +02:00
if _, err := os.Stat(submodule.Path); os.IsNotExist(err) {
2022-01-02 01:34:33 +02:00
self.Log.Infof("submodule path %s does not exist, returning", submodule.Path)
2020-09-29 00:47:14 +02:00
return nil
}
2022-01-02 01:34:33 +02:00
return self.cmd.New("git -C " + self.cmd.Quote(submodule.Path) + " stash --include-untracked").Run()
2020-09-28 01:14:32 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Reset(submodule *models.SubmoduleConfig) error {
return self.cmd.New("git submodule update --init --force -- " + self.cmd.Quote(submodule.Path)).Run()
2020-09-28 01:14:32 +02:00
}
2020-09-29 00:47:14 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) UpdateAll() error {
2020-09-30 01:06:11 +02:00
// not doing an --init here because the user probably doesn't want that
2022-01-02 01:34:33 +02:00
return self.cmd.New("git submodule update --force").Run()
2020-09-29 00:47:14 +02:00
}
2020-09-30 01:06:11 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Delete(submodule *models.SubmoduleConfig) error {
2020-09-30 01:06:11 +02:00
// based on https://gist.github.com/myusuf3/7f645819ded92bda6677
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git submodule deinit --force -- " + self.cmd.Quote(submodule.Path)).Run(); err != nil {
if strings.Contains(err.Error(), "did not match any file(s) known to git") {
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git config --file .gitmodules --remove-section submodule." + self.cmd.Quote(submodule.Name)).Run(); err != nil {
return err
}
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git config --remove-section submodule." + self.cmd.Quote(submodule.Name)).Run(); err != nil {
return err
}
// if there's an error here about it not existing then we'll just continue to do `git rm`
} else {
return err
}
2020-09-30 01:06:11 +02:00
}
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git rm --force -r " + submodule.Path).Run(); err != nil {
2020-10-01 01:04:09 +02:00
// if the directory isn't there then that's fine
2022-01-02 01:34:33 +02:00
self.Log.Error(err)
2020-09-30 01:06:11 +02:00
}
2022-01-02 01:34:33 +02:00
return os.RemoveAll(filepath.Join(self.dotGitDir, "modules", submodule.Path))
2020-09-30 13:12:03 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Add(name string, path string, url string) error {
return self.cmd.
2021-12-29 05:33:38 +02:00
New(
2021-12-07 12:59:36 +02:00
fmt.Sprintf(
"git submodule add --force --name %s -- %s %s ",
2022-01-02 01:34:33 +02:00
self.cmd.Quote(name),
self.cmd.Quote(url),
self.cmd.Quote(path),
2021-12-29 05:33:38 +02:00
)).
Run()
2020-09-30 01:06:11 +02:00
}
2020-09-30 14:05:34 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) UpdateUrl(name string, path string, newUrl string) error {
2020-09-30 23:19:53 +02:00
// the set-url command is only for later git versions so we're doing it manually here
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git config --file .gitmodules submodule." + self.cmd.Quote(name) + ".url " + self.cmd.Quote(newUrl)).Run(); err != nil {
2020-09-30 23:19:53 +02:00
return err
}
2022-01-02 01:34:33 +02:00
if err := self.cmd.New("git submodule sync -- " + self.cmd.Quote(path)).Run(); err != nil {
2020-10-01 14:13:32 +02:00
return err
}
return nil
}
2020-09-30 23:19:53 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Init(path string) error {
return self.cmd.New("git submodule init -- " + self.cmd.Quote(path)).Run()
2020-09-30 14:05:34 +02:00
}
2020-10-01 01:04:09 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) Update(path string) error {
return self.cmd.New("git submodule update --init -- " + self.cmd.Quote(path)).Run()
2020-10-01 01:04:09 +02:00
}
2020-10-01 14:13:32 +02:00
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) BulkInitCmdObj() oscommands.ICmdObj {
return self.cmd.New("git submodule init")
2020-10-01 14:13:32 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) BulkUpdateCmdObj() oscommands.ICmdObj {
return self.cmd.New("git submodule update")
2020-10-01 14:13:32 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) ForceBulkUpdateCmdObj() oscommands.ICmdObj {
return self.cmd.New("git submodule update --force")
2020-10-01 14:13:32 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) BulkDeinitCmdObj() oscommands.ICmdObj {
return self.cmd.New("git submodule deinit --all --force")
2020-10-01 14:13:32 +02:00
}
2022-01-02 01:34:33 +02:00
func (self *SubmoduleCommands) ResetSubmodules(submodules []*models.SubmoduleConfig) error {
2020-10-01 14:13:32 +02:00
for _, submodule := range submodules {
2022-01-02 01:34:33 +02:00
if err := self.Stash(submodule); err != nil {
2020-10-01 14:13:32 +02:00
return err
}
}
2022-01-02 01:34:33 +02:00
return self.UpdateAll()
2020-10-01 14:13:32 +02:00
}