mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-14 11:23:09 +02:00
140 lines
3.9 KiB
Go
140 lines
3.9 KiB
Go
package loaders
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
|
"github.com/jesseduffield/lazygit/pkg/common"
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
)
|
|
|
|
type FileLoaderConfig interface {
|
|
GetShowUntrackedFiles() string
|
|
}
|
|
|
|
type FileLoader struct {
|
|
*common.Common
|
|
cmd oscommands.ICmdObjBuilder
|
|
config FileLoaderConfig
|
|
gitConfig git_config.IGitConfig
|
|
getFileType func(string) string
|
|
}
|
|
|
|
func NewFileLoader(cmn *common.Common, cmd oscommands.ICmdObjBuilder, config FileLoaderConfig) *FileLoader {
|
|
return &FileLoader{
|
|
Common: cmn,
|
|
cmd: cmd,
|
|
getFileType: oscommands.FileType,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
type GetStatusFileOptions struct {
|
|
NoRenames bool
|
|
}
|
|
|
|
func (self *FileLoader) GetStatusFiles(opts GetStatusFileOptions) []*models.File {
|
|
// check if config wants us ignoring untracked files
|
|
untrackedFilesSetting := self.config.GetShowUntrackedFiles()
|
|
|
|
if untrackedFilesSetting == "" {
|
|
untrackedFilesSetting = "all"
|
|
}
|
|
untrackedFilesArg := fmt.Sprintf("--untracked-files=%s", untrackedFilesSetting)
|
|
|
|
statuses, err := self.GitStatus(GitStatusOptions{NoRenames: opts.NoRenames, UntrackedFilesArg: untrackedFilesArg})
|
|
if err != nil {
|
|
self.Log.Error(err)
|
|
}
|
|
files := []*models.File{}
|
|
|
|
for _, status := range statuses {
|
|
if strings.HasPrefix(status.StatusString, "warning") {
|
|
self.Log.Warningf("warning when calling git status: %s", status.StatusString)
|
|
continue
|
|
}
|
|
change := status.Change
|
|
stagedChange := change[0:1]
|
|
unstagedChange := change[1:2]
|
|
untracked := utils.IncludesString([]string{"??", "A ", "AM"}, change)
|
|
hasNoStagedChanges := utils.IncludesString([]string{" ", "U", "?"}, stagedChange)
|
|
hasMergeConflicts := utils.IncludesString([]string{"DD", "AA", "UU", "AU", "UA", "UD", "DU"}, change)
|
|
hasInlineMergeConflicts := utils.IncludesString([]string{"UU", "AA"}, change)
|
|
|
|
file := &models.File{
|
|
Name: status.Name,
|
|
PreviousName: status.PreviousName,
|
|
DisplayString: status.StatusString,
|
|
HasStagedChanges: !hasNoStagedChanges,
|
|
HasUnstagedChanges: unstagedChange != " ",
|
|
Tracked: !untracked,
|
|
Deleted: unstagedChange == "D" || stagedChange == "D",
|
|
Added: unstagedChange == "A" || untracked,
|
|
HasMergeConflicts: hasMergeConflicts,
|
|
HasInlineMergeConflicts: hasInlineMergeConflicts,
|
|
Type: self.getFileType(status.Name),
|
|
ShortStatus: change,
|
|
}
|
|
files = append(files, file)
|
|
}
|
|
|
|
return files
|
|
}
|
|
|
|
// GitStatus returns the file status of the repo
|
|
type GitStatusOptions struct {
|
|
NoRenames bool
|
|
UntrackedFilesArg string
|
|
}
|
|
|
|
type FileStatus struct {
|
|
StatusString string
|
|
Change string // ??, MM, AM, ...
|
|
Name string
|
|
PreviousName string
|
|
}
|
|
|
|
func (c *FileLoader) GitStatus(opts GitStatusOptions) ([]FileStatus, error) {
|
|
noRenamesFlag := ""
|
|
if opts.NoRenames {
|
|
noRenamesFlag = " --no-renames"
|
|
}
|
|
|
|
statusLines, err := c.cmd.New(fmt.Sprintf("git status %s --porcelain -z%s", opts.UntrackedFilesArg, noRenamesFlag)).DontLog().RunWithOutput()
|
|
if err != nil {
|
|
return []FileStatus{}, err
|
|
}
|
|
|
|
splitLines := strings.Split(statusLines, "\x00")
|
|
response := []FileStatus{}
|
|
|
|
for i := 0; i < len(splitLines); i++ {
|
|
original := splitLines[i]
|
|
|
|
if len(original) < 3 {
|
|
continue
|
|
}
|
|
|
|
status := FileStatus{
|
|
StatusString: original,
|
|
Change: original[:2],
|
|
Name: original[3:],
|
|
PreviousName: "",
|
|
}
|
|
|
|
if strings.HasPrefix(status.Change, "R") {
|
|
// if a line starts with 'R' then the next line is the original file.
|
|
status.PreviousName = strings.TrimSpace(splitLines[i+1])
|
|
status.StatusString = fmt.Sprintf("%s %s -> %s", status.Change, status.PreviousName, status.Name)
|
|
i++
|
|
}
|
|
|
|
response = append(response, status)
|
|
}
|
|
|
|
return response, nil
|
|
}
|